| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 | 
							- /*
 
- 	MIT License http://www.opensource.org/licenses/mit-license.php
 
- 	Author Tobias Koppers @sokra
 
- */
 
- "use strict";
 
- const { RawSource, ReplaceSource } = require("webpack-sources");
 
- // TODO: clean up this file
 
- // replace with newer constructs
 
- // TODO: remove DependencyVariables and replace them with something better
 
- class JavascriptGenerator {
 
- 	generate(module, dependencyTemplates, runtimeTemplate) {
 
- 		const originalSource = module.originalSource();
 
- 		if (!originalSource) {
 
- 			return new RawSource("throw new Error('No source available');");
 
- 		}
 
- 		const source = new ReplaceSource(originalSource);
 
- 		this.sourceBlock(
 
- 			module,
 
- 			module,
 
- 			[],
 
- 			dependencyTemplates,
 
- 			source,
 
- 			runtimeTemplate
 
- 		);
 
- 		return source;
 
- 	}
 
- 	sourceBlock(
 
- 		module,
 
- 		block,
 
- 		availableVars,
 
- 		dependencyTemplates,
 
- 		source,
 
- 		runtimeTemplate
 
- 	) {
 
- 		for (const dependency of block.dependencies) {
 
- 			this.sourceDependency(
 
- 				dependency,
 
- 				dependencyTemplates,
 
- 				source,
 
- 				runtimeTemplate
 
- 			);
 
- 		}
 
- 		/**
 
- 		 * Get the variables of all blocks that we need to inject.
 
- 		 * These will contain the variable name and its expression.
 
- 		 * The name will be added as a parameter in a IIFE the expression as its value.
 
- 		 */
 
- 		const vars = block.variables.reduce((result, value) => {
 
- 			const variable = this.sourceVariables(
 
- 				value,
 
- 				availableVars,
 
- 				dependencyTemplates,
 
- 				runtimeTemplate
 
- 			);
 
- 			if (variable) {
 
- 				result.push(variable);
 
- 			}
 
- 			return result;
 
- 		}, []);
 
- 		/**
 
- 		 * if we actually have variables
 
- 		 * this is important as how #splitVariablesInUniqueNamedChunks works
 
- 		 * it will always return an array in an array which would lead to a IIFE wrapper around
 
- 		 * a module if we do this with an empty vars array.
 
- 		 */
 
- 		if (vars.length > 0) {
 
- 			/**
 
- 			 * Split all variables up into chunks of unique names.
 
- 			 * e.g. imagine you have the following variable names that need to be injected:
 
- 			 * [foo, bar, baz, foo, some, more]
 
- 			 * we can not inject "foo" twice, therefore we just make two IIFEs like so:
 
- 			 * (function(foo, bar, baz){
 
- 			 *   (function(foo, some, more){
 
- 			 *     …
 
- 			 *   }(…));
 
- 			 * }(…));
 
- 			 *
 
- 			 * "splitVariablesInUniqueNamedChunks" splits the variables shown above up to this:
 
- 			 * [[foo, bar, baz], [foo, some, more]]
 
- 			 */
 
- 			const injectionVariableChunks = this.splitVariablesInUniqueNamedChunks(
 
- 				vars
 
- 			);
 
- 			// create all the beginnings of IIFEs
 
- 			const functionWrapperStarts = injectionVariableChunks.map(
 
- 				variableChunk => {
 
- 					return this.variableInjectionFunctionWrapperStartCode(
 
- 						variableChunk.map(variable => variable.name)
 
- 					);
 
- 				}
 
- 			);
 
- 			// and all the ends
 
- 			const functionWrapperEnds = injectionVariableChunks.map(variableChunk => {
 
- 				return this.variableInjectionFunctionWrapperEndCode(
 
- 					module,
 
- 					variableChunk.map(variable => variable.expression),
 
- 					block
 
- 				);
 
- 			});
 
- 			// join them to one big string
 
- 			const varStartCode = functionWrapperStarts.join("");
 
- 			// reverse the ends first before joining them, as the last added must be the inner most
 
- 			const varEndCode = functionWrapperEnds.reverse().join("");
 
- 			// if we have anything, add it to the source
 
- 			if (varStartCode && varEndCode) {
 
- 				const start = block.range ? block.range[0] : -10;
 
- 				const end = block.range
 
- 					? block.range[1]
 
- 					: module.originalSource().size() + 1;
 
- 				source.insert(start + 0.5, varStartCode);
 
- 				source.insert(end + 0.5, "\n/* WEBPACK VAR INJECTION */" + varEndCode);
 
- 			}
 
- 		}
 
- 		for (const childBlock of block.blocks) {
 
- 			this.sourceBlock(
 
- 				module,
 
- 				childBlock,
 
- 				availableVars.concat(vars),
 
- 				dependencyTemplates,
 
- 				source,
 
- 				runtimeTemplate
 
- 			);
 
- 		}
 
- 	}
 
- 	sourceDependency(dependency, dependencyTemplates, source, runtimeTemplate) {
 
- 		const template = dependencyTemplates.get(dependency.constructor);
 
- 		if (!template) {
 
- 			throw new Error(
 
- 				"No template for dependency: " + dependency.constructor.name
 
- 			);
 
- 		}
 
- 		template.apply(dependency, source, runtimeTemplate, dependencyTemplates);
 
- 	}
 
- 	sourceVariables(
 
- 		variable,
 
- 		availableVars,
 
- 		dependencyTemplates,
 
- 		runtimeTemplate
 
- 	) {
 
- 		const name = variable.name;
 
- 		const expr = variable.expressionSource(
 
- 			dependencyTemplates,
 
- 			runtimeTemplate
 
- 		);
 
- 		if (
 
- 			availableVars.some(
 
- 				v => v.name === name && v.expression.source() === expr.source()
 
- 			)
 
- 		) {
 
- 			return;
 
- 		}
 
- 		return {
 
- 			name: name,
 
- 			expression: expr
 
- 		};
 
- 	}
 
- 	/*
 
- 	 * creates the start part of a IIFE around the module to inject a variable name
 
- 	 * (function(…){   <- this part
 
- 	 * }.call(…))
 
- 	 */
 
- 	variableInjectionFunctionWrapperStartCode(varNames) {
 
- 		const args = varNames.join(", ");
 
- 		return `/* WEBPACK VAR INJECTION */(function(${args}) {`;
 
- 	}
 
- 	contextArgument(module, block) {
 
- 		if (this === block) {
 
- 			return module.exportsArgument;
 
- 		}
 
- 		return "this";
 
- 	}
 
- 	/*
 
- 	 * creates the end part of a IIFE around the module to inject a variable name
 
- 	 * (function(…){
 
- 	 * }.call(…))   <- this part
 
- 	 */
 
- 	variableInjectionFunctionWrapperEndCode(module, varExpressions, block) {
 
- 		const firstParam = this.contextArgument(module, block);
 
- 		const furtherParams = varExpressions.map(e => e.source()).join(", ");
 
- 		return `}.call(${firstParam}, ${furtherParams}))`;
 
- 	}
 
- 	splitVariablesInUniqueNamedChunks(vars) {
 
- 		const startState = [[]];
 
- 		return vars.reduce((chunks, variable) => {
 
- 			const current = chunks[chunks.length - 1];
 
- 			// check if variable with same name exists already
 
- 			// if so create a new chunk of variables.
 
- 			const variableNameAlreadyExists = current.some(
 
- 				v => v.name === variable.name
 
- 			);
 
- 			if (variableNameAlreadyExists) {
 
- 				// start new chunk with current variable
 
- 				chunks.push([variable]);
 
- 			} else {
 
- 				// else add it to current chunk
 
- 				current.push(variable);
 
- 			}
 
- 			return chunks;
 
- 		}, startState);
 
- 	}
 
- }
 
- module.exports = JavascriptGenerator;
 
 
  |