simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

AsyncWebAssemblyModulesPlugin.js (5898B)


      1 /*
      2 	MIT License http://www.opensource.org/licenses/mit-license.php
      3 	Author Tobias Koppers @sokra
      4 */
      5 
      6 "use strict";
      7 
      8 const { SyncWaterfallHook } = require("tapable");
      9 const Compilation = require("../Compilation");
     10 const Generator = require("../Generator");
     11 const { tryRunOrWebpackError } = require("../HookWebpackError");
     12 const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
     13 const { compareModulesByIdentifier } = require("../util/comparators");
     14 const memoize = require("../util/memoize");
     15 
     16 /** @typedef {import("webpack-sources").Source} Source */
     17 /** @typedef {import("../Chunk")} Chunk */
     18 /** @typedef {import("../ChunkGraph")} ChunkGraph */
     19 /** @typedef {import("../CodeGenerationResults")} CodeGenerationResults */
     20 /** @typedef {import("../Compiler")} Compiler */
     21 /** @typedef {import("../DependencyTemplates")} DependencyTemplates */
     22 /** @typedef {import("../Module")} Module */
     23 /** @typedef {import("../ModuleGraph")} ModuleGraph */
     24 /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
     25 /** @typedef {import("../Template").RenderManifestEntry} RenderManifestEntry */
     26 /** @typedef {import("../Template").RenderManifestOptions} RenderManifestOptions */
     27 
     28 const getAsyncWebAssemblyGenerator = memoize(() =>
     29 	require("./AsyncWebAssemblyGenerator")
     30 );
     31 const getAsyncWebAssemblyJavascriptGenerator = memoize(() =>
     32 	require("./AsyncWebAssemblyJavascriptGenerator")
     33 );
     34 const getAsyncWebAssemblyParser = memoize(() =>
     35 	require("./AsyncWebAssemblyParser")
     36 );
     37 
     38 /**
     39  * @typedef {Object} WebAssemblyRenderContext
     40  * @property {Chunk} chunk the chunk
     41  * @property {DependencyTemplates} dependencyTemplates the dependency templates
     42  * @property {RuntimeTemplate} runtimeTemplate the runtime template
     43  * @property {ModuleGraph} moduleGraph the module graph
     44  * @property {ChunkGraph} chunkGraph the chunk graph
     45  * @property {CodeGenerationResults} codeGenerationResults results of code generation
     46  */
     47 
     48 /**
     49  * @typedef {Object} CompilationHooks
     50  * @property {SyncWaterfallHook<[Source, Module, WebAssemblyRenderContext]>} renderModuleContent
     51  */
     52 
     53 /** @type {WeakMap<Compilation, CompilationHooks>} */
     54 const compilationHooksMap = new WeakMap();
     55 
     56 class AsyncWebAssemblyModulesPlugin {
     57 	/**
     58 	 * @param {Compilation} compilation the compilation
     59 	 * @returns {CompilationHooks} the attached hooks
     60 	 */
     61 	static getCompilationHooks(compilation) {
     62 		if (!(compilation instanceof Compilation)) {
     63 			throw new TypeError(
     64 				"The 'compilation' argument must be an instance of Compilation"
     65 			);
     66 		}
     67 		let hooks = compilationHooksMap.get(compilation);
     68 		if (hooks === undefined) {
     69 			hooks = {
     70 				renderModuleContent: new SyncWaterfallHook([
     71 					"source",
     72 					"module",
     73 					"renderContext"
     74 				])
     75 			};
     76 			compilationHooksMap.set(compilation, hooks);
     77 		}
     78 		return hooks;
     79 	}
     80 
     81 	constructor(options) {
     82 		this.options = options;
     83 	}
     84 
     85 	/**
     86 	 * Apply the plugin
     87 	 * @param {Compiler} compiler the compiler instance
     88 	 * @returns {void}
     89 	 */
     90 	apply(compiler) {
     91 		compiler.hooks.compilation.tap(
     92 			"AsyncWebAssemblyModulesPlugin",
     93 			(compilation, { normalModuleFactory }) => {
     94 				const hooks =
     95 					AsyncWebAssemblyModulesPlugin.getCompilationHooks(compilation);
     96 				compilation.dependencyFactories.set(
     97 					WebAssemblyImportDependency,
     98 					normalModuleFactory
     99 				);
    100 
    101 				normalModuleFactory.hooks.createParser
    102 					.for("webassembly/async")
    103 					.tap("AsyncWebAssemblyModulesPlugin", () => {
    104 						const AsyncWebAssemblyParser = getAsyncWebAssemblyParser();
    105 
    106 						return new AsyncWebAssemblyParser();
    107 					});
    108 				normalModuleFactory.hooks.createGenerator
    109 					.for("webassembly/async")
    110 					.tap("AsyncWebAssemblyModulesPlugin", () => {
    111 						const AsyncWebAssemblyJavascriptGenerator =
    112 							getAsyncWebAssemblyJavascriptGenerator();
    113 						const AsyncWebAssemblyGenerator = getAsyncWebAssemblyGenerator();
    114 
    115 						return Generator.byType({
    116 							javascript: new AsyncWebAssemblyJavascriptGenerator(
    117 								compilation.outputOptions.webassemblyModuleFilename
    118 							),
    119 							webassembly: new AsyncWebAssemblyGenerator(this.options)
    120 						});
    121 					});
    122 
    123 				compilation.hooks.renderManifest.tap(
    124 					"WebAssemblyModulesPlugin",
    125 					(result, options) => {
    126 						const { moduleGraph, chunkGraph, runtimeTemplate } = compilation;
    127 						const {
    128 							chunk,
    129 							outputOptions,
    130 							dependencyTemplates,
    131 							codeGenerationResults
    132 						} = options;
    133 
    134 						for (const module of chunkGraph.getOrderedChunkModulesIterable(
    135 							chunk,
    136 							compareModulesByIdentifier
    137 						)) {
    138 							if (module.type === "webassembly/async") {
    139 								const filenameTemplate =
    140 									outputOptions.webassemblyModuleFilename;
    141 
    142 								result.push({
    143 									render: () =>
    144 										this.renderModule(
    145 											module,
    146 											{
    147 												chunk,
    148 												dependencyTemplates,
    149 												runtimeTemplate,
    150 												moduleGraph,
    151 												chunkGraph,
    152 												codeGenerationResults
    153 											},
    154 											hooks
    155 										),
    156 									filenameTemplate,
    157 									pathOptions: {
    158 										module,
    159 										runtime: chunk.runtime,
    160 										chunkGraph
    161 									},
    162 									auxiliary: true,
    163 									identifier: `webassemblyAsyncModule${chunkGraph.getModuleId(
    164 										module
    165 									)}`,
    166 									hash: chunkGraph.getModuleHash(module, chunk.runtime)
    167 								});
    168 							}
    169 						}
    170 
    171 						return result;
    172 					}
    173 				);
    174 			}
    175 		);
    176 	}
    177 
    178 	renderModule(module, renderContext, hooks) {
    179 		const { codeGenerationResults, chunk } = renderContext;
    180 		try {
    181 			const moduleSource = codeGenerationResults.getSource(
    182 				module,
    183 				chunk.runtime,
    184 				"webassembly"
    185 			);
    186 			return tryRunOrWebpackError(
    187 				() =>
    188 					hooks.renderModuleContent.call(moduleSource, module, renderContext),
    189 				"AsyncWebAssemblyModulesPlugin.getCompilationHooks().renderModuleContent"
    190 			);
    191 		} catch (e) {
    192 			e.module = module;
    193 			throw e;
    194 		}
    195 	}
    196 }
    197 
    198 module.exports = AsyncWebAssemblyModulesPlugin;