UNPKG

5.88 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const { SyncWaterfallHook } = require("tapable");
9const Compilation = require("../Compilation");
10const Generator = require("../Generator");
11const { tryRunOrWebpackError } = require("../HookWebpackError");
12const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
13const { compareModulesByIdentifier } = require("../util/comparators");
14const 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
28const getAsyncWebAssemblyGenerator = memoize(() =>
29 require("./AsyncWebAssemblyGenerator")
30);
31const getAsyncWebAssemblyJavascriptGenerator = memoize(() =>
32 require("./AsyncWebAssemblyJavascriptGenerator")
33);
34const getAsyncWebAssemblyParser = memoize(() =>
35 require("./AsyncWebAssemblyParser")
36);
37
38/**
39 * @typedef {Object} RenderContext
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, RenderContext]>} renderModuleContent
51 */
52
53/** @type {WeakMap<Compilation, CompilationHooks>} */
54const compilationHooksMap = new WeakMap();
55
56class 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 = AsyncWebAssemblyModulesPlugin.getCompilationHooks(
95 compilation
96 );
97 compilation.dependencyFactories.set(
98 WebAssemblyImportDependency,
99 normalModuleFactory
100 );
101
102 normalModuleFactory.hooks.createParser
103 .for("webassembly/async")
104 .tap("AsyncWebAssemblyModulesPlugin", () => {
105 const AsyncWebAssemblyParser = getAsyncWebAssemblyParser();
106
107 return new AsyncWebAssemblyParser();
108 });
109 normalModuleFactory.hooks.createGenerator
110 .for("webassembly/async")
111 .tap("AsyncWebAssemblyModulesPlugin", () => {
112 const AsyncWebAssemblyJavascriptGenerator = 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
198module.exports = AsyncWebAssemblyModulesPlugin;