UNPKG

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