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 { provide } = require("./util/MapHelpers");
|
---|
9 | const { first } = require("./util/SetHelpers");
|
---|
10 | const createHash = require("./util/createHash");
|
---|
11 | const { 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 |
|
---|
18 | class 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(", ")}).
|
---|
48 | Caller 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 |
|
---|
150 | module.exports = CodeGenerationResults;
|
---|