diff --git a/common/changes/@rushstack/webpack5-module-minifier-plugin/user-thelarkinn-webpack5-compress-async-imports_2024-03-20-22-01.json b/common/changes/@rushstack/webpack5-module-minifier-plugin/user-thelarkinn-webpack5-compress-async-imports_2024-03-20-22-01.json new file mode 100644 index 0000000000..5d7cd5ef19 --- /dev/null +++ b/common/changes/@rushstack/webpack5-module-minifier-plugin/user-thelarkinn-webpack5-compress-async-imports_2024-03-20-22-01.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/webpack5-module-minifier-plugin", + "comment": "Port compressAsyncImports feature into current plugin from the webpack4 module minifier plugin.", + "type": "minor" + } + ], + "packageName": "@rushstack/webpack5-module-minifier-plugin" +} \ No newline at end of file diff --git a/common/reviews/api/webpack5-module-minifier-plugin.api.md b/common/reviews/api/webpack5-module-minifier-plugin.api.md index 825f134b3b..7ae5dfe8b0 100644 --- a/common/reviews/api/webpack5-module-minifier-plugin.api.md +++ b/common/reviews/api/webpack5-module-minifier-plugin.api.md @@ -74,6 +74,7 @@ export interface IModuleMinifierPluginHooks { // @public export interface IModuleMinifierPluginOptions { + compressAsyncImports?: boolean; minifier: IModuleMinifier; sourceMap?: boolean; } diff --git a/webpack/webpack5-module-minifier-plugin/src/AsyncImportCompressionPlugin.ts b/webpack/webpack5-module-minifier-plugin/src/AsyncImportCompressionPlugin.ts new file mode 100644 index 0000000000..eb05b6700e --- /dev/null +++ b/webpack/webpack5-module-minifier-plugin/src/AsyncImportCompressionPlugin.ts @@ -0,0 +1,307 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import type { + Chunk, + Compilation, + Compiler, + Module, + ModuleGraph, + WebpackPluginInstance, + sources +} from 'webpack'; + +import { Template, dependencies } from 'webpack'; + +import type { IModuleMinifierPluginHooks } from './ModuleMinifierPlugin.types'; +import { STAGE_AFTER } from './Constants'; +import { processModuleDependenciesRecursive } from './processModuleDependenciesRecursive'; + +type ChunkGroup = Compilation['chunkGroups'][0]; +type DependencyTemplateContext = Parameters[1]; + +interface IAsyncImportMetadata { + chunkCount: number; + chunkIds: number[]; + count: number; + index: number; +} + +interface ILocalImportMetadata { + meta: IAsyncImportMetadata; + module: Module; +} + +interface IConcatenatedModule extends Module { + modules: Module[]; +} + +interface IAttributes { + [x: string]: unknown; +} + +interface IImportDependencyTemplate { + apply( + dependency: WebpackImportDependency, + source: sources.ReplaceSource, + templateContext: DependencyTemplateContext + ): void; +} + +declare class WebpackImportDependency extends dependencies.ModuleDependency { + public range: [number, number]; + // eslint-disable-next-line @rushstack/no-new-null + public referencedExports?: string[][] | null; + public assertions?: IAttributes; + public get type(): 'import()'; + public get category(): 'esm'; +} + +const PLUGIN_NAME: 'AsyncImportCompressionPlugin' = 'AsyncImportCompressionPlugin'; +const ASYNC_IMPORT_PREFIX: '__IMPORT_ASYNC' = '__IMPORT_ASYNC'; +const ASYNC_IMPORT_REGEX: RegExp = /__IMPORT_ASYNC[^\)]+/g; + +function getImportTypeExpression(module: Module, originModule: Module, moduleGraph: ModuleGraph): string { + const strict: boolean = !!originModule.buildMeta?.strictHarmonyModule; + const exportsType: string | undefined = module.getExportsType(moduleGraph, strict); + // Logic translated from: + // https://github.com/webpack/webpack/blob/60daca54105f89eee45e118fd0bbc820730724ee/lib/RuntimeTemplate.js#L566-L586 + switch (exportsType) { + case 'namespace': + return ''; + case 'default-with-named': + return ',3'; + case 'default-only': + return ',1'; + // case 'dynamic': + default: + return ',7'; + } +} + +function getImportDependency(compilation: Compilation): typeof WebpackImportDependency { + for (const constructor of compilation.dependencyFactories.keys()) { + if (constructor.name === 'ImportDependency') { + return constructor as typeof WebpackImportDependency; + } + } + + throw new Error('ImportDependency not found'); +} + +export class AsyncImportCompressionPlugin implements WebpackPluginInstance { + private readonly _minifierHooks: IModuleMinifierPluginHooks; + + public constructor(minifierHooks: IModuleMinifierPluginHooks) { + this._minifierHooks = minifierHooks; + } + + public apply(compiler: Compiler): void { + const asyncImportMap: Map> = new Map(); + const asyncImportGroups: Map = new Map(); + let rankedImportGroups: IAsyncImportMetadata[] | undefined; + const { WebpackError, RuntimeModule, RuntimeGlobals } = compiler.webpack; + class CompressedAsyncImportRuntimeModule extends RuntimeModule { + public constructor() { + super('compressed async import'); + } + + public generate(): string { + const requireFn: string = RuntimeGlobals.require; + return Template.asString([ + `var asyncImportChunkGroups = [`, + rankedImportGroups + ? rankedImportGroups.map((x) => Template.indent(JSON.stringify(x.chunkIds))).join(',\n') + : '', + `];`, + `${requireFn}.ee = function (groupOrId, moduleId, importType) {`, + Template.indent([ + `return Promise.all((Array.isArray(groupOrId) ? groupOrId : asyncImportChunkGroups[groupOrId]).map(function (x) { return ${requireFn}.e(x); }))`, + `.then(importType ? ${requireFn}.t.bind(0,moduleId,importType) : ${requireFn}.bind(0,moduleId));` + ]), + `};` + ]); + } + } + + compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (compilation) => { + const { moduleGraph } = compilation; + asyncImportMap.clear(); + asyncImportGroups.clear(); + + this._minifierHooks.postProcessCodeFragment.tap({ name: PLUGIN_NAME, stage: -1 }, (source, context) => { + const code: string = source.original(); + + let localImports: Map | undefined; + + // Reset the state of the regex + ASYNC_IMPORT_REGEX.lastIndex = 0; + // RegExp.exec uses null or an array as the return type, explicitly + let match: RegExpExecArray | null = null; + while ((match = ASYNC_IMPORT_REGEX.exec(code))) { + const token: string = match[0]; + + if (!localImports) { + if (!context.module) { + context.compilation.errors.push( + new WebpackError( + `Unexpected async import ${token} in non-module context ${context.loggingName}` + ) + ); + return source; + } + + localImports = asyncImportMap.get(context.module); + if (!localImports) { + context.compilation.errors.push( + new WebpackError(`Unexpected async import ${token} in module ${context.loggingName}`) + ); + return source; + } + } + + const localImport: ILocalImportMetadata | undefined = localImports.get(token); + if (!localImport) { + context.compilation.errors.push( + new WebpackError(`Missing metadata for ${token} in module ${context.loggingName}`) + ); + return source; + } + const { meta, module } = localImport; + + const chunkExpression: string = meta.index < 0 ? JSON.stringify(meta.chunkIds) : `${meta.index}`; + + source.replace( + match.index, + ASYNC_IMPORT_REGEX.lastIndex - 1, + `${chunkExpression},${JSON.stringify(module.id!)}${getImportTypeExpression( + module, + context.module!, + moduleGraph + )}` + ); + } + + return source; + }); + + compilation.hooks.beforeChunkAssets.tap({ name: PLUGIN_NAME, stage: STAGE_AFTER }, () => { + const ImportDependency: typeof WebpackImportDependency = getImportDependency(compilation); + + for (const module of compilation.modules) { + let toProcess: Module[]; + + if (isConcatenatedModule(module)) { + toProcess = module.modules; + } else { + toProcess = [module]; + } + + for (const child of toProcess) { + processModuleDependenciesRecursive(child, (dep) => { + if (dep instanceof ImportDependency) { + const targetModule: Module = moduleGraph.getModule(dep); + + if (targetModule) { + let localAsyncImports: Map | undefined = + asyncImportMap.get(module); + if (!localAsyncImports) { + asyncImportMap.set(module, (localAsyncImports = new Map())); + } + + const chunkGroups: ChunkGroup[] = targetModule.blocks.map((b) => + compilation.chunkGraph.getBlockChunkGroup(b) + ); + + const chunkIds: Set = new Set(); + + for (const chunkGroup of chunkGroups) { + for (const chunk of chunkGroup.chunks) { + chunkIds.add(chunk.id); + } + } + + const idString: string = Array.from(chunkIds).join(';'); + + let meta: IAsyncImportMetadata | undefined = asyncImportGroups.get(idString); + if (!meta) { + asyncImportGroups.set( + idString, + (meta = { chunkCount: chunkIds.size, chunkIds: [], count: 0, index: -1 }) + ); + } + + meta.count++; + + const stringKey: string = `${targetModule.id}`.replace(/[^A-Za-z0-9_$]/g, '_'); + + const key: string = `${ASYNC_IMPORT_PREFIX}${stringKey}`; + localAsyncImports.set(key, { + meta, + module: targetModule + }); + } + } + }); + } + } + + const rankedImports: [string, IAsyncImportMetadata][] = [...asyncImportGroups] + .filter((x) => x[1].count > 1) + .sort((x, y) => { + let diff: number = y[1].count - x[1].count; + if (!diff) { + diff = y[1].chunkCount - x[1].chunkCount; + } + + if (!diff) { + diff = x[0] > y[0] ? 1 : x[0] < y[0] ? -1 : 0; + } + + return diff; + }); + + for (let i: number = 0, len: number = rankedImports.length; i < len; i++) { + rankedImports[i][1].index = i; + } + + rankedImportGroups = rankedImports.map((x) => x[1]); + + const { dependencyTemplates } = compilation; + + const defaultImplementation: IImportDependencyTemplate | undefined = + dependencyTemplates.get(ImportDependency); + + if (!defaultImplementation) { + compilation.errors.push(new WebpackError(`Could not find ImportDependencyTemplate`)); + } + + const customTemplate: IImportDependencyTemplate = { + apply( + dep: WebpackImportDependency, + source: sources.ReplaceSource, + dependencyTemplateContext: DependencyTemplateContext + ): void { + const targetModule: Module = moduleGraph.getModule(dep); + + if (targetModule) { + const moduleId: string | number = compilation.chunkGraph.getModuleId(targetModule); + const stringKey: string = `${moduleId}`.replace(/[^A-Za-z0-9_$]/g, '_'); + const key: string = `${ASYNC_IMPORT_PREFIX}${stringKey}`; + const content: string = `__webpack_require__.ee(${key})`; + source.replace(dep.range[0], dep.range[1] - 1, content); + } else { + defaultImplementation?.apply(dep, source, dependencyTemplateContext); + } + } + }; + + dependencyTemplates.set(ImportDependency, customTemplate); + }); + }); + } +} + +function isConcatenatedModule(module: Module): module is IConcatenatedModule { + return module.constructor.name === 'ConcatenatedModule'; +} diff --git a/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.ts b/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.ts index ca451b022c..dc681de199 100644 --- a/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.ts +++ b/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.ts @@ -44,8 +44,10 @@ import type { IModuleMinifierPluginStats as IModuleMinifierPluginStats, IAssetStats } from './ModuleMinifierPlugin.types'; + import { generateLicenseFileForAsset } from './GenerateLicenseFileForAsset'; import { rehydrateAsset } from './RehydrateAsset'; +import { AsyncImportCompressionPlugin } from './AsyncImportCompressionPlugin'; // The name of the plugin, for use in taps const PLUGIN_NAME: 'ModuleMinifierPlugin' = 'ModuleMinifierPlugin'; @@ -145,7 +147,7 @@ export class ModuleMinifierPlugin implements WebpackPluginInstance { postProcessCodeFragment: new SyncWaterfallHook(['code', 'context']) }; - const { minifier, sourceMap } = options; + const { minifier, sourceMap, compressAsyncImports = false } = options; this._optionsForHash = { ...options, @@ -155,6 +157,10 @@ export class ModuleMinifierPlugin implements WebpackPluginInstance { this._enhancers = []; + if (compressAsyncImports) { + this._enhancers.push(new AsyncImportCompressionPlugin(this.hooks)); + } + this.hooks.rehydrateAssets.tap(PLUGIN_NAME, defaultRehydrateAssets); this.minifier = minifier; diff --git a/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.types.ts b/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.types.ts index e2ae475131..05cb32b8fb 100644 --- a/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.types.ts +++ b/webpack/webpack5-module-minifier-plugin/src/ModuleMinifierPlugin.types.ts @@ -167,6 +167,11 @@ export interface IModuleMinifierPluginOptions { * Set to `false` for faster builds at the expense of debuggability. */ sourceMap?: boolean; + + /** + * Instructs the plugin to alter the code of async import statements to compress better and be portable across compilations. + */ + compressAsyncImports?: boolean; } /** diff --git a/webpack/webpack5-module-minifier-plugin/src/processModuleDependenciesRecursive.ts b/webpack/webpack5-module-minifier-plugin/src/processModuleDependenciesRecursive.ts new file mode 100644 index 0000000000..b45940cdfb --- /dev/null +++ b/webpack/webpack5-module-minifier-plugin/src/processModuleDependenciesRecursive.ts @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +import type { Dependency, Module } from 'webpack'; + +/** + * Recursively processes module dependencies. If a dependency has blocks, they will be processed too. + */ +export function processModuleDependenciesRecursive( + module: Module, + callback: (dependency: Dependency) => void +): void { + type DependenciesBlock = Pick; + + const queue: DependenciesBlock[] = [module]; + do { + const block: DependenciesBlock = queue.pop()!; + if (block.dependencies) { + for (const dep of block.dependencies) callback(dep); + } + if (block.blocks) { + for (const b of block.blocks) queue.push(b); + } + } while (queue.length !== 0); +} diff --git a/webpack/webpack5-module-minifier-plugin/src/test/CompressAsyncImports.test.ts b/webpack/webpack5-module-minifier-plugin/src/test/CompressAsyncImports.test.ts new file mode 100644 index 0000000000..3bbabd8a0b --- /dev/null +++ b/webpack/webpack5-module-minifier-plugin/src/test/CompressAsyncImports.test.ts @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. +// See LICENSE in the project root for license information. + +jest.disableAutomock(); + +import { promisify } from 'util'; +import { Volume } from 'memfs/lib/volume'; +import webpack, { type Stats } from 'webpack'; +import { ModuleMinifierPlugin } from '../ModuleMinifierPlugin'; +import type { IModuleMinifier } from '@rushstack/module-minifier'; +import { MockMinifier } from './MockMinifier'; +import exp from 'constants'; + +const MEMORY_FILE_SYSTEM: Volume = Volume.fromJSON({ + '/package.json': '{}', + '/entry.js': `// A comment\nconsole.log("Do stuff");import(/* webpackChunkName: 'async' */ './async.js').then(mod => mod.foo());`, + '/entry2.js': `Promise.all([import("./a"), import("./c"), import("./e")]).then( + ([a, c, e]) => { + console.log(a, c, e); + } + );`, + '/entry3.js': `Promise.all([import("./g"), import("./h"), import("./i"), import("./j")]).then( + ([g, h, i, j]) => { + console.log(g, h, i, j); + } + );`, + '/async.js': + '// @license MIT\nimport bar from "./bar";\nimport baz from "./baz";\nexport function foo() { bar.a(); baz.b(); }console.log("Test character lengths: \ufeff\uffef")', + '/a.js': `const b = import('./b').then(mod => mod.b); console.log(b);`, + '/b.js': `export const b = 'b';`, + '/c.js': `const d = import('./d').then(mod => mod.d); console.log(d);`, + '/d.js': `export const d = 'd';`, + '/e.js': `const f = import('./f').then(mod => mod.f); console.log(f);`, + '/f.js': `export const f = 'f';`, + '/g.js': `export default 'g';`, + '/h.js': `import g from './g'; export default g;`, + '/i.js': `import h from './h'; export default h;`, + '/j.js': `import i from './i'; export default i;`, + '/bar.js': `export default { a() { console.log('a'); } };`, + '/baz.js': `export default { b() { console.log('b'); } };` +}); + +function getDefaultConfig(minifier: IModuleMinifier): webpack.Configuration { + return { + entry: { + one: '/entry.js', + two: '/entry2.js', + three: '/entry3.js' + }, + output: { + path: '/release', + filename: '[name].js' + }, + optimization: { + minimizer: [] + }, + context: '/', + mode: 'production', + plugins: [new ModuleMinifierPlugin({ minifier, compressAsyncImports: true })] + }; +} + +async function runWebpack(): Promise { + const compiler: webpack.Compiler = webpack(getDefaultConfig(new MockMinifier())); + + compiler.inputFileSystem = MEMORY_FILE_SYSTEM; + compiler.outputFileSystem = MEMORY_FILE_SYSTEM; + + const stats: Stats | undefined = await promisify(compiler.run.bind(compiler))(); + await promisify(compiler.close.bind(compiler))(); + + if (!stats) { + throw new Error('No stats'); + } + + const { errors, warnings } = stats.toJson('errors-warnings'); + expect(errors).toMatchSnapshot('Errors'); + expect(warnings).toMatchSnapshot('Warnings'); + + const results: {} = MEMORY_FILE_SYSTEM.toJSON('/release'); + expect(results).toMatchSnapshot('Content'); +} + +describe(ModuleMinifierPlugin.name, () => { + it('Correctly compresses async import callsites', async () => { + await runWebpack(); + }); +}); diff --git a/webpack/webpack5-module-minifier-plugin/src/test/__snapshots__/CompressAsyncImports.test.ts.snap b/webpack/webpack5-module-minifier-plugin/src/test/__snapshots__/CompressAsyncImports.test.ts.snap new file mode 100644 index 0000000000..f0d0e9de25 --- /dev/null +++ b/webpack/webpack5-module-minifier-plugin/src/test/__snapshots__/CompressAsyncImports.test.ts.snap @@ -0,0 +1,1184 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ModuleMinifierPlugin Correctly compresses async import callsites: Content 1`] = ` +Object { + "/release/101.js": "// Begin Asset Hash=52317fcc2353829577ca8e89b8ab912b1a89272dea4dfa9b7d7c19b95e358af1 +\\"use strict\\"; +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[101,785,307],{ + +/***/ 785: + +// Begin Module Hash=f3b040812c295fcfc2520d6bfb8d2666cdb67d32f30ff46edb3ae8d95b85a3d9 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ('g'); + +/***/ }) + +// End Module +, + +/***/ 307: + +// Begin Module Hash=694dacf42ab9aa7020bab3bb4869bd2dc20edb73b3bbad1cffc0143e9662a7b9 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _g__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(785); + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_g__WEBPACK_IMPORTED_MODULE_0__[\\"default\\"]); + +/***/ }) + +// End Module +, + +/***/ 101: + +// Begin Module Hash=517ffdf5e8f7801b54257b2e7018d098abe8d93b95ff28dc086981af6f72c7f4 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _h__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(307); + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_h__WEBPACK_IMPORTED_MODULE_0__[\\"default\\"]); + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/138.js": "// Begin Asset Hash=71ae86f3d35360fc934ab1249f3b79f3edc5d3237025540fcda12d56d31cfae9 +\\"use strict\\"; +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[138,785,307,101],{ + +/***/ 785: + +// Begin Module Hash=f3b040812c295fcfc2520d6bfb8d2666cdb67d32f30ff46edb3ae8d95b85a3d9 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ('g'); + +/***/ }) + +// End Module +, + +/***/ 307: + +// Begin Module Hash=694dacf42ab9aa7020bab3bb4869bd2dc20edb73b3bbad1cffc0143e9662a7b9 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _g__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(785); + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_g__WEBPACK_IMPORTED_MODULE_0__[\\"default\\"]); + +/***/ }) + +// End Module +, + +/***/ 101: + +// Begin Module Hash=517ffdf5e8f7801b54257b2e7018d098abe8d93b95ff28dc086981af6f72c7f4 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _h__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(307); + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_h__WEBPACK_IMPORTED_MODULE_0__[\\"default\\"]); + +/***/ }) + +// End Module +, + +/***/ 138: + +// Begin Module Hash=5317ca94adfb2a81231932209bae566887b68ef4f3a655065895fe2213b3dc8b + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _i__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(101); + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_i__WEBPACK_IMPORTED_MODULE_0__[\\"default\\"]); + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/307.js": "// Begin Asset Hash=045915b7cb2d8eeb3adb8662e32af4dc62db7e025214bf9947841d66ff20a8ba +\\"use strict\\"; +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[307,785],{ + +/***/ 785: + +// Begin Module Hash=f3b040812c295fcfc2520d6bfb8d2666cdb67d32f30ff46edb3ae8d95b85a3d9 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ('g'); + +/***/ }) + +// End Module +, + +/***/ 307: + +// Begin Module Hash=694dacf42ab9aa7020bab3bb4869bd2dc20edb73b3bbad1cffc0143e9662a7b9 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony import */ var _g__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(785); + /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_g__WEBPACK_IMPORTED_MODULE_0__[\\"default\\"]); + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/390.js": "// Begin Asset Hash=a29bca4a195314fa47bd1226ebbf71b32f814a4d20b87331c87222c8911cf2c0 +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[390],{ + +/***/ 390: + +// Begin Module Hash=998eab634fabe3db3d1a1e5138db04e7b2ec1d2b9d0792e91eb63b60cd06daad + +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +const f = __webpack_require__.e(/* import() */ 568).then(__webpack_require__.bind(__webpack_require__, 568)).then(mod => mod.f); console.log(f); + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/460.js": "// Begin Asset Hash=8f6708bcae39dcef42d060ef9655f30ff19010a24133b5e3ab7a3a9185a7d385 +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[460],{ + +/***/ 460: + +// Begin Module Hash=88144b27e14735bed6a5f9bee53afcf6f7f3f1f6a6989f20fd91c7d437cc754c + +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +const d = __webpack_require__.e(/* import() */ 767).then(__webpack_require__.bind(__webpack_require__, 767)).then(mod => mod.d); console.log(d); + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/568.js": "// Begin Asset Hash=e50df9e89f3fcd30381fbc6666cb6bd54e5548db55c684c2850031eac6c2885f +\\"use strict\\"; +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[568],{ + +/***/ 568: + +// Begin Module Hash=f6e57c68596ffeb6d6c988a0bdf8bc3f92ab228e226574abd59fdd4aab801148 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"f\\": () => (/* binding */ f) +/* harmony export */ }); +const f = 'f'; + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/767.js": "// Begin Asset Hash=bc2ba9872aa9c447a883570cde81a64d44ab3f214e8298230f6e16b57d7b23d2 +\\"use strict\\"; +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[767],{ + +/***/ 767: + +// Begin Module Hash=1edfd59f0c6bcde8499ed337728a94d15bdbe2f413057c6cc82dbe6eca4ebc7b + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"d\\": () => (/* binding */ d) +/* harmony export */ }); +const d = 'd'; + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/785.js": "// Begin Asset Hash=2f42df6388f274451f185b84c06552e379a12267b23cbbef98419837806a4a45 +\\"use strict\\"; +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[785],{ + +/***/ 785: + +// Begin Module Hash=f3b040812c295fcfc2520d6bfb8d2666cdb67d32f30ff46edb3ae8d95b85a3d9 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"default\\": () => (__WEBPACK_DEFAULT_EXPORT__) +/* harmony export */ }); +/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ('g'); + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/847.js": "// Begin Asset Hash=1818ad2afb460fb65dc19d7933832b3efe9bd796ffbb8a84c07d784a900366f8 +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[847],{ + +/***/ 847: + +// Begin Module Hash=c8cd9c449ee89ee2130b653c3a8269519a9249cb44ca9b7f8a56e249893e95ff + +/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => { + +const b = __webpack_require__.e(/* import() */ 996).then(__webpack_require__.bind(__webpack_require__, 996)).then(mod => mod.b); console.log(b); + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/996.js": "// Begin Asset Hash=da1c045a838d4d99c79ee3f1a4e3d77a4d1c605abd0b1556cfe9db85b73a68f7 +\\"use strict\\"; +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[996],{ + +/***/ 996: + +// Begin Module Hash=a34a289a987e650e4d52350b26fec7bdcf3442e09409c783caade2e98a647e65 + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +__webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ \\"b\\": () => (/* binding */ b) +/* harmony export */ }); +const b = 'b'; + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/async.js": "/*! For license information please see async.js.LICENSE.txt */ +// Begin Asset Hash=0aa563f491c9a67516080c509b34ecd12e3e9cb653f90e3aa5d6efe026ea884c +\\"use strict\\"; +(self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []).push([[931],{ + +/***/ 731: + +// Begin Module Hash=1ebcc0f3559ea4f72aa0b42185934a89e9df26db61eb557cb04dbeb63d81010c + +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +// ESM COMPAT FLAG +__webpack_require__.r(__webpack_exports__); + +// EXPORTS +__webpack_require__.d(__webpack_exports__, { + \\"foo\\": () => (/* binding */ foo) +}); + +;// CONCATENATED MODULE: ./bar.js +/* harmony default export */ const bar = ({ a() { console.log('a'); } }); +;// CONCATENATED MODULE: ./baz.js +/* harmony default export */ const baz = ({ b() { console.log('b'); } }); +;// CONCATENATED MODULE: ./async.js +// @license MIT + + +function foo() { bar.a(); baz.b(); }console.log(\\"Test character lengths: ￯\\") + +/***/ }) + +// End Module + + +}]); +// End Asset", + "/release/async.js.LICENSE.txt": "// @license MIT +", + "/release/one.js": "// Begin Asset Hash=88aacca641bafba64991c9415a7510d6fac105b68b846dec45be70fa6bce985c +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({}); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = __webpack_modules__; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/ensure chunk */ +/******/ (() => { +/******/ __webpack_require__.f = {}; +/******/ // This file contains only the entry chunk. +/******/ // The chunk loading function for additional chunks +/******/ __webpack_require__.e = (chunkId) => { +/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => { +/******/ __webpack_require__.f[key](chunkId, promises); +/******/ return promises; +/******/ }, [])); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/get javascript chunk filename */ +/******/ (() => { +/******/ // This function allow to reference async chunks +/******/ __webpack_require__.u = (chunkId) => { +/******/ // return url for filenames based on template +/******/ return \\"\\" + \\"async\\" + \\".js\\"; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/load script */ +/******/ (() => { +/******/ var inProgress = {}; +/******/ // data-webpack is not used as build has no uniqueName +/******/ // loadScript function to load a script via script tag +/******/ __webpack_require__.l = (url, done, key, chunkId) => { +/******/ if(inProgress[url]) { inProgress[url].push(done); return; } +/******/ var script, needAttach; +/******/ if(key !== undefined) { +/******/ var scripts = document.getElementsByTagName(\\"script\\"); +/******/ for(var i = 0; i < scripts.length; i++) { +/******/ var s = scripts[i]; +/******/ if(s.getAttribute(\\"src\\") == url) { script = s; break; } +/******/ } +/******/ } +/******/ if(!script) { +/******/ needAttach = true; +/******/ script = document.createElement('script'); +/******/ +/******/ script.charset = 'utf-8'; +/******/ script.timeout = 120; +/******/ if (__webpack_require__.nc) { +/******/ script.setAttribute(\\"nonce\\", __webpack_require__.nc); +/******/ } +/******/ +/******/ script.src = url; +/******/ } +/******/ inProgress[url] = [done]; +/******/ var onScriptComplete = (prev, event) => { +/******/ // avoid mem leaks in IE. +/******/ script.onerror = script.onload = null; +/******/ clearTimeout(timeout); +/******/ var doneFns = inProgress[url]; +/******/ delete inProgress[url]; +/******/ script.parentNode && script.parentNode.removeChild(script); +/******/ doneFns && doneFns.forEach((fn) => (fn(event))); +/******/ if(prev) return prev(event); +/******/ } +/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); +/******/ script.onerror = onScriptComplete.bind(null, script.onerror); +/******/ script.onload = onScriptComplete.bind(null, script.onload); +/******/ needAttach && document.head.appendChild(script); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/publicPath */ +/******/ (() => { +/******/ var scriptUrl; +/******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + \\"\\"; +/******/ var document = __webpack_require__.g.document; +/******/ if (!scriptUrl && document) { +/******/ if (document.currentScript) +/******/ scriptUrl = document.currentScript.src; +/******/ if (!scriptUrl) { +/******/ var scripts = document.getElementsByTagName(\\"script\\"); +/******/ if(scripts.length) { +/******/ var i = scripts.length - 1; +/******/ while (i > -1 && !scriptUrl) scriptUrl = scripts[i--].src; +/******/ } +/******/ } +/******/ } +/******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration +/******/ // or pass an empty string (\\"\\") and set the __webpack_public_path__ variable from your code to use your own logic. +/******/ if (!scriptUrl) throw new Error(\\"Automatic publicPath is not supported in this browser\\"); +/******/ scriptUrl = scriptUrl.replace(/#.*$/, \\"\\").replace(/\\\\?.*$/, \\"\\").replace(/\\\\/[^\\\\/]+$/, \\"/\\"); +/******/ __webpack_require__.p = scriptUrl; +/******/ })(); +/******/ +/******/ /* webpack/runtime/jsonp chunk loading */ +/******/ (() => { +/******/ // no baseURI +/******/ +/******/ // object to store loaded and loading chunks +/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched +/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded +/******/ var installedChunks = { +/******/ 255: 0 +/******/ }; +/******/ +/******/ __webpack_require__.f.j = (chunkId, promises) => { +/******/ // JSONP chunk loading for javascript +/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined; +/******/ if(installedChunkData !== 0) { // 0 means \\"already installed\\". +/******/ +/******/ // a Promise means \\"currently loading\\". +/******/ if(installedChunkData) { +/******/ promises.push(installedChunkData[2]); +/******/ } else { +/******/ if(true) { // all chunks have JS +/******/ // setup Promise in chunk cache +/******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject])); +/******/ promises.push(installedChunkData[2] = promise); +/******/ +/******/ // start chunk loading +/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId); +/******/ // create error before stack unwound to get useful stacktrace later +/******/ var error = new Error(); +/******/ var loadingEnded = (event) => { +/******/ if(__webpack_require__.o(installedChunks, chunkId)) { +/******/ installedChunkData = installedChunks[chunkId]; +/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined; +/******/ if(installedChunkData) { +/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); +/******/ var realSrc = event && event.target && event.target.src; +/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\\\\n(' + errorType + ': ' + realSrc + ')'; +/******/ error.name = 'ChunkLoadError'; +/******/ error.type = errorType; +/******/ error.request = realSrc; +/******/ installedChunkData[1](error); +/******/ } +/******/ } +/******/ }; +/******/ __webpack_require__.l(url, loadingEnded, \\"chunk-\\" + chunkId, chunkId); +/******/ } +/******/ } +/******/ } +/******/ }; +/******/ +/******/ // no prefetching +/******/ +/******/ // no preloaded +/******/ +/******/ // no HMR +/******/ +/******/ // no HMR manifest +/******/ +/******/ // no on chunks loaded +/******/ +/******/ // install a JSONP callback for chunk loading +/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => { +/******/ var [chunkIds, moreModules, runtime] = data; +/******/ // add \\"moreModules\\" to the modules object, +/******/ // then flag all \\"chunkIds\\" as loaded and fire callback +/******/ var moduleId, chunkId, i = 0; +/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) { +/******/ for(moduleId in moreModules) { +/******/ if(__webpack_require__.o(moreModules, moduleId)) { +/******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; +/******/ } +/******/ } +/******/ if(runtime) var result = runtime(__webpack_require__); +/******/ } +/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); +/******/ for(;i < chunkIds.length; i++) { +/******/ chunkId = chunkIds[i]; +/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { +/******/ installedChunks[chunkId][0](); +/******/ } +/******/ installedChunks[chunkId] = 0; +/******/ } +/******/ +/******/ } +/******/ +/******/ var chunkLoadingGlobal = self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []; +/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); +/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// A comment +console.log(\\"Do stuff\\");__webpack_require__.e(/* import() | async */ 931).then(__webpack_require__.bind(__webpack_require__, 731)).then(mod => mod.foo()); +/******/ })() +; +// End Asset", + "/release/three.js": "// Begin Asset Hash=528a3127c155d37f1a4cc96ee49268fb3e9e96a52e78a3d52490228a63359aaa +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({}); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = __webpack_modules__; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/ensure chunk */ +/******/ (() => { +/******/ __webpack_require__.f = {}; +/******/ // This file contains only the entry chunk. +/******/ // The chunk loading function for additional chunks +/******/ __webpack_require__.e = (chunkId) => { +/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => { +/******/ __webpack_require__.f[key](chunkId, promises); +/******/ return promises; +/******/ }, [])); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/get javascript chunk filename */ +/******/ (() => { +/******/ // This function allow to reference async chunks +/******/ __webpack_require__.u = (chunkId) => { +/******/ // return url for filenames based on template +/******/ return \\"\\" + chunkId + \\".js\\"; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/load script */ +/******/ (() => { +/******/ var inProgress = {}; +/******/ // data-webpack is not used as build has no uniqueName +/******/ // loadScript function to load a script via script tag +/******/ __webpack_require__.l = (url, done, key, chunkId) => { +/******/ if(inProgress[url]) { inProgress[url].push(done); return; } +/******/ var script, needAttach; +/******/ if(key !== undefined) { +/******/ var scripts = document.getElementsByTagName(\\"script\\"); +/******/ for(var i = 0; i < scripts.length; i++) { +/******/ var s = scripts[i]; +/******/ if(s.getAttribute(\\"src\\") == url) { script = s; break; } +/******/ } +/******/ } +/******/ if(!script) { +/******/ needAttach = true; +/******/ script = document.createElement('script'); +/******/ +/******/ script.charset = 'utf-8'; +/******/ script.timeout = 120; +/******/ if (__webpack_require__.nc) { +/******/ script.setAttribute(\\"nonce\\", __webpack_require__.nc); +/******/ } +/******/ +/******/ script.src = url; +/******/ } +/******/ inProgress[url] = [done]; +/******/ var onScriptComplete = (prev, event) => { +/******/ // avoid mem leaks in IE. +/******/ script.onerror = script.onload = null; +/******/ clearTimeout(timeout); +/******/ var doneFns = inProgress[url]; +/******/ delete inProgress[url]; +/******/ script.parentNode && script.parentNode.removeChild(script); +/******/ doneFns && doneFns.forEach((fn) => (fn(event))); +/******/ if(prev) return prev(event); +/******/ } +/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); +/******/ script.onerror = onScriptComplete.bind(null, script.onerror); +/******/ script.onload = onScriptComplete.bind(null, script.onload); +/******/ needAttach && document.head.appendChild(script); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/publicPath */ +/******/ (() => { +/******/ var scriptUrl; +/******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + \\"\\"; +/******/ var document = __webpack_require__.g.document; +/******/ if (!scriptUrl && document) { +/******/ if (document.currentScript) +/******/ scriptUrl = document.currentScript.src; +/******/ if (!scriptUrl) { +/******/ var scripts = document.getElementsByTagName(\\"script\\"); +/******/ if(scripts.length) { +/******/ var i = scripts.length - 1; +/******/ while (i > -1 && !scriptUrl) scriptUrl = scripts[i--].src; +/******/ } +/******/ } +/******/ } +/******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration +/******/ // or pass an empty string (\\"\\") and set the __webpack_public_path__ variable from your code to use your own logic. +/******/ if (!scriptUrl) throw new Error(\\"Automatic publicPath is not supported in this browser\\"); +/******/ scriptUrl = scriptUrl.replace(/#.*$/, \\"\\").replace(/\\\\?.*$/, \\"\\").replace(/\\\\/[^\\\\/]+$/, \\"/\\"); +/******/ __webpack_require__.p = scriptUrl; +/******/ })(); +/******/ +/******/ /* webpack/runtime/jsonp chunk loading */ +/******/ (() => { +/******/ // no baseURI +/******/ +/******/ // object to store loaded and loading chunks +/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched +/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded +/******/ var installedChunks = { +/******/ 841: 0 +/******/ }; +/******/ +/******/ __webpack_require__.f.j = (chunkId, promises) => { +/******/ // JSONP chunk loading for javascript +/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined; +/******/ if(installedChunkData !== 0) { // 0 means \\"already installed\\". +/******/ +/******/ // a Promise means \\"currently loading\\". +/******/ if(installedChunkData) { +/******/ promises.push(installedChunkData[2]); +/******/ } else { +/******/ if(true) { // all chunks have JS +/******/ // setup Promise in chunk cache +/******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject])); +/******/ promises.push(installedChunkData[2] = promise); +/******/ +/******/ // start chunk loading +/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId); +/******/ // create error before stack unwound to get useful stacktrace later +/******/ var error = new Error(); +/******/ var loadingEnded = (event) => { +/******/ if(__webpack_require__.o(installedChunks, chunkId)) { +/******/ installedChunkData = installedChunks[chunkId]; +/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined; +/******/ if(installedChunkData) { +/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); +/******/ var realSrc = event && event.target && event.target.src; +/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\\\\n(' + errorType + ': ' + realSrc + ')'; +/******/ error.name = 'ChunkLoadError'; +/******/ error.type = errorType; +/******/ error.request = realSrc; +/******/ installedChunkData[1](error); +/******/ } +/******/ } +/******/ }; +/******/ __webpack_require__.l(url, loadingEnded, \\"chunk-\\" + chunkId, chunkId); +/******/ } +/******/ } +/******/ } +/******/ }; +/******/ +/******/ // no prefetching +/******/ +/******/ // no preloaded +/******/ +/******/ // no HMR +/******/ +/******/ // no HMR manifest +/******/ +/******/ // no on chunks loaded +/******/ +/******/ // install a JSONP callback for chunk loading +/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => { +/******/ var [chunkIds, moreModules, runtime] = data; +/******/ // add \\"moreModules\\" to the modules object, +/******/ // then flag all \\"chunkIds\\" as loaded and fire callback +/******/ var moduleId, chunkId, i = 0; +/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) { +/******/ for(moduleId in moreModules) { +/******/ if(__webpack_require__.o(moreModules, moduleId)) { +/******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; +/******/ } +/******/ } +/******/ if(runtime) var result = runtime(__webpack_require__); +/******/ } +/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); +/******/ for(;i < chunkIds.length; i++) { +/******/ chunkId = chunkIds[i]; +/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { +/******/ installedChunks[chunkId][0](); +/******/ } +/******/ installedChunks[chunkId] = 0; +/******/ } +/******/ +/******/ } +/******/ +/******/ var chunkLoadingGlobal = self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []; +/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); +/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +Promise.all([__webpack_require__.e(/* import() */ 785).then(__webpack_require__.bind(__webpack_require__, 785)), __webpack_require__.e(/* import() */ 307).then(__webpack_require__.bind(__webpack_require__, 307)), __webpack_require__.e(/* import() */ 101).then(__webpack_require__.bind(__webpack_require__, 101)), __webpack_require__.e(/* import() */ 138).then(__webpack_require__.bind(__webpack_require__, 138))]).then( + ([g, h, i, j]) => { + console.log(g, h, i, j); + } + ); +/******/ })() +; +// End Asset", + "/release/two.js": "// Begin Asset Hash=4b743bf2c27393054bb886d9f58f413e760ac398f7a85d66e33478c8431dbdce +/******/ (() => { // webpackBootstrap +/******/ var __webpack_modules__ = ({}); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = __webpack_modules__; +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/create fake namespace object */ +/******/ (() => { +/******/ var getProto = Object.getPrototypeOf ? (obj) => (Object.getPrototypeOf(obj)) : (obj) => (obj.__proto__); +/******/ var leafPrototypes; +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 16: return value when it's Promise-like +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = this(value); +/******/ if(mode & 8) return value; +/******/ if(typeof value === 'object' && value) { +/******/ if((mode & 4) && value.__esModule) return value; +/******/ if((mode & 16) && typeof value.then === 'function') return value; +/******/ } +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ var def = {}; +/******/ leafPrototypes = leafPrototypes || [null, getProto({}), getProto([]), getProto(getProto)]; +/******/ for(var current = mode & 2 && value; typeof current == 'object' && !~leafPrototypes.indexOf(current); current = getProto(current)) { +/******/ Object.getOwnPropertyNames(current).forEach((key) => (def[key] = () => (value[key]))); +/******/ } +/******/ def['default'] = () => (value); +/******/ __webpack_require__.d(ns, def); +/******/ return ns; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/define property getters */ +/******/ (() => { +/******/ // define getter functions for harmony exports +/******/ __webpack_require__.d = (exports, definition) => { +/******/ for(var key in definition) { +/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { +/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); +/******/ } +/******/ } +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/ensure chunk */ +/******/ (() => { +/******/ __webpack_require__.f = {}; +/******/ // This file contains only the entry chunk. +/******/ // The chunk loading function for additional chunks +/******/ __webpack_require__.e = (chunkId) => { +/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => { +/******/ __webpack_require__.f[key](chunkId, promises); +/******/ return promises; +/******/ }, [])); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/get javascript chunk filename */ +/******/ (() => { +/******/ // This function allow to reference async chunks +/******/ __webpack_require__.u = (chunkId) => { +/******/ // return url for filenames based on template +/******/ return \\"\\" + chunkId + \\".js\\"; +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/global */ +/******/ (() => { +/******/ __webpack_require__.g = (function() { +/******/ if (typeof globalThis === 'object') return globalThis; +/******/ try { +/******/ return this || new Function('return this')(); +/******/ } catch (e) { +/******/ if (typeof window === 'object') return window; +/******/ } +/******/ })(); +/******/ })(); +/******/ +/******/ /* webpack/runtime/hasOwnProperty shorthand */ +/******/ (() => { +/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) +/******/ })(); +/******/ +/******/ /* webpack/runtime/load script */ +/******/ (() => { +/******/ var inProgress = {}; +/******/ // data-webpack is not used as build has no uniqueName +/******/ // loadScript function to load a script via script tag +/******/ __webpack_require__.l = (url, done, key, chunkId) => { +/******/ if(inProgress[url]) { inProgress[url].push(done); return; } +/******/ var script, needAttach; +/******/ if(key !== undefined) { +/******/ var scripts = document.getElementsByTagName(\\"script\\"); +/******/ for(var i = 0; i < scripts.length; i++) { +/******/ var s = scripts[i]; +/******/ if(s.getAttribute(\\"src\\") == url) { script = s; break; } +/******/ } +/******/ } +/******/ if(!script) { +/******/ needAttach = true; +/******/ script = document.createElement('script'); +/******/ +/******/ script.charset = 'utf-8'; +/******/ script.timeout = 120; +/******/ if (__webpack_require__.nc) { +/******/ script.setAttribute(\\"nonce\\", __webpack_require__.nc); +/******/ } +/******/ +/******/ script.src = url; +/******/ } +/******/ inProgress[url] = [done]; +/******/ var onScriptComplete = (prev, event) => { +/******/ // avoid mem leaks in IE. +/******/ script.onerror = script.onload = null; +/******/ clearTimeout(timeout); +/******/ var doneFns = inProgress[url]; +/******/ delete inProgress[url]; +/******/ script.parentNode && script.parentNode.removeChild(script); +/******/ doneFns && doneFns.forEach((fn) => (fn(event))); +/******/ if(prev) return prev(event); +/******/ } +/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000); +/******/ script.onerror = onScriptComplete.bind(null, script.onerror); +/******/ script.onload = onScriptComplete.bind(null, script.onload); +/******/ needAttach && document.head.appendChild(script); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __webpack_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/publicPath */ +/******/ (() => { +/******/ var scriptUrl; +/******/ if (__webpack_require__.g.importScripts) scriptUrl = __webpack_require__.g.location + \\"\\"; +/******/ var document = __webpack_require__.g.document; +/******/ if (!scriptUrl && document) { +/******/ if (document.currentScript) +/******/ scriptUrl = document.currentScript.src; +/******/ if (!scriptUrl) { +/******/ var scripts = document.getElementsByTagName(\\"script\\"); +/******/ if(scripts.length) { +/******/ var i = scripts.length - 1; +/******/ while (i > -1 && !scriptUrl) scriptUrl = scripts[i--].src; +/******/ } +/******/ } +/******/ } +/******/ // When supporting browsers where an automatic publicPath is not supported you must specify an output.publicPath manually via configuration +/******/ // or pass an empty string (\\"\\") and set the __webpack_public_path__ variable from your code to use your own logic. +/******/ if (!scriptUrl) throw new Error(\\"Automatic publicPath is not supported in this browser\\"); +/******/ scriptUrl = scriptUrl.replace(/#.*$/, \\"\\").replace(/\\\\?.*$/, \\"\\").replace(/\\\\/[^\\\\/]+$/, \\"/\\"); +/******/ __webpack_require__.p = scriptUrl; +/******/ })(); +/******/ +/******/ /* webpack/runtime/jsonp chunk loading */ +/******/ (() => { +/******/ // no baseURI +/******/ +/******/ // object to store loaded and loading chunks +/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched +/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded +/******/ var installedChunks = { +/******/ 804: 0 +/******/ }; +/******/ +/******/ __webpack_require__.f.j = (chunkId, promises) => { +/******/ // JSONP chunk loading for javascript +/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined; +/******/ if(installedChunkData !== 0) { // 0 means \\"already installed\\". +/******/ +/******/ // a Promise means \\"currently loading\\". +/******/ if(installedChunkData) { +/******/ promises.push(installedChunkData[2]); +/******/ } else { +/******/ if(true) { // all chunks have JS +/******/ // setup Promise in chunk cache +/******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject])); +/******/ promises.push(installedChunkData[2] = promise); +/******/ +/******/ // start chunk loading +/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId); +/******/ // create error before stack unwound to get useful stacktrace later +/******/ var error = new Error(); +/******/ var loadingEnded = (event) => { +/******/ if(__webpack_require__.o(installedChunks, chunkId)) { +/******/ installedChunkData = installedChunks[chunkId]; +/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined; +/******/ if(installedChunkData) { +/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type); +/******/ var realSrc = event && event.target && event.target.src; +/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\\\\n(' + errorType + ': ' + realSrc + ')'; +/******/ error.name = 'ChunkLoadError'; +/******/ error.type = errorType; +/******/ error.request = realSrc; +/******/ installedChunkData[1](error); +/******/ } +/******/ } +/******/ }; +/******/ __webpack_require__.l(url, loadingEnded, \\"chunk-\\" + chunkId, chunkId); +/******/ } +/******/ } +/******/ } +/******/ }; +/******/ +/******/ // no prefetching +/******/ +/******/ // no preloaded +/******/ +/******/ // no HMR +/******/ +/******/ // no HMR manifest +/******/ +/******/ // no on chunks loaded +/******/ +/******/ // install a JSONP callback for chunk loading +/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => { +/******/ var [chunkIds, moreModules, runtime] = data; +/******/ // add \\"moreModules\\" to the modules object, +/******/ // then flag all \\"chunkIds\\" as loaded and fire callback +/******/ var moduleId, chunkId, i = 0; +/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) { +/******/ for(moduleId in moreModules) { +/******/ if(__webpack_require__.o(moreModules, moduleId)) { +/******/ __webpack_require__.m[moduleId] = moreModules[moduleId]; +/******/ } +/******/ } +/******/ if(runtime) var result = runtime(__webpack_require__); +/******/ } +/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data); +/******/ for(;i < chunkIds.length; i++) { +/******/ chunkId = chunkIds[i]; +/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) { +/******/ installedChunks[chunkId][0](); +/******/ } +/******/ installedChunks[chunkId] = 0; +/******/ } +/******/ +/******/ } +/******/ +/******/ var chunkLoadingGlobal = self[\\"webpackChunk\\"] = self[\\"webpackChunk\\"] || []; +/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0)); +/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal)); +/******/ })(); +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +Promise.all([__webpack_require__.e(/* import() */ 847).then(__webpack_require__.t.bind(__webpack_require__, 847, 23)), __webpack_require__.e(/* import() */ 460).then(__webpack_require__.t.bind(__webpack_require__, 460, 23)), __webpack_require__.e(/* import() */ 390).then(__webpack_require__.t.bind(__webpack_require__, 390, 23))]).then( + ([a, c, e]) => { + console.log(a, c, e); + } + ); +/******/ })() +; +// End Asset", +} +`; + +exports[`ModuleMinifierPlugin Correctly compresses async import callsites: Errors 1`] = `Array []`; + +exports[`ModuleMinifierPlugin Correctly compresses async import callsites: Warnings 1`] = `Array []`;