UNPKG

4.27 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 { provide } = require("./util/MapHelpers");
9const { first } = require("./util/SetHelpers");
10const createHash = require("./util/createHash");
11const { runtimeToString, RuntimeSpecMap } = require("./util/runtime");
12
13/** @typedef {import("webpack-sources").Source} Source */
14/** @typedef {import("./Module")} Module */
15/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
16/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
17
18class CodeGenerationResults {
19 constructor() {
20 /** @type {Map<Module, RuntimeSpecMap<CodeGenerationResult>>} */
21 this.map = new Map();
22 }
23
24 /**
25 * @param {Module} module the module
26 * @param {RuntimeSpec} runtime runtime(s)
27 * @returns {CodeGenerationResult} the CodeGenerationResult
28 */
29 get(module, runtime) {
30 const entry = this.map.get(module);
31 if (entry === undefined) {
32 throw new Error(
33 `No code generation entry for ${module.identifier()} (existing entries: ${Array.from(
34 this.map.keys(),
35 m => m.identifier()
36 ).join(", ")})`
37 );
38 }
39 if (runtime === undefined) {
40 if (entry.size > 1) {
41 const results = new Set(entry.values());
42 if (results.size !== 1) {
43 throw new Error(
44 `No unique code generation entry for unspecified runtime for ${module.identifier()} (existing runtimes: ${Array.from(
45 entry.keys(),
46 r => runtimeToString(r)
47 ).join(", ")}).
48Caller might not support runtime-dependent code generation (opt-out via optimization.usedExports: "global").`
49 );
50 }
51 return first(results);
52 }
53 return entry.values().next().value;
54 }
55 const result = entry.get(runtime);
56 if (result === undefined) {
57 throw new Error(
58 `No code generation entry for runtime ${runtimeToString(
59 runtime
60 )} for ${module.identifier()} (existing runtimes: ${Array.from(
61 entry.keys(),
62 r => runtimeToString(r)
63 ).join(", ")})`
64 );
65 }
66 return result;
67 }
68
69 /**
70 * @param {Module} module the module
71 * @param {RuntimeSpec} runtime runtime(s)
72 * @returns {boolean} true, when we have data for this
73 */
74 has(module, runtime) {
75 const entry = this.map.get(module);
76 if (entry === undefined) {
77 return false;
78 }
79 if (runtime !== undefined) {
80 return entry.has(runtime);
81 } else if (entry.size > 1) {
82 const results = new Set(entry.values());
83 return results.size === 1;
84 } else {
85 return entry.size === 1;
86 }
87 }
88
89 /**
90 * @param {Module} module the module
91 * @param {RuntimeSpec} runtime runtime(s)
92 * @param {string} sourceType the source type
93 * @returns {Source} a source
94 */
95 getSource(module, runtime, sourceType) {
96 return this.get(module, runtime).sources.get(sourceType);
97 }
98
99 /**
100 * @param {Module} module the module
101 * @param {RuntimeSpec} runtime runtime(s)
102 * @returns {ReadonlySet<string>} runtime requirements
103 */
104 getRuntimeRequirements(module, runtime) {
105 return this.get(module, runtime).runtimeRequirements;
106 }
107
108 /**
109 * @param {Module} module the module
110 * @param {RuntimeSpec} runtime runtime(s)
111 * @param {string} key data key
112 * @returns {any} data generated by code generation
113 */
114 getData(module, runtime, key) {
115 const data = this.get(module, runtime).data;
116 return data === undefined ? undefined : data.get(key);
117 }
118
119 /**
120 * @param {Module} module the module
121 * @param {RuntimeSpec} runtime runtime(s)
122 * @returns {any} hash of the code generation
123 */
124 getHash(module, runtime) {
125 const info = this.get(module, runtime);
126 if (info.hash !== undefined) return info.hash;
127 const hash = createHash("md4");
128 for (const [type, source] of info.sources) {
129 hash.update(type);
130 source.updateHash(hash);
131 }
132 if (info.runtimeRequirements) {
133 for (const rr of info.runtimeRequirements) hash.update(rr);
134 }
135 return (info.hash = /** @type {string} */ (hash.digest("hex")));
136 }
137
138 /**
139 * @param {Module} module the module
140 * @param {RuntimeSpec} runtime runtime(s)
141 * @param {CodeGenerationResult} result result from module
142 * @returns {void}
143 */
144 add(module, runtime, result) {
145 const map = provide(this.map, module, () => new RuntimeSpecMap());
146 map.set(runtime, result);
147 }
148}
149
150module.exports = CodeGenerationResults;