| 76 | * @returns {Promise<Map<number, string[]>>} internal-error messages keyed by entry index |
| 77 | */ |
| 78 | const buildBatch = (inputs, mode) => |
| 79 | new Promise((resolve) => { |
| 80 | const mfs = createFsFromVolume(new Volume()); |
| 81 | mfs.mkdirSync(class="st">"/src", { recursive: true }); |
| 82 | /** @type {Record<string, string>} */ |
| 83 | const entry = {}; |
| 84 | for (const [i, input] of inputs.entries()) { |
| 85 | mfs.writeFileSync(`/src/c${i}.html`, input); |
| 86 | entry[`c${i}`] = `./c${i}.html`; |
| 87 | } |
| 88 | const compiler = webpack({ |
| 89 | context: class="st">"/src", |
| 90 | mode, |
| 91 | entry, |
| 92 | output: { path: class="st">"/out", filename: class="st">"[name].js" }, |
| 93 | target: class="st">"web", |
| 94 | experiments: { html: true }, |
| 95 | module: { parser: { html: { sources: false } } } |
| 96 | }); |
| 97 | compiler.inputFileSystem = mfs; |
| 98 | compiler.outputFileSystem = mfs; |
| 99 | compiler.run((err, stats) => { |
| 100 | /** @type {Map<number, string[]>} */ |
| 101 | const internalByEntry = new Map(); |
| 102 | /** |
| 103 | * @param {number} i entry index |
| 104 | * @param {string} line message |
| 105 | */ |
| 106 | const add = (i, line) => { |
| 107 | if (!internalByEntry.has(i)) internalByEntry.set(i, []); |
| 108 | internalByEntry.get(i).push(line); |
| 109 | }; |
| 110 | if (err) { |
| 111 | class="cm">// Compiler-level throw can't be attributed to one entry; mark all. |
| 112 | const line = String(err.message).split(class="st">"\n")[0].slice(0, 160); |
| 113 | for (const i of inputs.keys()) add(i, line); |
| 114 | resolve(internalByEntry); |
| 115 | return; |
| 116 | } |
| 117 | const json = stats.toJson({ errors: true, warnings: true }); |
| 118 | for (const item of [...json.errors, ...json.warnings]) { |
| 119 | if (!INTERNAL.test(item.message)) continue; |
| 120 | const line = item.message.split(class="st">"\n")[0].slice(0, 160); |
| 121 | const match = /c(\d+)\.html/.exec(item.moduleName || class="st">""); |
| 122 | if (match) add(Number(match[1]), line); |
| 123 | else for (const i of inputs.keys()) add(i, line); |
| 124 | } |
| 125 | compiler.close(() => resolve(internalByEntry)); |
| 126 | }); |
| 127 | }); |
| 128 | |
| 129 | const tokenizerCases = |
| 130 | fs.existsSync(tokenizerDir) && fs.readdirSync(tokenizerDir).length > 0 |