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