@ggui-ai/ui-gen 0.15.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/generation-dispatch.d.ts +24 -4
- package/dist/adapters/generation-dispatch.js +5188 -3920
- package/dist/adapters/generation-dispatch.js.map +1 -1
- package/dist/adapters/index.js +33 -26
- package/dist/adapters/index.js.map +1 -1
- package/dist/advanced/index.d.ts +22 -13
- package/dist/advanced/index.js +4889 -3561
- package/dist/advanced/index.js.map +1 -1
- package/dist/blueprint-validator.js +8 -12
- package/dist/blueprint-validator.js.map +1 -1
- package/dist/boilerplate.d.ts +19 -1
- package/dist/boilerplate.js +671 -254
- package/dist/boilerplate.js.map +1 -1
- package/dist/check/index.d.ts +17 -3
- package/dist/check/index.js +34 -25
- package/dist/check/index.js.map +1 -1
- package/dist/compose.js +1 -1
- package/dist/compose.js.map +1 -1
- package/dist/create-ui-generator-C8Ki9Wz1.d.ts +189 -0
- package/dist/design-mode-DLufhrNp.d.ts +61 -0
- package/dist/{dispatch-BuZfTh9r.d.ts → dispatch-D2htzi9h.d.ts} +4 -1
- package/dist/evaluation/axis-checks/index.d.ts +4 -3
- package/dist/evaluation/axis-checks/index.js +300 -14
- package/dist/evaluation/axis-checks/index.js.map +1 -1
- package/dist/evaluation/axis-checks/registry.d.ts +2 -1
- package/dist/evaluation/axis-checks/registry.js +253 -1
- package/dist/evaluation/axis-checks/registry.js.map +1 -1
- package/dist/evaluation/index.d.ts +297 -5
- package/dist/evaluation/index.js +4515 -120
- package/dist/evaluation/index.js.map +1 -1
- package/dist/fragments/index.js +1 -1
- package/dist/fragments/index.js.map +1 -1
- package/dist/{generate-BTfvELgl.d.ts → generate-9IeNT4ZY.d.ts} +10 -1
- package/dist/harness/check/runtime-render/index.d.ts +3 -1
- package/dist/harness/check/runtime-render/index.js +8 -12
- package/dist/harness/check/runtime-render/index.js.map +1 -1
- package/dist/harness/index.d.ts +3 -1
- package/dist/harness/index.js +913 -441
- package/dist/harness/index.js.map +1 -1
- package/dist/harness/llm-trace-sink.d.ts +3 -3
- package/dist/harness/llm-trace-sink.js.map +1 -1
- package/dist/harness/prompts.d.ts +2 -1
- package/dist/harness/prompts.js +6 -3
- package/dist/harness/prompts.js.map +1 -1
- package/dist/harness/result-types.d.ts +17 -5
- package/dist/harness/result-types.js.map +1 -1
- package/dist/harness/runtime.d.ts +28 -3
- package/dist/harness/runtime.js +702 -274
- package/dist/harness/runtime.js.map +1 -1
- package/dist/harness/types-public.d.ts +39 -1
- package/dist/harness/types-public.js +913 -441
- package/dist/harness/types-public.js.map +1 -1
- package/dist/harness/validator-trace-sink.d.ts +2 -1
- package/dist/index.d.ts +32 -6
- package/dist/index.js +4899 -3560
- package/dist/index.js.map +1 -1
- package/dist/patch.d.ts +3 -1
- package/dist/{prompts-BVhtH3M1.d.ts → prompts-YU9piOgs.d.ts} +21 -45
- package/dist/providers/index.d.ts +2 -2
- package/dist/providers/index.js.map +1 -1
- package/dist/styling-profile-CxfvV48g.d.ts +35 -0
- package/dist/tools/get-primitives-ts.d.ts +1 -1
- package/dist/tools/get-primitives-ts.js +1 -1
- package/dist/tools/get-primitives-ts.js.map +1 -1
- package/dist/{types-public-CkNWEov9.d.ts → types-public-DVSssdc-.d.ts} +85 -5
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +4 -4
- package/dist/validation/index.js.map +1 -1
- package/dist/workflows.d.ts +3 -1
- package/package.json +12 -12
- package/src/adapters/generation-dispatch.ts +62 -4
- package/src/adapters/provider-router.ts +7 -6
- package/src/adapters/tools.ts +5 -5
- package/src/advanced/generator.ts +11 -10
- package/src/advanced/index.ts +5 -4
- package/src/boilerplate/free-design-prompt.ts +336 -0
- package/src/boilerplate/generate.ts +10 -1
- package/src/boilerplate/hard-sections.ts +257 -0
- package/src/boilerplate/render.ts +32 -8
- package/src/boilerplate/styling-profile.ts +166 -0
- package/src/boilerplate/system-prompt.ts +101 -237
- package/src/boilerplate/templates/base-free.tsx.tmpl +24 -0
- package/src/check/run-tier0.ts +82 -20
- package/src/coding-agent/tools.ts +8 -2
- package/src/contract-context.ts +43 -14
- package/src/create-harness.ts +15 -0
- package/src/create-ui-generator.ts +112 -27
- package/src/design-mode.ts +192 -0
- package/src/design-system-docs.ts +24 -17
- package/src/effort.ts +48 -0
- package/src/evaluation/axis-checks/checks/grid.ts +148 -0
- package/src/evaluation/axis-checks/checks/universal.ts +244 -0
- package/src/evaluation/axis-checks/dispatch.ts +82 -13
- package/src/evaluation/axis-checks/extras.ts +5 -0
- package/src/evaluation/axis-checks/helpers.ts +12 -0
- package/src/evaluation/axis-checks/registry.ts +2 -0
- package/src/evaluation/cost-tracker.ts +2 -3
- package/src/evaluation/design-identity.ts +96 -0
- package/src/evaluation/index.ts +63 -2
- package/src/evaluation/llm-evaluator.ts +89 -21
- package/src/evaluation/theme-css.ts +14 -0
- package/src/evaluation/types-public.ts +137 -8
- package/src/evaluation/visual-evaluator.ts +759 -54
- package/src/fragments/render.ts +1 -1
- package/src/harness/check/runtime-render/prepare-mockup.ts +18 -11
- package/src/harness/coding/dupe-break.ts +0 -0
- package/src/harness/coding/init-session.ts +2 -0
- package/src/harness/coding/run-coding-turn.ts +9 -14
- package/src/harness/coding/run-eval-round.ts +46 -5
- package/src/harness/llm-trace-sink.ts +3 -3
- package/src/harness/result-types.ts +15 -3
- package/src/harness/runtime.ts +28 -0
- package/src/harness/types-public.ts +38 -0
- package/src/index.ts +28 -0
- package/src/internal/extract-call-signatures.ts +2 -2
- package/src/pin-fixtures.ts +98 -0
- package/src/providers/bedrock.ts +4 -4
- package/src/run-check.ts +11 -10
- package/src/tools/get-primitives-ts.ts +1 -1
- package/src/tools.ts +2 -1
- package/src/validation/allowed-imports.ts +8 -2
- package/src/validation/primitives.ts +1 -1
- package/dist/create-ui-generator-D6TKuv9V.d.ts +0 -106
package/dist/evaluation/index.js
CHANGED
|
@@ -1,129 +1,3418 @@
|
|
|
1
|
+
import { readFileSync, readdirSync, statSync, mkdirSync, writeFileSync, unlinkSync, existsSync, rm, createReadStream, createWriteStream } from 'fs';
|
|
2
|
+
import 'fs/promises';
|
|
3
|
+
import { tmpdir } from 'os';
|
|
4
|
+
import { resolve, dirname, join, basename } from 'path';
|
|
5
|
+
import { Readable } from 'stream';
|
|
6
|
+
import { pipeline } from 'stream/promises';
|
|
7
|
+
import { createBrotliDecompress, createUnzip } from 'zlib';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
1
9
|
import { query, createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';
|
|
2
10
|
import Anthropic from '@anthropic-ai/sdk';
|
|
3
11
|
import { z } from 'zod';
|
|
4
|
-
import {
|
|
5
|
-
import '
|
|
6
|
-
import '
|
|
12
|
+
import { LUCIDE_ICON_NAMES } from '@ggui-ai/design';
|
|
13
|
+
import { listContractGadgets, HOOK_NAME_RE, STDLIB_GADGETS_PACKAGE, APP_GENERATION_PROFILE_BOUNDS } from '@ggui-ai/protocol';
|
|
14
|
+
import { createHash } from 'crypto';
|
|
15
|
+
import { build } from 'esbuild';
|
|
16
|
+
import { getCssTokens, composeThemeCss, fillFitRule } from '@ggui-ai/design/rendering';
|
|
17
|
+
import { createRequire } from 'module';
|
|
7
18
|
|
|
19
|
+
var __create = Object.create;
|
|
8
20
|
var __defProp = Object.defineProperty;
|
|
21
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
22
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
23
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
24
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
25
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
26
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
27
|
+
}) : x)(function(x) {
|
|
28
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
29
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
30
|
+
});
|
|
10
31
|
var __esm = (fn, res) => function __init() {
|
|
11
32
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
12
33
|
};
|
|
34
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
35
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
36
|
+
};
|
|
13
37
|
var __export = (target, all) => {
|
|
14
38
|
for (var name in all)
|
|
15
39
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
40
|
};
|
|
41
|
+
var __copyProps = (to, from, except, desc) => {
|
|
42
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
43
|
+
for (let key of __getOwnPropNames(from))
|
|
44
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
45
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
46
|
+
}
|
|
47
|
+
return to;
|
|
48
|
+
};
|
|
49
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
50
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
51
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
52
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
53
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
54
|
+
__defProp(target, "default", { value: mod, enumerable: true }) ,
|
|
55
|
+
mod
|
|
56
|
+
));
|
|
57
|
+
|
|
58
|
+
// src/adapters/openrouter/types.ts
|
|
59
|
+
var OpenRouterError;
|
|
60
|
+
var init_types = __esm({
|
|
61
|
+
"src/adapters/openrouter/types.ts"() {
|
|
62
|
+
OpenRouterError = class extends Error {
|
|
63
|
+
constructor(message, status, code, headers) {
|
|
64
|
+
super(message);
|
|
65
|
+
this.status = status;
|
|
66
|
+
this.code = code;
|
|
67
|
+
this.headers = headers;
|
|
68
|
+
this.name = "OpenRouterError";
|
|
69
|
+
}
|
|
70
|
+
status;
|
|
71
|
+
code;
|
|
72
|
+
headers;
|
|
73
|
+
get isTransient() {
|
|
74
|
+
return this.status === 408 || this.status === 429 || this.status === 502 || this.status === 503;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// src/adapters/openrouter/client.ts
|
|
81
|
+
var client_exports = {};
|
|
82
|
+
__export(client_exports, {
|
|
83
|
+
OpenRouterClient: () => OpenRouterClient
|
|
84
|
+
});
|
|
85
|
+
var DEFAULT_BASE_URL, OpenRouterClient;
|
|
86
|
+
var init_client = __esm({
|
|
87
|
+
"src/adapters/openrouter/client.ts"() {
|
|
88
|
+
init_types();
|
|
89
|
+
DEFAULT_BASE_URL = "https://openrouter.ai/api/v1";
|
|
90
|
+
OpenRouterClient = class {
|
|
91
|
+
constructor(config) {
|
|
92
|
+
this.config = config;
|
|
93
|
+
this.baseUrl = config.baseUrl ?? process.env.OPENROUTER_BASE_URL ?? DEFAULT_BASE_URL;
|
|
94
|
+
this.headers = {
|
|
95
|
+
"Authorization": `Bearer ${config.apiKey}`,
|
|
96
|
+
"Content-Type": "application/json",
|
|
97
|
+
"HTTP-Referer": config.siteUrl ?? process.env.OPENROUTER_SITE_URL ?? "https://ggui.ai",
|
|
98
|
+
"X-Title": config.siteName ?? process.env.OPENROUTER_SITE_NAME ?? "ggui"
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
config;
|
|
102
|
+
baseUrl;
|
|
103
|
+
headers;
|
|
104
|
+
/**
|
|
105
|
+
* Non-streaming chat completion.
|
|
106
|
+
*/
|
|
107
|
+
async chatCompletion(params) {
|
|
108
|
+
const body = { ...params, stream: false };
|
|
109
|
+
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
|
110
|
+
method: "POST",
|
|
111
|
+
headers: this.headers,
|
|
112
|
+
body: JSON.stringify(body)
|
|
113
|
+
});
|
|
114
|
+
if (!response.ok) {
|
|
115
|
+
const errorBody = await response.json().catch(() => ({ error: { message: response.statusText } }));
|
|
116
|
+
const message = errorBody.error?.message ?? response.statusText;
|
|
117
|
+
throw new OpenRouterError(message, response.status, void 0, response.headers);
|
|
118
|
+
}
|
|
119
|
+
return response.json();
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Streaming chat completion via SSE.
|
|
123
|
+
* Yields delta chunks, accumulates the final usage from the last chunk.
|
|
124
|
+
*/
|
|
125
|
+
async *chatCompletionStream(params) {
|
|
126
|
+
const body = { ...params, stream: true };
|
|
127
|
+
const response = await fetch(`${this.baseUrl}/chat/completions`, {
|
|
128
|
+
method: "POST",
|
|
129
|
+
headers: this.headers,
|
|
130
|
+
body: JSON.stringify(body)
|
|
131
|
+
});
|
|
132
|
+
if (!response.ok) {
|
|
133
|
+
const errorBody = await response.json().catch(() => ({ error: { message: response.statusText } }));
|
|
134
|
+
const message = errorBody.error?.message ?? response.statusText;
|
|
135
|
+
throw new OpenRouterError(message, response.status, void 0, response.headers);
|
|
136
|
+
}
|
|
137
|
+
if (!response.body) {
|
|
138
|
+
throw new OpenRouterError("No response body for streaming request", 500);
|
|
139
|
+
}
|
|
140
|
+
const reader = response.body.getReader();
|
|
141
|
+
const decoder = new TextDecoder();
|
|
142
|
+
let buffer = "";
|
|
143
|
+
try {
|
|
144
|
+
while (true) {
|
|
145
|
+
const { done, value } = await reader.read();
|
|
146
|
+
if (done) break;
|
|
147
|
+
buffer += decoder.decode(value, { stream: true });
|
|
148
|
+
const lines = buffer.split("\n");
|
|
149
|
+
buffer = lines.pop() ?? "";
|
|
150
|
+
for (const line of lines) {
|
|
151
|
+
const trimmed = line.trim();
|
|
152
|
+
if (!trimmed || trimmed.startsWith(":")) continue;
|
|
153
|
+
if (trimmed === "data: [DONE]") return;
|
|
154
|
+
if (!trimmed.startsWith("data: ")) continue;
|
|
155
|
+
const json = trimmed.slice("data: ".length);
|
|
156
|
+
try {
|
|
157
|
+
yield JSON.parse(json);
|
|
158
|
+
} catch {
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
} finally {
|
|
163
|
+
reader.releaseLock();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// ../../node_modules/events-universal/default.js
|
|
171
|
+
var require_default = __commonJS({
|
|
172
|
+
"../../node_modules/events-universal/default.js"(exports, module) {
|
|
173
|
+
module.exports = __require("events");
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// ../../node_modules/fast-fifo/fixed-size.js
|
|
178
|
+
var require_fixed_size = __commonJS({
|
|
179
|
+
"../../node_modules/fast-fifo/fixed-size.js"(exports, module) {
|
|
180
|
+
module.exports = class FixedFIFO {
|
|
181
|
+
constructor(hwm) {
|
|
182
|
+
if (!(hwm > 0) || (hwm - 1 & hwm) !== 0) throw new Error("Max size for a FixedFIFO should be a power of two");
|
|
183
|
+
this.buffer = new Array(hwm);
|
|
184
|
+
this.mask = hwm - 1;
|
|
185
|
+
this.top = 0;
|
|
186
|
+
this.btm = 0;
|
|
187
|
+
this.next = null;
|
|
188
|
+
}
|
|
189
|
+
clear() {
|
|
190
|
+
this.top = this.btm = 0;
|
|
191
|
+
this.next = null;
|
|
192
|
+
this.buffer.fill(void 0);
|
|
193
|
+
}
|
|
194
|
+
push(data) {
|
|
195
|
+
if (this.buffer[this.top] !== void 0) return false;
|
|
196
|
+
this.buffer[this.top] = data;
|
|
197
|
+
this.top = this.top + 1 & this.mask;
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
shift() {
|
|
201
|
+
const last = this.buffer[this.btm];
|
|
202
|
+
if (last === void 0) return void 0;
|
|
203
|
+
this.buffer[this.btm] = void 0;
|
|
204
|
+
this.btm = this.btm + 1 & this.mask;
|
|
205
|
+
return last;
|
|
206
|
+
}
|
|
207
|
+
peek() {
|
|
208
|
+
return this.buffer[this.btm];
|
|
209
|
+
}
|
|
210
|
+
isEmpty() {
|
|
211
|
+
return this.buffer[this.btm] === void 0;
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// ../../node_modules/fast-fifo/index.js
|
|
218
|
+
var require_fast_fifo = __commonJS({
|
|
219
|
+
"../../node_modules/fast-fifo/index.js"(exports, module) {
|
|
220
|
+
var FixedFIFO = require_fixed_size();
|
|
221
|
+
module.exports = class FastFIFO {
|
|
222
|
+
constructor(hwm) {
|
|
223
|
+
this.hwm = hwm || 16;
|
|
224
|
+
this.head = new FixedFIFO(this.hwm);
|
|
225
|
+
this.tail = this.head;
|
|
226
|
+
this.length = 0;
|
|
227
|
+
}
|
|
228
|
+
clear() {
|
|
229
|
+
this.head = this.tail;
|
|
230
|
+
this.head.clear();
|
|
231
|
+
this.length = 0;
|
|
232
|
+
}
|
|
233
|
+
push(val) {
|
|
234
|
+
this.length++;
|
|
235
|
+
if (!this.head.push(val)) {
|
|
236
|
+
const prev = this.head;
|
|
237
|
+
this.head = prev.next = new FixedFIFO(2 * this.head.buffer.length);
|
|
238
|
+
this.head.push(val);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
shift() {
|
|
242
|
+
if (this.length !== 0) this.length--;
|
|
243
|
+
const val = this.tail.shift();
|
|
244
|
+
if (val === void 0 && this.tail.next) {
|
|
245
|
+
const next = this.tail.next;
|
|
246
|
+
this.tail.next = null;
|
|
247
|
+
this.tail = next;
|
|
248
|
+
return this.tail.shift();
|
|
249
|
+
}
|
|
250
|
+
return val;
|
|
251
|
+
}
|
|
252
|
+
peek() {
|
|
253
|
+
const val = this.tail.peek();
|
|
254
|
+
if (val === void 0 && this.tail.next) return this.tail.next.peek();
|
|
255
|
+
return val;
|
|
256
|
+
}
|
|
257
|
+
isEmpty() {
|
|
258
|
+
return this.length === 0;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
// ../../node_modules/b4a/index.js
|
|
265
|
+
var require_b4a = __commonJS({
|
|
266
|
+
"../../node_modules/b4a/index.js"(exports, module) {
|
|
267
|
+
function isBuffer(value) {
|
|
268
|
+
return Buffer.isBuffer(value) || value instanceof Uint8Array;
|
|
269
|
+
}
|
|
270
|
+
function isEncoding(encoding) {
|
|
271
|
+
return Buffer.isEncoding(encoding);
|
|
272
|
+
}
|
|
273
|
+
function alloc(size, fill2, encoding) {
|
|
274
|
+
return Buffer.alloc(size, fill2, encoding);
|
|
275
|
+
}
|
|
276
|
+
function allocUnsafe(size) {
|
|
277
|
+
return Buffer.allocUnsafe(size);
|
|
278
|
+
}
|
|
279
|
+
function allocUnsafeSlow(size) {
|
|
280
|
+
return Buffer.allocUnsafeSlow(size);
|
|
281
|
+
}
|
|
282
|
+
function byteLength(string, encoding) {
|
|
283
|
+
return Buffer.byteLength(string, encoding);
|
|
284
|
+
}
|
|
285
|
+
function compare(a, b) {
|
|
286
|
+
return Buffer.compare(a, b);
|
|
287
|
+
}
|
|
288
|
+
function concat(buffers, totalLength) {
|
|
289
|
+
return Buffer.concat(buffers, totalLength);
|
|
290
|
+
}
|
|
291
|
+
function copy(source, target, targetStart, start, end) {
|
|
292
|
+
return toBuffer(source).copy(target, targetStart, start, end);
|
|
293
|
+
}
|
|
294
|
+
function equals(a, b) {
|
|
295
|
+
return toBuffer(a).equals(b);
|
|
296
|
+
}
|
|
297
|
+
function fill(buffer, value, offset, end, encoding) {
|
|
298
|
+
return toBuffer(buffer).fill(value, offset, end, encoding);
|
|
299
|
+
}
|
|
300
|
+
function from(value, encodingOrOffset, length) {
|
|
301
|
+
return Buffer.from(value, encodingOrOffset, length);
|
|
302
|
+
}
|
|
303
|
+
function includes(buffer, value, byteOffset, encoding) {
|
|
304
|
+
return toBuffer(buffer).includes(value, byteOffset, encoding);
|
|
305
|
+
}
|
|
306
|
+
function indexOf(buffer, value, byfeOffset, encoding) {
|
|
307
|
+
return toBuffer(buffer).indexOf(value, byfeOffset, encoding);
|
|
308
|
+
}
|
|
309
|
+
function lastIndexOf(buffer, value, byteOffset, encoding) {
|
|
310
|
+
return toBuffer(buffer).lastIndexOf(value, byteOffset, encoding);
|
|
311
|
+
}
|
|
312
|
+
function swap16(buffer) {
|
|
313
|
+
return toBuffer(buffer).swap16();
|
|
314
|
+
}
|
|
315
|
+
function swap32(buffer) {
|
|
316
|
+
return toBuffer(buffer).swap32();
|
|
317
|
+
}
|
|
318
|
+
function swap64(buffer) {
|
|
319
|
+
return toBuffer(buffer).swap64();
|
|
320
|
+
}
|
|
321
|
+
function toBuffer(buffer) {
|
|
322
|
+
if (Buffer.isBuffer(buffer)) return buffer;
|
|
323
|
+
return Buffer.from(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
324
|
+
}
|
|
325
|
+
function toString(buffer, encoding, start, end) {
|
|
326
|
+
return toBuffer(buffer).toString(encoding, start, end);
|
|
327
|
+
}
|
|
328
|
+
function write(buffer, string, offset, length, encoding) {
|
|
329
|
+
return toBuffer(buffer).write(string, offset, length, encoding);
|
|
330
|
+
}
|
|
331
|
+
function readDoubleBE(buffer, offset) {
|
|
332
|
+
return toBuffer(buffer).readDoubleBE(offset);
|
|
333
|
+
}
|
|
334
|
+
function readDoubleLE(buffer, offset) {
|
|
335
|
+
return toBuffer(buffer).readDoubleLE(offset);
|
|
336
|
+
}
|
|
337
|
+
function readFloatBE(buffer, offset) {
|
|
338
|
+
return toBuffer(buffer).readFloatBE(offset);
|
|
339
|
+
}
|
|
340
|
+
function readFloatLE(buffer, offset) {
|
|
341
|
+
return toBuffer(buffer).readFloatLE(offset);
|
|
342
|
+
}
|
|
343
|
+
function readInt32BE(buffer, offset) {
|
|
344
|
+
return toBuffer(buffer).readInt32BE(offset);
|
|
345
|
+
}
|
|
346
|
+
function readInt32LE(buffer, offset) {
|
|
347
|
+
return toBuffer(buffer).readInt32LE(offset);
|
|
348
|
+
}
|
|
349
|
+
function readUInt32BE(buffer, offset) {
|
|
350
|
+
return toBuffer(buffer).readUInt32BE(offset);
|
|
351
|
+
}
|
|
352
|
+
function readUInt32LE(buffer, offset) {
|
|
353
|
+
return toBuffer(buffer).readUInt32LE(offset);
|
|
354
|
+
}
|
|
355
|
+
function writeDoubleBE(buffer, value, offset) {
|
|
356
|
+
return toBuffer(buffer).writeDoubleBE(value, offset);
|
|
357
|
+
}
|
|
358
|
+
function writeDoubleLE(buffer, value, offset) {
|
|
359
|
+
return toBuffer(buffer).writeDoubleLE(value, offset);
|
|
360
|
+
}
|
|
361
|
+
function writeFloatBE(buffer, value, offset) {
|
|
362
|
+
return toBuffer(buffer).writeFloatBE(value, offset);
|
|
363
|
+
}
|
|
364
|
+
function writeFloatLE(buffer, value, offset) {
|
|
365
|
+
return toBuffer(buffer).writeFloatLE(value, offset);
|
|
366
|
+
}
|
|
367
|
+
function writeInt32BE(buffer, value, offset) {
|
|
368
|
+
return toBuffer(buffer).writeInt32BE(value, offset);
|
|
369
|
+
}
|
|
370
|
+
function writeInt32LE(buffer, value, offset) {
|
|
371
|
+
return toBuffer(buffer).writeInt32LE(value, offset);
|
|
372
|
+
}
|
|
373
|
+
function writeUInt32BE(buffer, value, offset) {
|
|
374
|
+
return toBuffer(buffer).writeUInt32BE(value, offset);
|
|
375
|
+
}
|
|
376
|
+
function writeUInt32LE(buffer, value, offset) {
|
|
377
|
+
return toBuffer(buffer).writeUInt32LE(value, offset);
|
|
378
|
+
}
|
|
379
|
+
module.exports = {
|
|
380
|
+
isBuffer,
|
|
381
|
+
isEncoding,
|
|
382
|
+
alloc,
|
|
383
|
+
allocUnsafe,
|
|
384
|
+
allocUnsafeSlow,
|
|
385
|
+
byteLength,
|
|
386
|
+
compare,
|
|
387
|
+
concat,
|
|
388
|
+
copy,
|
|
389
|
+
equals,
|
|
390
|
+
fill,
|
|
391
|
+
from,
|
|
392
|
+
includes,
|
|
393
|
+
indexOf,
|
|
394
|
+
lastIndexOf,
|
|
395
|
+
swap16,
|
|
396
|
+
swap32,
|
|
397
|
+
swap64,
|
|
398
|
+
toBuffer,
|
|
399
|
+
toString,
|
|
400
|
+
write,
|
|
401
|
+
readDoubleBE,
|
|
402
|
+
readDoubleLE,
|
|
403
|
+
readFloatBE,
|
|
404
|
+
readFloatLE,
|
|
405
|
+
readInt32BE,
|
|
406
|
+
readInt32LE,
|
|
407
|
+
readUInt32BE,
|
|
408
|
+
readUInt32LE,
|
|
409
|
+
writeDoubleBE,
|
|
410
|
+
writeDoubleLE,
|
|
411
|
+
writeFloatBE,
|
|
412
|
+
writeFloatLE,
|
|
413
|
+
writeInt32BE,
|
|
414
|
+
writeInt32LE,
|
|
415
|
+
writeUInt32BE,
|
|
416
|
+
writeUInt32LE
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
// ../../node_modules/text-decoder/lib/pass-through-decoder.js
|
|
422
|
+
var require_pass_through_decoder = __commonJS({
|
|
423
|
+
"../../node_modules/text-decoder/lib/pass-through-decoder.js"(exports, module) {
|
|
424
|
+
var b4a = require_b4a();
|
|
425
|
+
module.exports = class PassThroughDecoder {
|
|
426
|
+
constructor(encoding) {
|
|
427
|
+
this.encoding = encoding;
|
|
428
|
+
}
|
|
429
|
+
get remaining() {
|
|
430
|
+
return 0;
|
|
431
|
+
}
|
|
432
|
+
decode(data) {
|
|
433
|
+
return b4a.toString(data, this.encoding);
|
|
434
|
+
}
|
|
435
|
+
flush() {
|
|
436
|
+
return "";
|
|
437
|
+
}
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
// ../../node_modules/text-decoder/lib/utf8-decoder.js
|
|
443
|
+
var require_utf8_decoder = __commonJS({
|
|
444
|
+
"../../node_modules/text-decoder/lib/utf8-decoder.js"(exports, module) {
|
|
445
|
+
var b4a = require_b4a();
|
|
446
|
+
module.exports = class UTF8Decoder {
|
|
447
|
+
constructor() {
|
|
448
|
+
this._reset();
|
|
449
|
+
}
|
|
450
|
+
get remaining() {
|
|
451
|
+
return this.bytesSeen;
|
|
452
|
+
}
|
|
453
|
+
decode(data) {
|
|
454
|
+
if (data.byteLength === 0) return "";
|
|
455
|
+
if (this.bytesNeeded === 0 && trailingIncomplete(data, 0) === 0) {
|
|
456
|
+
this.bytesSeen = trailingBytesSeen(data);
|
|
457
|
+
return b4a.toString(data, "utf8");
|
|
458
|
+
}
|
|
459
|
+
let result = "";
|
|
460
|
+
let start = 0;
|
|
461
|
+
if (this.bytesNeeded > 0) {
|
|
462
|
+
while (start < data.byteLength) {
|
|
463
|
+
const byte = data[start];
|
|
464
|
+
if (byte < this.lowerBoundary || byte > this.upperBoundary) {
|
|
465
|
+
result += "\uFFFD";
|
|
466
|
+
this._reset();
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
this.lowerBoundary = 128;
|
|
470
|
+
this.upperBoundary = 191;
|
|
471
|
+
this.codePoint = this.codePoint << 6 | byte & 63;
|
|
472
|
+
this.bytesSeen++;
|
|
473
|
+
start++;
|
|
474
|
+
if (this.bytesSeen === this.bytesNeeded) {
|
|
475
|
+
result += String.fromCodePoint(this.codePoint);
|
|
476
|
+
this._reset();
|
|
477
|
+
break;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
if (this.bytesNeeded > 0) return result;
|
|
481
|
+
}
|
|
482
|
+
const trailing = trailingIncomplete(data, start);
|
|
483
|
+
const end = data.byteLength - trailing;
|
|
484
|
+
if (end > start) result += b4a.toString(data, "utf8", start, end);
|
|
485
|
+
for (let i = end; i < data.byteLength; i++) {
|
|
486
|
+
const byte = data[i];
|
|
487
|
+
if (this.bytesNeeded === 0) {
|
|
488
|
+
if (byte <= 127) {
|
|
489
|
+
this.bytesSeen = 0;
|
|
490
|
+
result += String.fromCharCode(byte);
|
|
491
|
+
} else if (byte >= 194 && byte <= 223) {
|
|
492
|
+
this.bytesNeeded = 2;
|
|
493
|
+
this.bytesSeen = 1;
|
|
494
|
+
this.codePoint = byte & 31;
|
|
495
|
+
} else if (byte >= 224 && byte <= 239) {
|
|
496
|
+
if (byte === 224) this.lowerBoundary = 160;
|
|
497
|
+
else if (byte === 237) this.upperBoundary = 159;
|
|
498
|
+
this.bytesNeeded = 3;
|
|
499
|
+
this.bytesSeen = 1;
|
|
500
|
+
this.codePoint = byte & 15;
|
|
501
|
+
} else if (byte >= 240 && byte <= 244) {
|
|
502
|
+
if (byte === 240) this.lowerBoundary = 144;
|
|
503
|
+
else if (byte === 244) this.upperBoundary = 143;
|
|
504
|
+
this.bytesNeeded = 4;
|
|
505
|
+
this.bytesSeen = 1;
|
|
506
|
+
this.codePoint = byte & 7;
|
|
507
|
+
} else {
|
|
508
|
+
this.bytesSeen = 1;
|
|
509
|
+
result += "\uFFFD";
|
|
510
|
+
}
|
|
511
|
+
continue;
|
|
512
|
+
}
|
|
513
|
+
if (byte < this.lowerBoundary || byte > this.upperBoundary) {
|
|
514
|
+
result += "\uFFFD";
|
|
515
|
+
i--;
|
|
516
|
+
this._reset();
|
|
517
|
+
continue;
|
|
518
|
+
}
|
|
519
|
+
this.lowerBoundary = 128;
|
|
520
|
+
this.upperBoundary = 191;
|
|
521
|
+
this.codePoint = this.codePoint << 6 | byte & 63;
|
|
522
|
+
this.bytesSeen++;
|
|
523
|
+
if (this.bytesSeen === this.bytesNeeded) {
|
|
524
|
+
result += String.fromCodePoint(this.codePoint);
|
|
525
|
+
this._reset();
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return result;
|
|
529
|
+
}
|
|
530
|
+
flush() {
|
|
531
|
+
const result = this.bytesNeeded > 0 ? "\uFFFD" : "";
|
|
532
|
+
this._reset();
|
|
533
|
+
return result;
|
|
534
|
+
}
|
|
535
|
+
_reset() {
|
|
536
|
+
this.codePoint = 0;
|
|
537
|
+
this.bytesNeeded = 0;
|
|
538
|
+
this.bytesSeen = 0;
|
|
539
|
+
this.lowerBoundary = 128;
|
|
540
|
+
this.upperBoundary = 191;
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
function trailingIncomplete(data, start) {
|
|
544
|
+
const len = data.byteLength;
|
|
545
|
+
if (len <= start) return 0;
|
|
546
|
+
const limit = Math.max(start, len - 4);
|
|
547
|
+
let i = len - 1;
|
|
548
|
+
while (i > limit && (data[i] & 192) === 128) i--;
|
|
549
|
+
if (i < start) return 0;
|
|
550
|
+
const byte = data[i];
|
|
551
|
+
let needed;
|
|
552
|
+
if (byte <= 127) return 0;
|
|
553
|
+
if (byte >= 194 && byte <= 223) needed = 2;
|
|
554
|
+
else if (byte >= 224 && byte <= 239) needed = 3;
|
|
555
|
+
else if (byte >= 240 && byte <= 244) needed = 4;
|
|
556
|
+
else return 0;
|
|
557
|
+
const available = len - i;
|
|
558
|
+
return available < needed ? available : 0;
|
|
559
|
+
}
|
|
560
|
+
function trailingBytesSeen(data) {
|
|
561
|
+
const len = data.byteLength;
|
|
562
|
+
if (len === 0) return 0;
|
|
563
|
+
const last = data[len - 1];
|
|
564
|
+
if (last <= 127) return 0;
|
|
565
|
+
if ((last & 192) !== 128) return 1;
|
|
566
|
+
const limit = Math.max(0, len - 4);
|
|
567
|
+
let i = len - 2;
|
|
568
|
+
while (i >= limit && (data[i] & 192) === 128) i--;
|
|
569
|
+
if (i < 0) return 1;
|
|
570
|
+
const first = data[i];
|
|
571
|
+
let needed;
|
|
572
|
+
if (first >= 194 && first <= 223) needed = 2;
|
|
573
|
+
else if (first >= 224 && first <= 239) needed = 3;
|
|
574
|
+
else if (first >= 240 && first <= 244) needed = 4;
|
|
575
|
+
else return 1;
|
|
576
|
+
if (len - i !== needed) return 1;
|
|
577
|
+
if (needed >= 3) {
|
|
578
|
+
const second = data[i + 1];
|
|
579
|
+
if (first === 224 && second < 160) return 1;
|
|
580
|
+
if (first === 237 && second > 159) return 1;
|
|
581
|
+
if (first === 240 && second < 144) return 1;
|
|
582
|
+
if (first === 244 && second > 143) return 1;
|
|
583
|
+
}
|
|
584
|
+
return 0;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
// ../../node_modules/text-decoder/index.js
|
|
590
|
+
var require_text_decoder = __commonJS({
|
|
591
|
+
"../../node_modules/text-decoder/index.js"(exports, module) {
|
|
592
|
+
var PassThroughDecoder = require_pass_through_decoder();
|
|
593
|
+
var UTF8Decoder = require_utf8_decoder();
|
|
594
|
+
module.exports = class TextDecoder {
|
|
595
|
+
constructor(encoding = "utf8") {
|
|
596
|
+
this.encoding = normalizeEncoding(encoding);
|
|
597
|
+
switch (this.encoding) {
|
|
598
|
+
case "utf8":
|
|
599
|
+
this.decoder = new UTF8Decoder();
|
|
600
|
+
break;
|
|
601
|
+
case "utf16le":
|
|
602
|
+
case "base64":
|
|
603
|
+
throw new Error("Unsupported encoding: " + this.encoding);
|
|
604
|
+
default:
|
|
605
|
+
this.decoder = new PassThroughDecoder(this.encoding);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
get remaining() {
|
|
609
|
+
return this.decoder.remaining;
|
|
610
|
+
}
|
|
611
|
+
push(data) {
|
|
612
|
+
if (typeof data === "string") return data;
|
|
613
|
+
return this.decoder.decode(data);
|
|
614
|
+
}
|
|
615
|
+
// For Node.js compatibility
|
|
616
|
+
write(data) {
|
|
617
|
+
return this.push(data);
|
|
618
|
+
}
|
|
619
|
+
end(data) {
|
|
620
|
+
let result = "";
|
|
621
|
+
if (data) result = this.push(data);
|
|
622
|
+
result += this.decoder.flush();
|
|
623
|
+
return result;
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
function normalizeEncoding(encoding) {
|
|
627
|
+
encoding = encoding.toLowerCase();
|
|
628
|
+
switch (encoding) {
|
|
629
|
+
case "utf8":
|
|
630
|
+
case "utf-8":
|
|
631
|
+
return "utf8";
|
|
632
|
+
case "ucs2":
|
|
633
|
+
case "ucs-2":
|
|
634
|
+
case "utf16le":
|
|
635
|
+
case "utf-16le":
|
|
636
|
+
return "utf16le";
|
|
637
|
+
case "latin1":
|
|
638
|
+
case "binary":
|
|
639
|
+
return "latin1";
|
|
640
|
+
case "base64":
|
|
641
|
+
case "ascii":
|
|
642
|
+
case "hex":
|
|
643
|
+
return encoding;
|
|
644
|
+
default:
|
|
645
|
+
throw new Error("Unknown encoding: " + encoding);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
});
|
|
650
|
+
|
|
651
|
+
// ../../node_modules/streamx/lib/errors.js
|
|
652
|
+
var require_errors = __commonJS({
|
|
653
|
+
"../../node_modules/streamx/lib/errors.js"(exports, module) {
|
|
654
|
+
module.exports = class StreamError extends Error {
|
|
655
|
+
constructor(msg, code, fn = StreamError) {
|
|
656
|
+
super(msg);
|
|
657
|
+
this.code = code;
|
|
658
|
+
if (Error.captureStackTrace) {
|
|
659
|
+
Error.captureStackTrace(this, fn);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
static isStreamDestroyed(err) {
|
|
663
|
+
return err && err.code === "STREAM_DESTROYED";
|
|
664
|
+
}
|
|
665
|
+
static isPrematureClose(err) {
|
|
666
|
+
return err && err.code === "PREMATURE_CLOSE";
|
|
667
|
+
}
|
|
668
|
+
static isAborted(err) {
|
|
669
|
+
return err && err.code === "ABORTED";
|
|
670
|
+
}
|
|
671
|
+
static isBadArgument(err) {
|
|
672
|
+
return err && err.code === "BAD_ARGUMENT";
|
|
673
|
+
}
|
|
674
|
+
get name() {
|
|
675
|
+
return "StreamError";
|
|
676
|
+
}
|
|
677
|
+
static STREAM_DESTROYED() {
|
|
678
|
+
return new StreamError("Stream was destroyed", "STREAM_DESTROYED", StreamError.STREAM_DESTROYED);
|
|
679
|
+
}
|
|
680
|
+
static PREMATURE_CLOSE(msg = "Premature close") {
|
|
681
|
+
return new StreamError(msg, "PREMATURE_CLOSE", StreamError.PREMATURE_CLOSE);
|
|
682
|
+
}
|
|
683
|
+
static ABORTED() {
|
|
684
|
+
return new StreamError("Stream aborted", "ABORTED", StreamError.ABORTED);
|
|
685
|
+
}
|
|
686
|
+
static BAD_ARGUMENT(msg = "Bad argument") {
|
|
687
|
+
return new StreamError(msg, "BAD_ARGUMENT", StreamError.BAD_ARGUMENT);
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
// ../../node_modules/streamx/index.js
|
|
694
|
+
var require_streamx = __commonJS({
|
|
695
|
+
"../../node_modules/streamx/index.js"(exports, module) {
|
|
696
|
+
var { EventEmitter } = require_default();
|
|
697
|
+
var FIFO = require_fast_fifo();
|
|
698
|
+
var TextDecoder2 = require_text_decoder();
|
|
699
|
+
var StreamError = require_errors();
|
|
700
|
+
var qmt = typeof queueMicrotask === "undefined" ? (fn) => global.process.nextTick(fn) : queueMicrotask;
|
|
701
|
+
var MAX = (1 << 29) - 1;
|
|
702
|
+
var OPENING = 1;
|
|
703
|
+
var PREDESTROYING = 2;
|
|
704
|
+
var DESTROYING = 4;
|
|
705
|
+
var DESTROYED = 8;
|
|
706
|
+
var NOT_OPENING = MAX ^ OPENING;
|
|
707
|
+
var NOT_PREDESTROYING = MAX ^ PREDESTROYING;
|
|
708
|
+
var READ_ACTIVE = 1 << 4;
|
|
709
|
+
var READ_UPDATING = 2 << 4;
|
|
710
|
+
var READ_PRIMARY = 4 << 4;
|
|
711
|
+
var READ_QUEUED = 8 << 4;
|
|
712
|
+
var READ_RESUMED = 16 << 4;
|
|
713
|
+
var READ_PIPE_DRAINED = 32 << 4;
|
|
714
|
+
var READ_ENDING = 64 << 4;
|
|
715
|
+
var READ_EMIT_DATA = 128 << 4;
|
|
716
|
+
var READ_EMIT_READABLE = 256 << 4;
|
|
717
|
+
var READ_EMITTED_READABLE = 512 << 4;
|
|
718
|
+
var READ_DONE = 1024 << 4;
|
|
719
|
+
var READ_NEXT_TICK = 2048 << 4;
|
|
720
|
+
var READ_NEEDS_PUSH = 4096 << 4;
|
|
721
|
+
var READ_READ_AHEAD = 8192 << 4;
|
|
722
|
+
var READ_FLOWING = READ_RESUMED | READ_PIPE_DRAINED;
|
|
723
|
+
var READ_ACTIVE_AND_NEEDS_PUSH = READ_ACTIVE | READ_NEEDS_PUSH;
|
|
724
|
+
var READ_PRIMARY_AND_ACTIVE = READ_PRIMARY | READ_ACTIVE;
|
|
725
|
+
var READ_EMIT_READABLE_AND_QUEUED = READ_EMIT_READABLE | READ_QUEUED;
|
|
726
|
+
var READ_RESUMED_READ_AHEAD = READ_RESUMED | READ_READ_AHEAD;
|
|
727
|
+
var READ_NOT_ACTIVE = MAX ^ READ_ACTIVE;
|
|
728
|
+
var READ_NON_PRIMARY = MAX ^ READ_PRIMARY;
|
|
729
|
+
var READ_NON_PRIMARY_AND_PUSHED = MAX ^ (READ_PRIMARY | READ_NEEDS_PUSH);
|
|
730
|
+
var READ_PUSHED = MAX ^ READ_NEEDS_PUSH;
|
|
731
|
+
var READ_PAUSED = MAX ^ READ_RESUMED;
|
|
732
|
+
var READ_NOT_QUEUED = MAX ^ (READ_QUEUED | READ_EMITTED_READABLE);
|
|
733
|
+
var READ_NOT_ENDING = MAX ^ READ_ENDING;
|
|
734
|
+
var READ_PIPE_NOT_DRAINED = MAX ^ READ_FLOWING;
|
|
735
|
+
var READ_NOT_NEXT_TICK = MAX ^ READ_NEXT_TICK;
|
|
736
|
+
var READ_NOT_UPDATING = MAX ^ READ_UPDATING;
|
|
737
|
+
var READ_NO_READ_AHEAD = MAX ^ READ_READ_AHEAD;
|
|
738
|
+
var READ_PAUSED_NO_READ_AHEAD = MAX ^ READ_RESUMED_READ_AHEAD;
|
|
739
|
+
var WRITE_ACTIVE = 1 << 18;
|
|
740
|
+
var WRITE_UPDATING = 2 << 18;
|
|
741
|
+
var WRITE_PRIMARY = 4 << 18;
|
|
742
|
+
var WRITE_QUEUED = 8 << 18;
|
|
743
|
+
var WRITE_UNDRAINED = 16 << 18;
|
|
744
|
+
var WRITE_DONE = 32 << 18;
|
|
745
|
+
var WRITE_EMIT_DRAIN = 64 << 18;
|
|
746
|
+
var WRITE_NEXT_TICK = 128 << 18;
|
|
747
|
+
var WRITE_WRITING = 256 << 18;
|
|
748
|
+
var WRITE_FINISHING = 512 << 18;
|
|
749
|
+
var WRITE_CORKED = 1024 << 18;
|
|
750
|
+
var WRITE_NOT_ACTIVE = MAX ^ (WRITE_ACTIVE | WRITE_WRITING);
|
|
751
|
+
var WRITE_NON_PRIMARY = MAX ^ WRITE_PRIMARY;
|
|
752
|
+
var WRITE_NOT_FINISHING = MAX ^ (WRITE_ACTIVE | WRITE_FINISHING);
|
|
753
|
+
var WRITE_DRAINED = MAX ^ WRITE_UNDRAINED;
|
|
754
|
+
var WRITE_NOT_QUEUED = MAX ^ WRITE_QUEUED;
|
|
755
|
+
var WRITE_NOT_NEXT_TICK = MAX ^ WRITE_NEXT_TICK;
|
|
756
|
+
var WRITE_NOT_UPDATING = MAX ^ WRITE_UPDATING;
|
|
757
|
+
var WRITE_NOT_CORKED = MAX ^ WRITE_CORKED;
|
|
758
|
+
var ACTIVE = READ_ACTIVE | WRITE_ACTIVE;
|
|
759
|
+
var NOT_ACTIVE = MAX ^ ACTIVE;
|
|
760
|
+
var DONE = READ_DONE | WRITE_DONE;
|
|
761
|
+
var DESTROY_STATUS = DESTROYING | DESTROYED | PREDESTROYING;
|
|
762
|
+
var OPEN_STATUS = DESTROY_STATUS | OPENING;
|
|
763
|
+
var AUTO_DESTROY = DESTROY_STATUS | DONE;
|
|
764
|
+
var NON_PRIMARY = WRITE_NON_PRIMARY & READ_NON_PRIMARY;
|
|
765
|
+
var ACTIVE_OR_TICKING = WRITE_NEXT_TICK | READ_NEXT_TICK;
|
|
766
|
+
var TICKING = ACTIVE_OR_TICKING & NOT_ACTIVE;
|
|
767
|
+
var IS_OPENING = OPEN_STATUS | TICKING;
|
|
768
|
+
var READ_PRIMARY_STATUS = OPEN_STATUS | READ_ENDING | READ_DONE;
|
|
769
|
+
var READ_STATUS = OPEN_STATUS | READ_DONE | READ_QUEUED;
|
|
770
|
+
var READ_ENDING_STATUS = OPEN_STATUS | READ_ENDING | READ_QUEUED;
|
|
771
|
+
var READ_READABLE_STATUS = OPEN_STATUS | READ_EMIT_READABLE | READ_QUEUED | READ_EMITTED_READABLE;
|
|
772
|
+
var SHOULD_NOT_READ = OPEN_STATUS | READ_ACTIVE | READ_ENDING | READ_DONE | READ_NEEDS_PUSH | READ_READ_AHEAD;
|
|
773
|
+
var READ_BACKPRESSURE_STATUS = DESTROY_STATUS | READ_ENDING | READ_DONE;
|
|
774
|
+
var READ_UPDATE_SYNC_STATUS = READ_UPDATING | OPEN_STATUS | READ_NEXT_TICK | READ_PRIMARY;
|
|
775
|
+
var READ_NEXT_TICK_OR_OPENING = READ_NEXT_TICK | OPENING;
|
|
776
|
+
var WRITE_PRIMARY_STATUS = OPEN_STATUS | WRITE_FINISHING | WRITE_DONE;
|
|
777
|
+
var WRITE_QUEUED_AND_UNDRAINED = WRITE_QUEUED | WRITE_UNDRAINED;
|
|
778
|
+
var WRITE_QUEUED_AND_ACTIVE = WRITE_QUEUED | WRITE_ACTIVE;
|
|
779
|
+
var WRITE_DRAIN_STATUS = WRITE_QUEUED | WRITE_UNDRAINED | OPEN_STATUS | WRITE_ACTIVE;
|
|
780
|
+
var WRITE_STATUS = OPEN_STATUS | WRITE_ACTIVE | WRITE_QUEUED | WRITE_CORKED;
|
|
781
|
+
var WRITE_PRIMARY_AND_ACTIVE = WRITE_PRIMARY | WRITE_ACTIVE;
|
|
782
|
+
var WRITE_ACTIVE_AND_WRITING = WRITE_ACTIVE | WRITE_WRITING;
|
|
783
|
+
var WRITE_FINISHING_STATUS = OPEN_STATUS | WRITE_FINISHING | WRITE_QUEUED_AND_ACTIVE | WRITE_DONE;
|
|
784
|
+
var WRITE_BACKPRESSURE_STATUS = WRITE_UNDRAINED | DESTROY_STATUS | WRITE_FINISHING | WRITE_DONE;
|
|
785
|
+
var WRITE_UPDATE_SYNC_STATUS = WRITE_UPDATING | OPEN_STATUS | WRITE_NEXT_TICK | WRITE_PRIMARY;
|
|
786
|
+
var WRITE_DROP_DATA = WRITE_FINISHING | WRITE_DONE | DESTROY_STATUS;
|
|
787
|
+
var asyncIterator = Symbol.asyncIterator || /* @__PURE__ */ Symbol("asyncIterator");
|
|
788
|
+
var WritableState = class {
|
|
789
|
+
constructor(stream, { highWaterMark = 16384, map = null, mapWritable, byteLength, byteLengthWritable } = {}) {
|
|
790
|
+
this.stream = stream;
|
|
791
|
+
this.queue = new FIFO();
|
|
792
|
+
this.highWaterMark = highWaterMark;
|
|
793
|
+
this.buffered = 0;
|
|
794
|
+
this.error = null;
|
|
795
|
+
this.pipeline = null;
|
|
796
|
+
this.drains = null;
|
|
797
|
+
this.byteLength = byteLengthWritable || byteLength || defaultByteLength;
|
|
798
|
+
this.map = mapWritable || map;
|
|
799
|
+
this.afterWrite = afterWrite.bind(this);
|
|
800
|
+
this.afterUpdateNextTick = updateWriteNT.bind(this);
|
|
801
|
+
}
|
|
802
|
+
get ending() {
|
|
803
|
+
return (this.stream._duplexState & WRITE_FINISHING) !== 0;
|
|
804
|
+
}
|
|
805
|
+
get ended() {
|
|
806
|
+
return (this.stream._duplexState & WRITE_DONE) !== 0;
|
|
807
|
+
}
|
|
808
|
+
push(data) {
|
|
809
|
+
if ((this.stream._duplexState & WRITE_DROP_DATA) !== 0) return false;
|
|
810
|
+
if (this.map !== null) data = this.map(data);
|
|
811
|
+
this.buffered += this.byteLength(data);
|
|
812
|
+
this.queue.push(data);
|
|
813
|
+
if (this.buffered < this.highWaterMark) {
|
|
814
|
+
this.stream._duplexState |= WRITE_QUEUED;
|
|
815
|
+
return true;
|
|
816
|
+
}
|
|
817
|
+
this.stream._duplexState |= WRITE_QUEUED_AND_UNDRAINED;
|
|
818
|
+
return false;
|
|
819
|
+
}
|
|
820
|
+
shift() {
|
|
821
|
+
const data = this.queue.shift();
|
|
822
|
+
this.buffered -= this.byteLength(data);
|
|
823
|
+
if (this.buffered === 0) this.stream._duplexState &= WRITE_NOT_QUEUED;
|
|
824
|
+
return data;
|
|
825
|
+
}
|
|
826
|
+
end(data) {
|
|
827
|
+
if (typeof data === "function") {
|
|
828
|
+
this.stream.once("finish", data);
|
|
829
|
+
} else if (data !== void 0 && data !== null) {
|
|
830
|
+
this.push(data);
|
|
831
|
+
}
|
|
832
|
+
this.stream._duplexState = (this.stream._duplexState | WRITE_FINISHING) & WRITE_NON_PRIMARY;
|
|
833
|
+
}
|
|
834
|
+
autoBatch(data, cb) {
|
|
835
|
+
const buffer = [];
|
|
836
|
+
const stream = this.stream;
|
|
837
|
+
buffer.push(data);
|
|
838
|
+
while ((stream._duplexState & WRITE_STATUS) === WRITE_QUEUED_AND_ACTIVE) {
|
|
839
|
+
buffer.push(stream._writableState.shift());
|
|
840
|
+
}
|
|
841
|
+
if ((stream._duplexState & OPEN_STATUS) !== 0) return cb(null);
|
|
842
|
+
stream._writev(buffer, cb);
|
|
843
|
+
}
|
|
844
|
+
update() {
|
|
845
|
+
const stream = this.stream;
|
|
846
|
+
stream._duplexState |= WRITE_UPDATING;
|
|
847
|
+
do {
|
|
848
|
+
while ((stream._duplexState & WRITE_STATUS) === WRITE_QUEUED) {
|
|
849
|
+
const data = this.shift();
|
|
850
|
+
stream._duplexState |= WRITE_ACTIVE_AND_WRITING;
|
|
851
|
+
stream._write(data, this.afterWrite);
|
|
852
|
+
}
|
|
853
|
+
if ((stream._duplexState & WRITE_PRIMARY_AND_ACTIVE) === 0) this.updateNonPrimary();
|
|
854
|
+
} while (this.continueUpdate() === true);
|
|
855
|
+
stream._duplexState &= WRITE_NOT_UPDATING;
|
|
856
|
+
}
|
|
857
|
+
updateNonPrimary() {
|
|
858
|
+
const stream = this.stream;
|
|
859
|
+
if ((stream._duplexState & WRITE_FINISHING_STATUS) === WRITE_FINISHING) {
|
|
860
|
+
stream._duplexState = stream._duplexState | WRITE_ACTIVE;
|
|
861
|
+
stream._final(afterFinal.bind(this));
|
|
862
|
+
return;
|
|
863
|
+
}
|
|
864
|
+
if ((stream._duplexState & DESTROY_STATUS) === DESTROYING) {
|
|
865
|
+
if ((stream._duplexState & ACTIVE_OR_TICKING) === 0) {
|
|
866
|
+
stream._duplexState |= ACTIVE;
|
|
867
|
+
stream._destroy(afterDestroy.bind(this));
|
|
868
|
+
}
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
if ((stream._duplexState & IS_OPENING) === OPENING) {
|
|
872
|
+
stream._duplexState = (stream._duplexState | ACTIVE) & NOT_OPENING;
|
|
873
|
+
stream._open(afterOpen.bind(this));
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
continueUpdate() {
|
|
877
|
+
if ((this.stream._duplexState & WRITE_NEXT_TICK) === 0) return false;
|
|
878
|
+
this.stream._duplexState &= WRITE_NOT_NEXT_TICK;
|
|
879
|
+
return true;
|
|
880
|
+
}
|
|
881
|
+
updateCallback() {
|
|
882
|
+
if ((this.stream._duplexState & WRITE_UPDATE_SYNC_STATUS) === WRITE_PRIMARY) {
|
|
883
|
+
this.update();
|
|
884
|
+
} else {
|
|
885
|
+
this.updateNextTick();
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
updateNextTick() {
|
|
889
|
+
if ((this.stream._duplexState & WRITE_NEXT_TICK) !== 0) return;
|
|
890
|
+
this.stream._duplexState |= WRITE_NEXT_TICK;
|
|
891
|
+
if ((this.stream._duplexState & WRITE_UPDATING) === 0) qmt(this.afterUpdateNextTick);
|
|
892
|
+
}
|
|
893
|
+
};
|
|
894
|
+
var ReadableState = class {
|
|
895
|
+
constructor(stream, { highWaterMark = 16384, map = null, mapReadable, byteLength, byteLengthReadable } = {}) {
|
|
896
|
+
this.stream = stream;
|
|
897
|
+
this.queue = new FIFO();
|
|
898
|
+
this.highWaterMark = highWaterMark === 0 ? 1 : highWaterMark;
|
|
899
|
+
this.buffered = 0;
|
|
900
|
+
this.readAhead = highWaterMark > 0;
|
|
901
|
+
this.error = null;
|
|
902
|
+
this.pipeline = null;
|
|
903
|
+
this.byteLength = byteLengthReadable || byteLength || defaultByteLength;
|
|
904
|
+
this.map = mapReadable || map;
|
|
905
|
+
this.pipeTo = null;
|
|
906
|
+
this.afterRead = afterRead.bind(this);
|
|
907
|
+
this.afterUpdateNextTick = updateReadNT.bind(this);
|
|
908
|
+
}
|
|
909
|
+
get ending() {
|
|
910
|
+
return (this.stream._duplexState & READ_ENDING) !== 0;
|
|
911
|
+
}
|
|
912
|
+
get ended() {
|
|
913
|
+
return (this.stream._duplexState & READ_DONE) !== 0;
|
|
914
|
+
}
|
|
915
|
+
pipe(pipeTo, cb) {
|
|
916
|
+
if (this.pipeTo !== null) throw StreamError.BAD_ARGUMENT("Can only pipe to one destination");
|
|
917
|
+
if (typeof cb !== "function") cb = null;
|
|
918
|
+
this.stream._duplexState |= READ_PIPE_DRAINED;
|
|
919
|
+
this.pipeTo = pipeTo;
|
|
920
|
+
this.pipeline = new Pipeline(this.stream, pipeTo, cb);
|
|
921
|
+
if (cb) this.stream.on("error", noop);
|
|
922
|
+
if (isStreamx(pipeTo)) {
|
|
923
|
+
pipeTo._writableState.pipeline = this.pipeline;
|
|
924
|
+
if (cb) pipeTo.on("error", noop);
|
|
925
|
+
pipeTo.on("finish", this.pipeline.finished.bind(this.pipeline));
|
|
926
|
+
} else {
|
|
927
|
+
const onerror = this.pipeline.done.bind(this.pipeline, pipeTo);
|
|
928
|
+
const onclose = this.pipeline.done.bind(this.pipeline, pipeTo, null);
|
|
929
|
+
pipeTo.on("error", onerror);
|
|
930
|
+
pipeTo.on("close", onclose);
|
|
931
|
+
pipeTo.on("finish", this.pipeline.finished.bind(this.pipeline));
|
|
932
|
+
}
|
|
933
|
+
pipeTo.on("drain", afterDrain.bind(this));
|
|
934
|
+
this.stream.emit("piping", pipeTo);
|
|
935
|
+
pipeTo.emit("pipe", this.stream);
|
|
936
|
+
}
|
|
937
|
+
push(data) {
|
|
938
|
+
const stream = this.stream;
|
|
939
|
+
if (data === null) {
|
|
940
|
+
this.highWaterMark = 0;
|
|
941
|
+
stream._duplexState = (stream._duplexState | READ_ENDING) & READ_NON_PRIMARY_AND_PUSHED;
|
|
942
|
+
return false;
|
|
943
|
+
}
|
|
944
|
+
if (this.map !== null) {
|
|
945
|
+
data = this.map(data);
|
|
946
|
+
if (data === null) {
|
|
947
|
+
stream._duplexState &= READ_PUSHED;
|
|
948
|
+
return this.buffered < this.highWaterMark;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
this.buffered += this.byteLength(data);
|
|
952
|
+
this.queue.push(data);
|
|
953
|
+
stream._duplexState = (stream._duplexState | READ_QUEUED) & READ_PUSHED;
|
|
954
|
+
return this.buffered < this.highWaterMark;
|
|
955
|
+
}
|
|
956
|
+
shift() {
|
|
957
|
+
const data = this.queue.shift();
|
|
958
|
+
this.buffered -= this.byteLength(data);
|
|
959
|
+
if (this.buffered === 0) {
|
|
960
|
+
this.stream._duplexState &= READ_NOT_QUEUED;
|
|
961
|
+
}
|
|
962
|
+
return data;
|
|
963
|
+
}
|
|
964
|
+
unshift(data) {
|
|
965
|
+
const pending = [this.map !== null ? this.map(data) : data];
|
|
966
|
+
while (this.buffered > 0) pending.push(this.shift());
|
|
967
|
+
for (let i = 0; i < pending.length - 1; i++) {
|
|
968
|
+
const data2 = pending[i];
|
|
969
|
+
this.buffered += this.byteLength(data2);
|
|
970
|
+
this.queue.push(data2);
|
|
971
|
+
}
|
|
972
|
+
this.push(pending[pending.length - 1]);
|
|
973
|
+
}
|
|
974
|
+
read() {
|
|
975
|
+
const stream = this.stream;
|
|
976
|
+
if ((stream._duplexState & READ_STATUS) === READ_QUEUED) {
|
|
977
|
+
const data = this.shift();
|
|
978
|
+
if (this.pipeTo !== null && this.pipeTo.write(data) === false) {
|
|
979
|
+
stream._duplexState &= READ_PIPE_NOT_DRAINED;
|
|
980
|
+
}
|
|
981
|
+
if ((stream._duplexState & READ_EMIT_DATA) !== 0) {
|
|
982
|
+
stream.emit("data", data);
|
|
983
|
+
}
|
|
984
|
+
return data;
|
|
985
|
+
}
|
|
986
|
+
if (this.readAhead === false) {
|
|
987
|
+
stream._duplexState |= READ_READ_AHEAD;
|
|
988
|
+
this.updateNextTick();
|
|
989
|
+
}
|
|
990
|
+
return null;
|
|
991
|
+
}
|
|
992
|
+
drain() {
|
|
993
|
+
const stream = this.stream;
|
|
994
|
+
while ((stream._duplexState & READ_STATUS) === READ_QUEUED && (stream._duplexState & READ_FLOWING) !== 0) {
|
|
995
|
+
const data = this.shift();
|
|
996
|
+
if (this.pipeTo !== null && this.pipeTo.write(data) === false) {
|
|
997
|
+
stream._duplexState &= READ_PIPE_NOT_DRAINED;
|
|
998
|
+
}
|
|
999
|
+
if ((stream._duplexState & READ_EMIT_DATA) !== 0) {
|
|
1000
|
+
stream.emit("data", data);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
update() {
|
|
1005
|
+
const stream = this.stream;
|
|
1006
|
+
stream._duplexState |= READ_UPDATING;
|
|
1007
|
+
do {
|
|
1008
|
+
this.drain();
|
|
1009
|
+
while (this.buffered < this.highWaterMark && (stream._duplexState & SHOULD_NOT_READ) === READ_READ_AHEAD) {
|
|
1010
|
+
stream._duplexState |= READ_ACTIVE_AND_NEEDS_PUSH;
|
|
1011
|
+
stream._read(this.afterRead);
|
|
1012
|
+
this.drain();
|
|
1013
|
+
}
|
|
1014
|
+
if ((stream._duplexState & READ_READABLE_STATUS) === READ_EMIT_READABLE_AND_QUEUED) {
|
|
1015
|
+
stream._duplexState |= READ_EMITTED_READABLE;
|
|
1016
|
+
stream.emit("readable");
|
|
1017
|
+
}
|
|
1018
|
+
if ((stream._duplexState & READ_PRIMARY_AND_ACTIVE) === 0) {
|
|
1019
|
+
this.updateNonPrimary();
|
|
1020
|
+
}
|
|
1021
|
+
} while (this.continueUpdate() === true);
|
|
1022
|
+
stream._duplexState &= READ_NOT_UPDATING;
|
|
1023
|
+
}
|
|
1024
|
+
updateNonPrimary() {
|
|
1025
|
+
const stream = this.stream;
|
|
1026
|
+
if ((stream._duplexState & READ_ENDING_STATUS) === READ_ENDING) {
|
|
1027
|
+
stream._duplexState = (stream._duplexState | READ_DONE) & READ_NOT_ENDING;
|
|
1028
|
+
stream.emit("end");
|
|
1029
|
+
if ((stream._duplexState & AUTO_DESTROY) === DONE) {
|
|
1030
|
+
stream._duplexState |= DESTROYING;
|
|
1031
|
+
}
|
|
1032
|
+
if (this.pipeTo !== null) {
|
|
1033
|
+
this.pipeTo.end();
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
if ((stream._duplexState & DESTROY_STATUS) === DESTROYING) {
|
|
1037
|
+
if ((stream._duplexState & ACTIVE_OR_TICKING) === 0) {
|
|
1038
|
+
stream._duplexState |= ACTIVE;
|
|
1039
|
+
stream._destroy(afterDestroy.bind(this));
|
|
1040
|
+
}
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
if ((stream._duplexState & IS_OPENING) === OPENING) {
|
|
1044
|
+
stream._duplexState = (stream._duplexState | ACTIVE) & NOT_OPENING;
|
|
1045
|
+
stream._open(afterOpen.bind(this));
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
continueUpdate() {
|
|
1049
|
+
if ((this.stream._duplexState & READ_NEXT_TICK) === 0) return false;
|
|
1050
|
+
this.stream._duplexState &= READ_NOT_NEXT_TICK;
|
|
1051
|
+
return true;
|
|
1052
|
+
}
|
|
1053
|
+
updateCallback() {
|
|
1054
|
+
if ((this.stream._duplexState & READ_UPDATE_SYNC_STATUS) === READ_PRIMARY) {
|
|
1055
|
+
this.update();
|
|
1056
|
+
} else {
|
|
1057
|
+
this.updateNextTick();
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
updateNextTickIfOpen() {
|
|
1061
|
+
if ((this.stream._duplexState & READ_NEXT_TICK_OR_OPENING) !== 0) return;
|
|
1062
|
+
this.stream._duplexState |= READ_NEXT_TICK;
|
|
1063
|
+
if ((this.stream._duplexState & READ_UPDATING) === 0) qmt(this.afterUpdateNextTick);
|
|
1064
|
+
}
|
|
1065
|
+
updateNextTick() {
|
|
1066
|
+
if ((this.stream._duplexState & READ_NEXT_TICK) !== 0) return;
|
|
1067
|
+
this.stream._duplexState |= READ_NEXT_TICK;
|
|
1068
|
+
if ((this.stream._duplexState & READ_UPDATING) === 0) qmt(this.afterUpdateNextTick);
|
|
1069
|
+
}
|
|
1070
|
+
};
|
|
1071
|
+
var TransformState = class {
|
|
1072
|
+
constructor(stream) {
|
|
1073
|
+
this.data = null;
|
|
1074
|
+
this.afterTransform = afterTransform.bind(stream);
|
|
1075
|
+
this.afterFinal = null;
|
|
1076
|
+
}
|
|
1077
|
+
};
|
|
1078
|
+
var Pipeline = class {
|
|
1079
|
+
constructor(src, dst, cb) {
|
|
1080
|
+
this.from = src;
|
|
1081
|
+
this.to = dst;
|
|
1082
|
+
this.afterPipe = cb;
|
|
1083
|
+
this.error = null;
|
|
1084
|
+
this.pipeToFinished = false;
|
|
1085
|
+
}
|
|
1086
|
+
finished() {
|
|
1087
|
+
this.pipeToFinished = true;
|
|
1088
|
+
}
|
|
1089
|
+
done(stream, err) {
|
|
1090
|
+
if (err) this.error = err;
|
|
1091
|
+
if (stream === this.to) {
|
|
1092
|
+
this.to = null;
|
|
1093
|
+
if (this.from !== null) {
|
|
1094
|
+
if ((this.from._duplexState & READ_DONE) === 0 || !this.pipeToFinished) {
|
|
1095
|
+
this.from.destroy(this.error || StreamError.PREMATURE_CLOSE("Writable stream closed"));
|
|
1096
|
+
}
|
|
1097
|
+
return;
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
if (stream === this.from) {
|
|
1101
|
+
this.from = null;
|
|
1102
|
+
if (this.to !== null) {
|
|
1103
|
+
if ((stream._duplexState & READ_DONE) === 0) {
|
|
1104
|
+
this.to.destroy(this.error || StreamError.PREMATURE_CLOSE("Readable stream closed"));
|
|
1105
|
+
}
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
if (this.afterPipe !== null) this.afterPipe(this.error);
|
|
1110
|
+
this.to = this.from = this.afterPipe = null;
|
|
1111
|
+
}
|
|
1112
|
+
};
|
|
1113
|
+
function afterDrain() {
|
|
1114
|
+
this.stream._duplexState |= READ_PIPE_DRAINED;
|
|
1115
|
+
this.updateCallback();
|
|
1116
|
+
}
|
|
1117
|
+
function afterFinal(err) {
|
|
1118
|
+
const stream = this.stream;
|
|
1119
|
+
if (err) stream.destroy(err);
|
|
1120
|
+
if ((stream._duplexState & DESTROY_STATUS) === 0) {
|
|
1121
|
+
stream._duplexState |= WRITE_DONE;
|
|
1122
|
+
stream.emit("finish");
|
|
1123
|
+
}
|
|
1124
|
+
if ((stream._duplexState & AUTO_DESTROY) === DONE) {
|
|
1125
|
+
stream._duplexState |= DESTROYING;
|
|
1126
|
+
}
|
|
1127
|
+
stream._duplexState &= WRITE_NOT_FINISHING;
|
|
1128
|
+
if ((stream._duplexState & WRITE_UPDATING) === 0) {
|
|
1129
|
+
this.update();
|
|
1130
|
+
} else {
|
|
1131
|
+
this.updateNextTick();
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
function afterDestroy(err) {
|
|
1135
|
+
const stream = this.stream;
|
|
1136
|
+
if (!err && !StreamError.isStreamDestroyed(this.error)) err = this.error;
|
|
1137
|
+
if (err) stream.emit("error", err);
|
|
1138
|
+
stream._duplexState |= DESTROYED;
|
|
1139
|
+
stream.emit("close");
|
|
1140
|
+
const rs = stream._readableState;
|
|
1141
|
+
const ws = stream._writableState;
|
|
1142
|
+
if (rs !== null && rs.pipeline !== null) {
|
|
1143
|
+
rs.pipeline.done(stream, err);
|
|
1144
|
+
}
|
|
1145
|
+
if (ws !== null) {
|
|
1146
|
+
while (ws.drains !== null && ws.drains.length > 0) {
|
|
1147
|
+
ws.drains.shift().resolve(false);
|
|
1148
|
+
}
|
|
1149
|
+
if (ws.pipeline !== null) {
|
|
1150
|
+
ws.pipeline.done(stream, err);
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
function afterWrite(err) {
|
|
1155
|
+
const stream = this.stream;
|
|
1156
|
+
if (err) stream.destroy(err);
|
|
1157
|
+
stream._duplexState &= WRITE_NOT_ACTIVE;
|
|
1158
|
+
if (this.drains !== null) tickDrains(this.drains);
|
|
1159
|
+
if ((stream._duplexState & WRITE_DRAIN_STATUS) === WRITE_UNDRAINED) {
|
|
1160
|
+
stream._duplexState &= WRITE_DRAINED;
|
|
1161
|
+
if ((stream._duplexState & WRITE_EMIT_DRAIN) === WRITE_EMIT_DRAIN) {
|
|
1162
|
+
stream.emit("drain");
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
this.updateCallback();
|
|
1166
|
+
}
|
|
1167
|
+
function afterRead(err) {
|
|
1168
|
+
if (err) this.stream.destroy(err);
|
|
1169
|
+
this.stream._duplexState &= READ_NOT_ACTIVE;
|
|
1170
|
+
if (this.readAhead === false && (this.stream._duplexState & READ_RESUMED) === 0) {
|
|
1171
|
+
this.stream._duplexState &= READ_NO_READ_AHEAD;
|
|
1172
|
+
}
|
|
1173
|
+
this.updateCallback();
|
|
1174
|
+
}
|
|
1175
|
+
function updateReadNT() {
|
|
1176
|
+
if ((this.stream._duplexState & READ_UPDATING) === 0) {
|
|
1177
|
+
this.stream._duplexState &= READ_NOT_NEXT_TICK;
|
|
1178
|
+
this.update();
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
function updateWriteNT() {
|
|
1182
|
+
if ((this.stream._duplexState & WRITE_UPDATING) === 0) {
|
|
1183
|
+
this.stream._duplexState &= WRITE_NOT_NEXT_TICK;
|
|
1184
|
+
this.update();
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
function tickDrains(drains) {
|
|
1188
|
+
for (let i = 0; i < drains.length; i++) {
|
|
1189
|
+
if (--drains[i].writes === 0) {
|
|
1190
|
+
drains.shift().resolve(true);
|
|
1191
|
+
i--;
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
function afterOpen(err) {
|
|
1196
|
+
const stream = this.stream;
|
|
1197
|
+
if (err) stream.destroy(err);
|
|
1198
|
+
if ((stream._duplexState & DESTROYING) === 0) {
|
|
1199
|
+
if ((stream._duplexState & READ_PRIMARY_STATUS) === 0) {
|
|
1200
|
+
stream._duplexState |= READ_PRIMARY;
|
|
1201
|
+
}
|
|
1202
|
+
if ((stream._duplexState & WRITE_PRIMARY_STATUS) === 0) {
|
|
1203
|
+
stream._duplexState |= WRITE_PRIMARY;
|
|
1204
|
+
}
|
|
1205
|
+
stream.emit("open");
|
|
1206
|
+
}
|
|
1207
|
+
stream._duplexState &= NOT_ACTIVE;
|
|
1208
|
+
if (stream._writableState !== null) {
|
|
1209
|
+
stream._writableState.updateCallback();
|
|
1210
|
+
}
|
|
1211
|
+
if (stream._readableState !== null) {
|
|
1212
|
+
stream._readableState.updateCallback();
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
function afterTransform(err, data) {
|
|
1216
|
+
if (data !== void 0 && data !== null) this.push(data);
|
|
1217
|
+
this._writableState.afterWrite(err);
|
|
1218
|
+
}
|
|
1219
|
+
function newListener(name) {
|
|
1220
|
+
if (this._readableState !== null) {
|
|
1221
|
+
if (name === "data") {
|
|
1222
|
+
this._duplexState |= READ_EMIT_DATA | READ_RESUMED_READ_AHEAD;
|
|
1223
|
+
this._readableState.updateNextTick();
|
|
1224
|
+
}
|
|
1225
|
+
if (name === "readable") {
|
|
1226
|
+
this._duplexState |= READ_EMIT_READABLE;
|
|
1227
|
+
this._readableState.updateNextTick();
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
if (this._writableState !== null) {
|
|
1231
|
+
if (name === "drain") {
|
|
1232
|
+
this._duplexState |= WRITE_EMIT_DRAIN;
|
|
1233
|
+
this._writableState.updateNextTick();
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
var Stream = class extends EventEmitter {
|
|
1238
|
+
constructor(opts) {
|
|
1239
|
+
super();
|
|
1240
|
+
this._duplexState = 0;
|
|
1241
|
+
this._readableState = null;
|
|
1242
|
+
this._writableState = null;
|
|
1243
|
+
if (opts) {
|
|
1244
|
+
if (opts.open) this._open = opts.open;
|
|
1245
|
+
if (opts.destroy) this._destroy = opts.destroy;
|
|
1246
|
+
if (opts.predestroy) this._predestroy = opts.predestroy;
|
|
1247
|
+
if (opts.signal) opts.signal.addEventListener("abort", abort.bind(this));
|
|
1248
|
+
}
|
|
1249
|
+
this.on("newListener", newListener);
|
|
1250
|
+
}
|
|
1251
|
+
_open(cb) {
|
|
1252
|
+
cb(null);
|
|
1253
|
+
}
|
|
1254
|
+
_destroy(cb) {
|
|
1255
|
+
cb(null);
|
|
1256
|
+
}
|
|
1257
|
+
_predestroy() {
|
|
1258
|
+
}
|
|
1259
|
+
get readable() {
|
|
1260
|
+
return this._readableState !== null ? true : void 0;
|
|
1261
|
+
}
|
|
1262
|
+
get writable() {
|
|
1263
|
+
return this._writableState !== null ? true : void 0;
|
|
1264
|
+
}
|
|
1265
|
+
get destroyed() {
|
|
1266
|
+
return (this._duplexState & DESTROYED) !== 0;
|
|
1267
|
+
}
|
|
1268
|
+
get destroying() {
|
|
1269
|
+
return (this._duplexState & DESTROY_STATUS) !== 0;
|
|
1270
|
+
}
|
|
1271
|
+
destroy(err) {
|
|
1272
|
+
if ((this._duplexState & DESTROY_STATUS) === 0) {
|
|
1273
|
+
if (!err) err = StreamError.STREAM_DESTROYED();
|
|
1274
|
+
this._duplexState = (this._duplexState | DESTROYING) & NON_PRIMARY;
|
|
1275
|
+
if (this._readableState !== null) {
|
|
1276
|
+
this._readableState.highWaterMark = 0;
|
|
1277
|
+
this._readableState.error = err;
|
|
1278
|
+
}
|
|
1279
|
+
if (this._writableState !== null) {
|
|
1280
|
+
this._writableState.highWaterMark = 0;
|
|
1281
|
+
this._writableState.error = err;
|
|
1282
|
+
}
|
|
1283
|
+
this._duplexState |= PREDESTROYING;
|
|
1284
|
+
this._predestroy();
|
|
1285
|
+
this._duplexState &= NOT_PREDESTROYING;
|
|
1286
|
+
if (this._readableState !== null) {
|
|
1287
|
+
this._readableState.updateNextTick();
|
|
1288
|
+
}
|
|
1289
|
+
if (this._writableState !== null) {
|
|
1290
|
+
this._writableState.updateNextTick();
|
|
1291
|
+
}
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
var Readable2 = class _Readable extends Stream {
|
|
1296
|
+
constructor(opts) {
|
|
1297
|
+
super(opts);
|
|
1298
|
+
this._duplexState |= OPENING | WRITE_DONE | READ_READ_AHEAD;
|
|
1299
|
+
this._readableState = new ReadableState(this, opts);
|
|
1300
|
+
if (opts) {
|
|
1301
|
+
if (this._readableState.readAhead === false) this._duplexState &= READ_NO_READ_AHEAD;
|
|
1302
|
+
if (opts.read) this._read = opts.read;
|
|
1303
|
+
if (opts.eagerOpen) this._readableState.updateNextTick();
|
|
1304
|
+
if (opts.encoding) this.setEncoding(opts.encoding);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
static deferred(fn, opts) {
|
|
1308
|
+
const out = new PassThrough(opts);
|
|
1309
|
+
fn().then((src) => {
|
|
1310
|
+
if (src === null) return out.end();
|
|
1311
|
+
if (out.destroying) return;
|
|
1312
|
+
pipeline2(src, out, noop);
|
|
1313
|
+
}).catch((err) => out.destroy(err));
|
|
1314
|
+
return out;
|
|
1315
|
+
}
|
|
1316
|
+
setEncoding(encoding) {
|
|
1317
|
+
const dec = new TextDecoder2(encoding);
|
|
1318
|
+
const map = this._readableState.map || echo;
|
|
1319
|
+
this._readableState.map = mapOrSkip;
|
|
1320
|
+
return this;
|
|
1321
|
+
function mapOrSkip(data) {
|
|
1322
|
+
const next = dec.push(data);
|
|
1323
|
+
return next === "" && (data.byteLength !== 0 || dec.remaining > 0) ? null : map(next);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
_read(cb) {
|
|
1327
|
+
cb(null);
|
|
1328
|
+
}
|
|
1329
|
+
pipe(dest, cb) {
|
|
1330
|
+
this._readableState.updateNextTick();
|
|
1331
|
+
this._readableState.pipe(dest, cb);
|
|
1332
|
+
return dest;
|
|
1333
|
+
}
|
|
1334
|
+
read() {
|
|
1335
|
+
this._readableState.updateNextTick();
|
|
1336
|
+
return this._readableState.read();
|
|
1337
|
+
}
|
|
1338
|
+
push(data) {
|
|
1339
|
+
this._readableState.updateNextTickIfOpen();
|
|
1340
|
+
return this._readableState.push(data);
|
|
1341
|
+
}
|
|
1342
|
+
unshift(data) {
|
|
1343
|
+
this._readableState.updateNextTickIfOpen();
|
|
1344
|
+
return this._readableState.unshift(data);
|
|
1345
|
+
}
|
|
1346
|
+
resume() {
|
|
1347
|
+
this._duplexState |= READ_RESUMED_READ_AHEAD;
|
|
1348
|
+
this._readableState.updateNextTick();
|
|
1349
|
+
return this;
|
|
1350
|
+
}
|
|
1351
|
+
pause() {
|
|
1352
|
+
this._duplexState &= this._readableState.readAhead === false ? READ_PAUSED_NO_READ_AHEAD : READ_PAUSED;
|
|
1353
|
+
return this;
|
|
1354
|
+
}
|
|
1355
|
+
static _fromAsyncIterator(ite, opts) {
|
|
1356
|
+
let destroy;
|
|
1357
|
+
const rs = new _Readable({
|
|
1358
|
+
...opts,
|
|
1359
|
+
read(cb) {
|
|
1360
|
+
ite.next().then(push).then(cb.bind(null, null)).catch(cb);
|
|
1361
|
+
},
|
|
1362
|
+
predestroy() {
|
|
1363
|
+
destroy = ite.return();
|
|
1364
|
+
},
|
|
1365
|
+
destroy(cb) {
|
|
1366
|
+
if (!destroy) return cb(null);
|
|
1367
|
+
destroy.then(cb.bind(null, null)).catch(cb);
|
|
1368
|
+
}
|
|
1369
|
+
});
|
|
1370
|
+
return rs;
|
|
1371
|
+
function push(data) {
|
|
1372
|
+
if (data.done) rs.push(null);
|
|
1373
|
+
else rs.push(data.value);
|
|
1374
|
+
}
|
|
1375
|
+
}
|
|
1376
|
+
static from(data, opts) {
|
|
1377
|
+
if (isReadStreamx(data)) return data;
|
|
1378
|
+
if (data[asyncIterator]) return this._fromAsyncIterator(data[asyncIterator](), opts);
|
|
1379
|
+
if (!Array.isArray(data)) data = data === void 0 ? [] : [data];
|
|
1380
|
+
let i = 0;
|
|
1381
|
+
return new _Readable({
|
|
1382
|
+
...opts,
|
|
1383
|
+
read(cb) {
|
|
1384
|
+
this.push(i === data.length ? null : data[i++]);
|
|
1385
|
+
cb(null);
|
|
1386
|
+
}
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
static isBackpressured(rs) {
|
|
1390
|
+
return (rs._duplexState & READ_BACKPRESSURE_STATUS) !== 0 || rs._readableState.buffered >= rs._readableState.highWaterMark;
|
|
1391
|
+
}
|
|
1392
|
+
static isPaused(rs) {
|
|
1393
|
+
return (rs._duplexState & READ_RESUMED) === 0;
|
|
1394
|
+
}
|
|
1395
|
+
[asyncIterator]() {
|
|
1396
|
+
const stream = this;
|
|
1397
|
+
let error = null;
|
|
1398
|
+
let promiseResolve = null;
|
|
1399
|
+
let promiseReject = null;
|
|
1400
|
+
this.on("error", (err) => {
|
|
1401
|
+
error = err;
|
|
1402
|
+
});
|
|
1403
|
+
this.on("readable", onreadable);
|
|
1404
|
+
this.on("close", onclose);
|
|
1405
|
+
return {
|
|
1406
|
+
[asyncIterator]() {
|
|
1407
|
+
return this;
|
|
1408
|
+
},
|
|
1409
|
+
next() {
|
|
1410
|
+
return new Promise(function(resolve3, reject) {
|
|
1411
|
+
promiseResolve = resolve3;
|
|
1412
|
+
promiseReject = reject;
|
|
1413
|
+
const data = stream.read();
|
|
1414
|
+
if (data !== null) ondata(data);
|
|
1415
|
+
else if ((stream._duplexState & DESTROYED) !== 0) ondata(null);
|
|
1416
|
+
});
|
|
1417
|
+
},
|
|
1418
|
+
return() {
|
|
1419
|
+
return destroy(null);
|
|
1420
|
+
},
|
|
1421
|
+
throw(err) {
|
|
1422
|
+
return destroy(err);
|
|
1423
|
+
}
|
|
1424
|
+
};
|
|
1425
|
+
function onreadable() {
|
|
1426
|
+
if (promiseResolve !== null) ondata(stream.read());
|
|
1427
|
+
}
|
|
1428
|
+
function onclose() {
|
|
1429
|
+
if (promiseResolve !== null) ondata(null);
|
|
1430
|
+
}
|
|
1431
|
+
function ondata(data) {
|
|
1432
|
+
if (promiseReject === null) return;
|
|
1433
|
+
if (error) {
|
|
1434
|
+
promiseReject(error);
|
|
1435
|
+
} else if (data === null && (stream._duplexState & READ_DONE) === 0) {
|
|
1436
|
+
promiseReject(StreamError.STREAM_DESTROYED());
|
|
1437
|
+
} else {
|
|
1438
|
+
promiseResolve({ value: data, done: data === null });
|
|
1439
|
+
}
|
|
1440
|
+
promiseReject = promiseResolve = null;
|
|
1441
|
+
}
|
|
1442
|
+
function destroy(err) {
|
|
1443
|
+
stream.destroy(err);
|
|
1444
|
+
return new Promise((resolve3, reject) => {
|
|
1445
|
+
if (stream._duplexState & DESTROYED) return resolve3({ value: void 0, done: true });
|
|
1446
|
+
stream.once("close", function() {
|
|
1447
|
+
if (err) reject(err);
|
|
1448
|
+
else resolve3({ value: void 0, done: true });
|
|
1449
|
+
});
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
}
|
|
1453
|
+
};
|
|
1454
|
+
var Writable = class extends Stream {
|
|
1455
|
+
constructor(opts) {
|
|
1456
|
+
super(opts);
|
|
1457
|
+
this._duplexState |= OPENING | READ_DONE;
|
|
1458
|
+
this._writableState = new WritableState(this, opts);
|
|
1459
|
+
if (opts) {
|
|
1460
|
+
if (opts.writev) this._writev = opts.writev;
|
|
1461
|
+
if (opts.write) this._write = opts.write;
|
|
1462
|
+
if (opts.final) this._final = opts.final;
|
|
1463
|
+
if (opts.eagerOpen) this._writableState.updateNextTick();
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
cork() {
|
|
1467
|
+
this._duplexState |= WRITE_CORKED;
|
|
1468
|
+
}
|
|
1469
|
+
uncork() {
|
|
1470
|
+
this._duplexState &= WRITE_NOT_CORKED;
|
|
1471
|
+
this._writableState.updateNextTick();
|
|
1472
|
+
}
|
|
1473
|
+
_writev(batch, cb) {
|
|
1474
|
+
cb(null);
|
|
1475
|
+
}
|
|
1476
|
+
_write(data, cb) {
|
|
1477
|
+
this._writableState.autoBatch(data, cb);
|
|
1478
|
+
}
|
|
1479
|
+
_final(cb) {
|
|
1480
|
+
cb(null);
|
|
1481
|
+
}
|
|
1482
|
+
static isBackpressured(ws) {
|
|
1483
|
+
return (ws._duplexState & WRITE_BACKPRESSURE_STATUS) !== 0;
|
|
1484
|
+
}
|
|
1485
|
+
static drained(ws) {
|
|
1486
|
+
if (ws.destroyed) return Promise.resolve(false);
|
|
1487
|
+
const state = ws._writableState;
|
|
1488
|
+
const pending = isWritev(ws) ? Math.min(1, state.queue.length) : state.queue.length;
|
|
1489
|
+
const writes = pending + (ws._duplexState & WRITE_WRITING ? 1 : 0);
|
|
1490
|
+
if (writes === 0) return Promise.resolve(true);
|
|
1491
|
+
if (state.drains === null) state.drains = [];
|
|
1492
|
+
return new Promise((resolve3) => {
|
|
1493
|
+
state.drains.push({ writes, resolve: resolve3 });
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1496
|
+
write(data) {
|
|
1497
|
+
this._writableState.updateNextTick();
|
|
1498
|
+
return this._writableState.push(data);
|
|
1499
|
+
}
|
|
1500
|
+
end(data) {
|
|
1501
|
+
this._writableState.updateNextTick();
|
|
1502
|
+
this._writableState.end(data);
|
|
1503
|
+
return this;
|
|
1504
|
+
}
|
|
1505
|
+
};
|
|
1506
|
+
var Duplex = class extends Readable2 {
|
|
1507
|
+
// and Writable
|
|
1508
|
+
constructor(opts) {
|
|
1509
|
+
super(opts);
|
|
1510
|
+
this._duplexState = OPENING | this._duplexState & READ_READ_AHEAD;
|
|
1511
|
+
this._writableState = new WritableState(this, opts);
|
|
1512
|
+
if (opts) {
|
|
1513
|
+
if (opts.writev) this._writev = opts.writev;
|
|
1514
|
+
if (opts.write) this._write = opts.write;
|
|
1515
|
+
if (opts.final) this._final = opts.final;
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
cork() {
|
|
1519
|
+
this._duplexState |= WRITE_CORKED;
|
|
1520
|
+
}
|
|
1521
|
+
uncork() {
|
|
1522
|
+
this._duplexState &= WRITE_NOT_CORKED;
|
|
1523
|
+
this._writableState.updateNextTick();
|
|
1524
|
+
}
|
|
1525
|
+
_writev(batch, cb) {
|
|
1526
|
+
cb(null);
|
|
1527
|
+
}
|
|
1528
|
+
_write(data, cb) {
|
|
1529
|
+
this._writableState.autoBatch(data, cb);
|
|
1530
|
+
}
|
|
1531
|
+
_final(cb) {
|
|
1532
|
+
cb(null);
|
|
1533
|
+
}
|
|
1534
|
+
write(data) {
|
|
1535
|
+
this._writableState.updateNextTick();
|
|
1536
|
+
return this._writableState.push(data);
|
|
1537
|
+
}
|
|
1538
|
+
end(data) {
|
|
1539
|
+
this._writableState.updateNextTick();
|
|
1540
|
+
this._writableState.end(data);
|
|
1541
|
+
return this;
|
|
1542
|
+
}
|
|
1543
|
+
};
|
|
1544
|
+
var Transform = class extends Duplex {
|
|
1545
|
+
constructor(opts) {
|
|
1546
|
+
super(opts);
|
|
1547
|
+
this._transformState = new TransformState(this);
|
|
1548
|
+
if (opts) {
|
|
1549
|
+
if (opts.transform) this._transform = opts.transform;
|
|
1550
|
+
if (opts.flush) this._flush = opts.flush;
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
_write(data, cb) {
|
|
1554
|
+
if (this._readableState.buffered >= this._readableState.highWaterMark) {
|
|
1555
|
+
this._transformState.data = data;
|
|
1556
|
+
} else {
|
|
1557
|
+
this._transform(data, this._transformState.afterTransform);
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1560
|
+
_read(cb) {
|
|
1561
|
+
if (this._transformState.data !== null) {
|
|
1562
|
+
const data = this._transformState.data;
|
|
1563
|
+
this._transformState.data = null;
|
|
1564
|
+
cb(null);
|
|
1565
|
+
this._transform(data, this._transformState.afterTransform);
|
|
1566
|
+
} else {
|
|
1567
|
+
cb(null);
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
destroy(err) {
|
|
1571
|
+
super.destroy(err);
|
|
1572
|
+
if (this._transformState.data !== null) {
|
|
1573
|
+
this._transformState.data = null;
|
|
1574
|
+
this._transformState.afterTransform();
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
_transform(data, cb) {
|
|
1578
|
+
cb(null, data);
|
|
1579
|
+
}
|
|
1580
|
+
_flush(cb) {
|
|
1581
|
+
cb(null);
|
|
1582
|
+
}
|
|
1583
|
+
_final(cb) {
|
|
1584
|
+
this._transformState.afterFinal = cb;
|
|
1585
|
+
this._flush(transformAfterFlush.bind(this));
|
|
1586
|
+
}
|
|
1587
|
+
};
|
|
1588
|
+
var PassThrough = class extends Transform {
|
|
1589
|
+
};
|
|
1590
|
+
function transformAfterFlush(err, data) {
|
|
1591
|
+
const cb = this._transformState.afterFinal;
|
|
1592
|
+
if (err) return cb(err);
|
|
1593
|
+
if (data !== null && data !== void 0) this.push(data);
|
|
1594
|
+
this.push(null);
|
|
1595
|
+
cb(null);
|
|
1596
|
+
}
|
|
1597
|
+
function pipelinePromise(...streams) {
|
|
1598
|
+
return new Promise((resolve3, reject) => {
|
|
1599
|
+
return pipeline2(...streams, (err) => {
|
|
1600
|
+
if (err) return reject(err);
|
|
1601
|
+
resolve3();
|
|
1602
|
+
});
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
function pipeline2(stream, ...streams) {
|
|
1606
|
+
const all = Array.isArray(stream) ? [...stream, ...streams] : [stream, ...streams];
|
|
1607
|
+
const done = all.length && typeof all[all.length - 1] === "function" ? all.pop() : null;
|
|
1608
|
+
if (all.length < 2) throw StreamError.BAD_ARGUMENT("Pipeline requires at least 2 streams");
|
|
1609
|
+
let src = all[0];
|
|
1610
|
+
let dest = null;
|
|
1611
|
+
let error = null;
|
|
1612
|
+
for (let i = 1; i < all.length; i++) {
|
|
1613
|
+
dest = all[i];
|
|
1614
|
+
if (isStreamx(src)) {
|
|
1615
|
+
src.pipe(dest, onerror);
|
|
1616
|
+
} else {
|
|
1617
|
+
errorHandle(src, true, i > 1, onerror);
|
|
1618
|
+
src.pipe(dest);
|
|
1619
|
+
}
|
|
1620
|
+
src = dest;
|
|
1621
|
+
}
|
|
1622
|
+
if (done) {
|
|
1623
|
+
let fin = false;
|
|
1624
|
+
const autoDestroy = isStreamx(dest) || !!(dest._writableState && dest._writableState.autoDestroy);
|
|
1625
|
+
dest.on("error", (err) => {
|
|
1626
|
+
if (error === null) error = err;
|
|
1627
|
+
});
|
|
1628
|
+
dest.on("finish", () => {
|
|
1629
|
+
fin = true;
|
|
1630
|
+
if (!autoDestroy) done(error);
|
|
1631
|
+
});
|
|
1632
|
+
if (autoDestroy) {
|
|
1633
|
+
dest.on("close", () => done(error || (fin ? null : StreamError.PREMATURE_CLOSE())));
|
|
1634
|
+
}
|
|
1635
|
+
}
|
|
1636
|
+
return dest;
|
|
1637
|
+
function errorHandle(s, rd, wr, onerror2) {
|
|
1638
|
+
s.on("error", onerror2);
|
|
1639
|
+
s.on("close", onclose);
|
|
1640
|
+
function onclose() {
|
|
1641
|
+
if (s._readableState && !s._readableState.ended) {
|
|
1642
|
+
return onerror2(StreamError.PREMATURE_CLOSE());
|
|
1643
|
+
}
|
|
1644
|
+
if (wr && s._writableState && !s._writableState.ended) {
|
|
1645
|
+
return onerror2(StreamError.PREMATURE_CLOSE());
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
}
|
|
1649
|
+
function onerror(err) {
|
|
1650
|
+
if (!err || error) return;
|
|
1651
|
+
error = err;
|
|
1652
|
+
for (const s of all) {
|
|
1653
|
+
s.destroy(err);
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
}
|
|
1657
|
+
function echo(s) {
|
|
1658
|
+
return s;
|
|
1659
|
+
}
|
|
1660
|
+
function isStream(stream) {
|
|
1661
|
+
return !!stream._readableState || !!stream._writableState;
|
|
1662
|
+
}
|
|
1663
|
+
function isStreamx(stream) {
|
|
1664
|
+
return typeof stream._duplexState === "number" && isStream(stream);
|
|
1665
|
+
}
|
|
1666
|
+
function isEnding(stream) {
|
|
1667
|
+
return !!stream._readableState && stream._readableState.ending;
|
|
1668
|
+
}
|
|
1669
|
+
function isEnded(stream) {
|
|
1670
|
+
return !!stream._readableState && stream._readableState.ended;
|
|
1671
|
+
}
|
|
1672
|
+
function isFinishing(stream) {
|
|
1673
|
+
return !!stream._writableState && stream._writableState.ending;
|
|
1674
|
+
}
|
|
1675
|
+
function isFinished(stream) {
|
|
1676
|
+
return !!stream._writableState && stream._writableState.ended;
|
|
1677
|
+
}
|
|
1678
|
+
function getStreamError(stream, opts = {}) {
|
|
1679
|
+
const err = stream._readableState && stream._readableState.error || stream._writableState && stream._writableState.error;
|
|
1680
|
+
return !opts.all && StreamError.isStreamDestroyed(err) ? null : err;
|
|
1681
|
+
}
|
|
1682
|
+
function isReadStreamx(stream) {
|
|
1683
|
+
return isStreamx(stream) && stream.readable;
|
|
1684
|
+
}
|
|
1685
|
+
function isDisturbed(stream) {
|
|
1686
|
+
return (stream._duplexState & OPENING) !== OPENING || (stream._duplexState & DESTROYING) === DESTROYING || (stream._duplexState & ACTIVE_OR_TICKING) !== 0;
|
|
1687
|
+
}
|
|
1688
|
+
function isTypedArray(data) {
|
|
1689
|
+
return typeof data === "object" && data !== null && typeof data.byteLength === "number";
|
|
1690
|
+
}
|
|
1691
|
+
function defaultByteLength(data) {
|
|
1692
|
+
return isTypedArray(data) ? data.byteLength : 1024;
|
|
1693
|
+
}
|
|
1694
|
+
function noop() {
|
|
1695
|
+
}
|
|
1696
|
+
function abort() {
|
|
1697
|
+
this.destroy(StreamError.ABORTED());
|
|
1698
|
+
}
|
|
1699
|
+
function isWritev(s) {
|
|
1700
|
+
return s._writev !== Writable.prototype._writev && s._writev !== Duplex.prototype._writev;
|
|
1701
|
+
}
|
|
1702
|
+
module.exports = {
|
|
1703
|
+
pipeline: pipeline2,
|
|
1704
|
+
pipelinePromise,
|
|
1705
|
+
isStream,
|
|
1706
|
+
isStreamx,
|
|
1707
|
+
isEnding,
|
|
1708
|
+
isEnded,
|
|
1709
|
+
isFinishing,
|
|
1710
|
+
isFinished,
|
|
1711
|
+
isDisturbed,
|
|
1712
|
+
getStreamError,
|
|
1713
|
+
Stream,
|
|
1714
|
+
Writable,
|
|
1715
|
+
Readable: Readable2,
|
|
1716
|
+
Duplex,
|
|
1717
|
+
Transform,
|
|
1718
|
+
// Export PassThrough for compatibility with Node.js core's stream module
|
|
1719
|
+
PassThrough
|
|
1720
|
+
};
|
|
1721
|
+
}
|
|
1722
|
+
});
|
|
1723
|
+
|
|
1724
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-stream/headers.js
|
|
1725
|
+
var require_headers = __commonJS({
|
|
1726
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-stream/headers.js"(exports) {
|
|
1727
|
+
var b4a = require_b4a();
|
|
1728
|
+
var ZEROS = "0000000000000000000";
|
|
1729
|
+
var SEVENS = "7777777777777777777";
|
|
1730
|
+
var ZERO_OFFSET = "0".charCodeAt(0);
|
|
1731
|
+
var USTAR_MAGIC = b4a.from([117, 115, 116, 97, 114, 0]);
|
|
1732
|
+
var USTAR_VER = b4a.from([ZERO_OFFSET, ZERO_OFFSET]);
|
|
1733
|
+
var GNU_MAGIC = b4a.from([117, 115, 116, 97, 114, 32]);
|
|
1734
|
+
var GNU_VER = b4a.from([32, 0]);
|
|
1735
|
+
var MASK = 4095;
|
|
1736
|
+
var MAGIC_OFFSET = 257;
|
|
1737
|
+
var VERSION_OFFSET = 263;
|
|
1738
|
+
exports.decodeLongPath = function decodeLongPath(buf, encoding) {
|
|
1739
|
+
return decodeStr(buf, 0, buf.length, encoding);
|
|
1740
|
+
};
|
|
1741
|
+
exports.encodePax = function encodePax(opts) {
|
|
1742
|
+
let result = "";
|
|
1743
|
+
if (opts.name) result += addLength(" path=" + opts.name + "\n");
|
|
1744
|
+
if (opts.linkname) result += addLength(" linkpath=" + opts.linkname + "\n");
|
|
1745
|
+
const pax = opts.pax;
|
|
1746
|
+
if (pax) {
|
|
1747
|
+
for (const key in pax) {
|
|
1748
|
+
result += addLength(" " + key + "=" + pax[key] + "\n");
|
|
1749
|
+
}
|
|
1750
|
+
}
|
|
1751
|
+
return b4a.from(result);
|
|
1752
|
+
};
|
|
1753
|
+
exports.decodePax = function decodePax(buf) {
|
|
1754
|
+
const result = {};
|
|
1755
|
+
while (buf.length) {
|
|
1756
|
+
let i = 0;
|
|
1757
|
+
while (i < buf.length && buf[i] !== 32) i++;
|
|
1758
|
+
const len = parseInt(b4a.toString(buf.subarray(0, i)), 10);
|
|
1759
|
+
if (!len) return result;
|
|
1760
|
+
const b = b4a.toString(buf.subarray(i + 1, len - 1));
|
|
1761
|
+
const keyIndex = b.indexOf("=");
|
|
1762
|
+
if (keyIndex === -1) return result;
|
|
1763
|
+
result[b.slice(0, keyIndex)] = b.slice(keyIndex + 1);
|
|
1764
|
+
buf = buf.subarray(len);
|
|
1765
|
+
}
|
|
1766
|
+
return result;
|
|
1767
|
+
};
|
|
1768
|
+
exports.encode = function encode(opts) {
|
|
1769
|
+
const buf = b4a.alloc(512);
|
|
1770
|
+
let name = opts.name;
|
|
1771
|
+
let prefix = "";
|
|
1772
|
+
if (opts.typeflag === 5 && name[name.length - 1] !== "/") name += "/";
|
|
1773
|
+
if (b4a.byteLength(name) !== name.length) return null;
|
|
1774
|
+
while (b4a.byteLength(name) > 100) {
|
|
1775
|
+
const i = name.indexOf("/");
|
|
1776
|
+
if (i === -1) return null;
|
|
1777
|
+
prefix += prefix ? "/" + name.slice(0, i) : name.slice(0, i);
|
|
1778
|
+
name = name.slice(i + 1);
|
|
1779
|
+
}
|
|
1780
|
+
if (b4a.byteLength(name) > 100 || b4a.byteLength(prefix) > 155) return null;
|
|
1781
|
+
if (opts.linkname && b4a.byteLength(opts.linkname) > 100) return null;
|
|
1782
|
+
b4a.write(buf, name);
|
|
1783
|
+
b4a.write(buf, encodeOct(opts.mode & MASK, 6), 100);
|
|
1784
|
+
b4a.write(buf, encodeOct(opts.uid, 6), 108);
|
|
1785
|
+
b4a.write(buf, encodeOct(opts.gid, 6), 116);
|
|
1786
|
+
encodeSize(opts.size, buf, 124);
|
|
1787
|
+
b4a.write(buf, encodeOct(opts.mtime.getTime() / 1e3 | 0, 11), 136);
|
|
1788
|
+
buf[156] = ZERO_OFFSET + toTypeflag(opts.type);
|
|
1789
|
+
if (opts.linkname) b4a.write(buf, opts.linkname, 157);
|
|
1790
|
+
b4a.copy(USTAR_MAGIC, buf, MAGIC_OFFSET);
|
|
1791
|
+
b4a.copy(USTAR_VER, buf, VERSION_OFFSET);
|
|
1792
|
+
if (opts.uname) b4a.write(buf, opts.uname, 265);
|
|
1793
|
+
if (opts.gname) b4a.write(buf, opts.gname, 297);
|
|
1794
|
+
b4a.write(buf, encodeOct(opts.devmajor || 0, 6), 329);
|
|
1795
|
+
b4a.write(buf, encodeOct(opts.devminor || 0, 6), 337);
|
|
1796
|
+
if (prefix) b4a.write(buf, prefix, 345);
|
|
1797
|
+
b4a.write(buf, encodeOct(cksum(buf), 6), 148);
|
|
1798
|
+
return buf;
|
|
1799
|
+
};
|
|
1800
|
+
exports.decode = function decode(buf, filenameEncoding, allowUnknownFormat) {
|
|
1801
|
+
let typeflag = buf[156] === 0 ? 0 : buf[156] - ZERO_OFFSET;
|
|
1802
|
+
let name = decodeStr(buf, 0, 100, filenameEncoding);
|
|
1803
|
+
const mode = decodeOct(buf, 100, 8);
|
|
1804
|
+
const uid = decodeOct(buf, 108, 8);
|
|
1805
|
+
const gid = decodeOct(buf, 116, 8);
|
|
1806
|
+
const size = decodeOct(buf, 124, 12);
|
|
1807
|
+
const mtime = decodeOct(buf, 136, 12);
|
|
1808
|
+
const type = toType(typeflag);
|
|
1809
|
+
const linkname = buf[157] === 0 ? null : decodeStr(buf, 157, 100, filenameEncoding);
|
|
1810
|
+
const uname = decodeStr(buf, 265, 32);
|
|
1811
|
+
const gname = decodeStr(buf, 297, 32);
|
|
1812
|
+
const devmajor = decodeOct(buf, 329, 8);
|
|
1813
|
+
const devminor = decodeOct(buf, 337, 8);
|
|
1814
|
+
const c = cksum(buf);
|
|
1815
|
+
if (c === 8 * 32) return null;
|
|
1816
|
+
if (c !== decodeOct(buf, 148, 8)) throw new Error("Invalid tar header. Maybe the tar is corrupted or it needs to be gunzipped?");
|
|
1817
|
+
if (isUSTAR(buf)) {
|
|
1818
|
+
if (buf[345]) name = decodeStr(buf, 345, 155, filenameEncoding) + "/" + name;
|
|
1819
|
+
} else if (isGNU(buf)) ; else {
|
|
1820
|
+
if (!allowUnknownFormat) {
|
|
1821
|
+
throw new Error("Invalid tar header: unknown format.");
|
|
1822
|
+
}
|
|
1823
|
+
}
|
|
1824
|
+
if (typeflag === 0 && name && name[name.length - 1] === "/") typeflag = 5;
|
|
1825
|
+
return {
|
|
1826
|
+
name,
|
|
1827
|
+
mode,
|
|
1828
|
+
uid,
|
|
1829
|
+
gid,
|
|
1830
|
+
size,
|
|
1831
|
+
mtime: new Date(1e3 * mtime),
|
|
1832
|
+
type,
|
|
1833
|
+
linkname,
|
|
1834
|
+
uname,
|
|
1835
|
+
gname,
|
|
1836
|
+
devmajor,
|
|
1837
|
+
devminor,
|
|
1838
|
+
pax: null
|
|
1839
|
+
};
|
|
1840
|
+
};
|
|
1841
|
+
function isUSTAR(buf) {
|
|
1842
|
+
return b4a.equals(USTAR_MAGIC, buf.subarray(MAGIC_OFFSET, MAGIC_OFFSET + 6));
|
|
1843
|
+
}
|
|
1844
|
+
function isGNU(buf) {
|
|
1845
|
+
return b4a.equals(GNU_MAGIC, buf.subarray(MAGIC_OFFSET, MAGIC_OFFSET + 6)) && b4a.equals(GNU_VER, buf.subarray(VERSION_OFFSET, VERSION_OFFSET + 2));
|
|
1846
|
+
}
|
|
1847
|
+
function clamp(index, len, defaultValue) {
|
|
1848
|
+
if (typeof index !== "number") return defaultValue;
|
|
1849
|
+
index = ~~index;
|
|
1850
|
+
if (index >= len) return len;
|
|
1851
|
+
if (index >= 0) return index;
|
|
1852
|
+
index += len;
|
|
1853
|
+
if (index >= 0) return index;
|
|
1854
|
+
return 0;
|
|
1855
|
+
}
|
|
1856
|
+
function toType(flag) {
|
|
1857
|
+
switch (flag) {
|
|
1858
|
+
case 0:
|
|
1859
|
+
return "file";
|
|
1860
|
+
case 1:
|
|
1861
|
+
return "link";
|
|
1862
|
+
case 2:
|
|
1863
|
+
return "symlink";
|
|
1864
|
+
case 3:
|
|
1865
|
+
return "character-device";
|
|
1866
|
+
case 4:
|
|
1867
|
+
return "block-device";
|
|
1868
|
+
case 5:
|
|
1869
|
+
return "directory";
|
|
1870
|
+
case 6:
|
|
1871
|
+
return "fifo";
|
|
1872
|
+
case 7:
|
|
1873
|
+
return "contiguous-file";
|
|
1874
|
+
case 72:
|
|
1875
|
+
return "pax-header";
|
|
1876
|
+
case 55:
|
|
1877
|
+
return "pax-global-header";
|
|
1878
|
+
case 27:
|
|
1879
|
+
return "gnu-long-link-path";
|
|
1880
|
+
case 28:
|
|
1881
|
+
case 30:
|
|
1882
|
+
return "gnu-long-path";
|
|
1883
|
+
}
|
|
1884
|
+
return null;
|
|
1885
|
+
}
|
|
1886
|
+
function toTypeflag(flag) {
|
|
1887
|
+
switch (flag) {
|
|
1888
|
+
case "file":
|
|
1889
|
+
return 0;
|
|
1890
|
+
case "link":
|
|
1891
|
+
return 1;
|
|
1892
|
+
case "symlink":
|
|
1893
|
+
return 2;
|
|
1894
|
+
case "character-device":
|
|
1895
|
+
return 3;
|
|
1896
|
+
case "block-device":
|
|
1897
|
+
return 4;
|
|
1898
|
+
case "directory":
|
|
1899
|
+
return 5;
|
|
1900
|
+
case "fifo":
|
|
1901
|
+
return 6;
|
|
1902
|
+
case "contiguous-file":
|
|
1903
|
+
return 7;
|
|
1904
|
+
case "pax-header":
|
|
1905
|
+
return 72;
|
|
1906
|
+
}
|
|
1907
|
+
return 0;
|
|
1908
|
+
}
|
|
1909
|
+
function indexOf(block, num, offset, end) {
|
|
1910
|
+
for (; offset < end; offset++) {
|
|
1911
|
+
if (block[offset] === num) return offset;
|
|
1912
|
+
}
|
|
1913
|
+
return end;
|
|
1914
|
+
}
|
|
1915
|
+
function cksum(block) {
|
|
1916
|
+
let sum = 8 * 32;
|
|
1917
|
+
for (let i = 0; i < 148; i++) sum += block[i];
|
|
1918
|
+
for (let j = 156; j < 512; j++) sum += block[j];
|
|
1919
|
+
return sum;
|
|
1920
|
+
}
|
|
1921
|
+
function encodeOct(val, n) {
|
|
1922
|
+
val = val.toString(8);
|
|
1923
|
+
if (val.length > n) return SEVENS.slice(0, n) + " ";
|
|
1924
|
+
return ZEROS.slice(0, n - val.length) + val + " ";
|
|
1925
|
+
}
|
|
1926
|
+
function encodeSizeBin(num, buf, off) {
|
|
1927
|
+
buf[off] = 128;
|
|
1928
|
+
for (let i = 11; i > 0; i--) {
|
|
1929
|
+
buf[off + i] = num & 255;
|
|
1930
|
+
num = Math.floor(num / 256);
|
|
1931
|
+
}
|
|
1932
|
+
}
|
|
1933
|
+
function encodeSize(num, buf, off) {
|
|
1934
|
+
if (num.toString(8).length > 11) {
|
|
1935
|
+
encodeSizeBin(num, buf, off);
|
|
1936
|
+
} else {
|
|
1937
|
+
b4a.write(buf, encodeOct(num, 11), off);
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
function parse256(buf) {
|
|
1941
|
+
let positive;
|
|
1942
|
+
if (buf[0] === 128) positive = true;
|
|
1943
|
+
else if (buf[0] === 255) positive = false;
|
|
1944
|
+
else return null;
|
|
1945
|
+
const tuple = [];
|
|
1946
|
+
let i;
|
|
1947
|
+
for (i = buf.length - 1; i > 0; i--) {
|
|
1948
|
+
const byte = buf[i];
|
|
1949
|
+
if (positive) tuple.push(byte);
|
|
1950
|
+
else tuple.push(255 - byte);
|
|
1951
|
+
}
|
|
1952
|
+
let sum = 0;
|
|
1953
|
+
const l = tuple.length;
|
|
1954
|
+
for (i = 0; i < l; i++) {
|
|
1955
|
+
sum += tuple[i] * Math.pow(256, i);
|
|
1956
|
+
}
|
|
1957
|
+
return positive ? sum : -1 * sum;
|
|
1958
|
+
}
|
|
1959
|
+
function decodeOct(val, offset, length) {
|
|
1960
|
+
val = val.subarray(offset, offset + length);
|
|
1961
|
+
offset = 0;
|
|
1962
|
+
if (val[offset] & 128) {
|
|
1963
|
+
return parse256(val);
|
|
1964
|
+
} else {
|
|
1965
|
+
while (offset < val.length && val[offset] === 32) offset++;
|
|
1966
|
+
const end = clamp(indexOf(val, 32, offset, val.length), val.length, val.length);
|
|
1967
|
+
while (offset < end && val[offset] === 0) offset++;
|
|
1968
|
+
if (end === offset) return 0;
|
|
1969
|
+
return parseInt(b4a.toString(val.subarray(offset, end)), 8);
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
function decodeStr(val, offset, length, encoding) {
|
|
1973
|
+
return b4a.toString(val.subarray(offset, indexOf(val, 0, offset, offset + length)), encoding);
|
|
1974
|
+
}
|
|
1975
|
+
function addLength(str) {
|
|
1976
|
+
const len = b4a.byteLength(str);
|
|
1977
|
+
let digits = Math.floor(Math.log(len) / Math.log(10)) + 1;
|
|
1978
|
+
if (len + digits >= Math.pow(10, digits)) digits++;
|
|
1979
|
+
return len + digits + str;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
});
|
|
1983
|
+
|
|
1984
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-stream/extract.js
|
|
1985
|
+
var require_extract = __commonJS({
|
|
1986
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-stream/extract.js"(exports, module) {
|
|
1987
|
+
var { Writable, Readable: Readable2, getStreamError } = require_streamx();
|
|
1988
|
+
var FIFO = require_fast_fifo();
|
|
1989
|
+
var b4a = require_b4a();
|
|
1990
|
+
var headers = require_headers();
|
|
1991
|
+
var EMPTY = b4a.alloc(0);
|
|
1992
|
+
var BufferList = class {
|
|
1993
|
+
constructor() {
|
|
1994
|
+
this.buffered = 0;
|
|
1995
|
+
this.shifted = 0;
|
|
1996
|
+
this.queue = new FIFO();
|
|
1997
|
+
this._offset = 0;
|
|
1998
|
+
}
|
|
1999
|
+
push(buffer) {
|
|
2000
|
+
this.buffered += buffer.byteLength;
|
|
2001
|
+
this.queue.push(buffer);
|
|
2002
|
+
}
|
|
2003
|
+
shiftFirst(size) {
|
|
2004
|
+
return this._buffered === 0 ? null : this._next(size);
|
|
2005
|
+
}
|
|
2006
|
+
shift(size) {
|
|
2007
|
+
if (size > this.buffered) return null;
|
|
2008
|
+
if (size === 0) return EMPTY;
|
|
2009
|
+
let chunk = this._next(size);
|
|
2010
|
+
if (size === chunk.byteLength) return chunk;
|
|
2011
|
+
const chunks = [chunk];
|
|
2012
|
+
while ((size -= chunk.byteLength) > 0) {
|
|
2013
|
+
chunk = this._next(size);
|
|
2014
|
+
chunks.push(chunk);
|
|
2015
|
+
}
|
|
2016
|
+
return b4a.concat(chunks);
|
|
2017
|
+
}
|
|
2018
|
+
_next(size) {
|
|
2019
|
+
const buf = this.queue.peek();
|
|
2020
|
+
const rem = buf.byteLength - this._offset;
|
|
2021
|
+
if (size >= rem) {
|
|
2022
|
+
const sub = this._offset ? buf.subarray(this._offset, buf.byteLength) : buf;
|
|
2023
|
+
this.queue.shift();
|
|
2024
|
+
this._offset = 0;
|
|
2025
|
+
this.buffered -= rem;
|
|
2026
|
+
this.shifted += rem;
|
|
2027
|
+
return sub;
|
|
2028
|
+
}
|
|
2029
|
+
this.buffered -= size;
|
|
2030
|
+
this.shifted += size;
|
|
2031
|
+
return buf.subarray(this._offset, this._offset += size);
|
|
2032
|
+
}
|
|
2033
|
+
};
|
|
2034
|
+
var Source = class extends Readable2 {
|
|
2035
|
+
constructor(self, header, offset) {
|
|
2036
|
+
super();
|
|
2037
|
+
this.header = header;
|
|
2038
|
+
this.offset = offset;
|
|
2039
|
+
this._parent = self;
|
|
2040
|
+
}
|
|
2041
|
+
_read(cb) {
|
|
2042
|
+
if (this.header.size === 0) {
|
|
2043
|
+
this.push(null);
|
|
2044
|
+
}
|
|
2045
|
+
if (this._parent._stream === this) {
|
|
2046
|
+
this._parent._update();
|
|
2047
|
+
}
|
|
2048
|
+
cb(null);
|
|
2049
|
+
}
|
|
2050
|
+
_predestroy() {
|
|
2051
|
+
this._parent.destroy(getStreamError(this));
|
|
2052
|
+
}
|
|
2053
|
+
_detach() {
|
|
2054
|
+
if (this._parent._stream === this) {
|
|
2055
|
+
this._parent._stream = null;
|
|
2056
|
+
this._parent._missing = overflow(this.header.size);
|
|
2057
|
+
this._parent._update();
|
|
2058
|
+
}
|
|
2059
|
+
}
|
|
2060
|
+
_destroy(cb) {
|
|
2061
|
+
this._detach();
|
|
2062
|
+
cb(null);
|
|
2063
|
+
}
|
|
2064
|
+
};
|
|
2065
|
+
var Extract = class extends Writable {
|
|
2066
|
+
constructor(opts) {
|
|
2067
|
+
super(opts);
|
|
2068
|
+
if (!opts) opts = {};
|
|
2069
|
+
this._buffer = new BufferList();
|
|
2070
|
+
this._offset = 0;
|
|
2071
|
+
this._header = null;
|
|
2072
|
+
this._stream = null;
|
|
2073
|
+
this._missing = 0;
|
|
2074
|
+
this._longHeader = false;
|
|
2075
|
+
this._callback = noop;
|
|
2076
|
+
this._locked = false;
|
|
2077
|
+
this._finished = false;
|
|
2078
|
+
this._pax = null;
|
|
2079
|
+
this._paxGlobal = null;
|
|
2080
|
+
this._gnuLongPath = null;
|
|
2081
|
+
this._gnuLongLinkPath = null;
|
|
2082
|
+
this._filenameEncoding = opts.filenameEncoding || "utf-8";
|
|
2083
|
+
this._allowUnknownFormat = !!opts.allowUnknownFormat;
|
|
2084
|
+
this._unlockBound = this._unlock.bind(this);
|
|
2085
|
+
}
|
|
2086
|
+
_unlock(err) {
|
|
2087
|
+
this._locked = false;
|
|
2088
|
+
if (err) {
|
|
2089
|
+
this.destroy(err);
|
|
2090
|
+
this._continueWrite(err);
|
|
2091
|
+
return;
|
|
2092
|
+
}
|
|
2093
|
+
this._update();
|
|
2094
|
+
}
|
|
2095
|
+
_consumeHeader() {
|
|
2096
|
+
if (this._locked) return false;
|
|
2097
|
+
this._offset = this._buffer.shifted;
|
|
2098
|
+
try {
|
|
2099
|
+
this._header = headers.decode(this._buffer.shift(512), this._filenameEncoding, this._allowUnknownFormat);
|
|
2100
|
+
} catch (err) {
|
|
2101
|
+
this._continueWrite(err);
|
|
2102
|
+
return false;
|
|
2103
|
+
}
|
|
2104
|
+
if (!this._header) return true;
|
|
2105
|
+
switch (this._header.type) {
|
|
2106
|
+
case "gnu-long-path":
|
|
2107
|
+
case "gnu-long-link-path":
|
|
2108
|
+
case "pax-global-header":
|
|
2109
|
+
case "pax-header":
|
|
2110
|
+
this._longHeader = true;
|
|
2111
|
+
this._missing = this._header.size;
|
|
2112
|
+
return true;
|
|
2113
|
+
}
|
|
2114
|
+
this._locked = true;
|
|
2115
|
+
this._applyLongHeaders();
|
|
2116
|
+
if (this._header.size === 0 || this._header.type === "directory") {
|
|
2117
|
+
this.emit("entry", this._header, this._createStream(), this._unlockBound);
|
|
2118
|
+
return true;
|
|
2119
|
+
}
|
|
2120
|
+
this._stream = this._createStream();
|
|
2121
|
+
this._missing = this._header.size;
|
|
2122
|
+
this.emit("entry", this._header, this._stream, this._unlockBound);
|
|
2123
|
+
return true;
|
|
2124
|
+
}
|
|
2125
|
+
_applyLongHeaders() {
|
|
2126
|
+
if (this._gnuLongPath) {
|
|
2127
|
+
this._header.name = this._gnuLongPath;
|
|
2128
|
+
this._gnuLongPath = null;
|
|
2129
|
+
}
|
|
2130
|
+
if (this._gnuLongLinkPath) {
|
|
2131
|
+
this._header.linkname = this._gnuLongLinkPath;
|
|
2132
|
+
this._gnuLongLinkPath = null;
|
|
2133
|
+
}
|
|
2134
|
+
if (this._pax) {
|
|
2135
|
+
if (this._pax.path) this._header.name = this._pax.path;
|
|
2136
|
+
if (this._pax.linkpath) this._header.linkname = this._pax.linkpath;
|
|
2137
|
+
if (this._pax.size) this._header.size = parseInt(this._pax.size, 10);
|
|
2138
|
+
this._header.pax = this._pax;
|
|
2139
|
+
this._pax = null;
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
_decodeLongHeader(buf) {
|
|
2143
|
+
switch (this._header.type) {
|
|
2144
|
+
case "gnu-long-path":
|
|
2145
|
+
this._gnuLongPath = headers.decodeLongPath(buf, this._filenameEncoding);
|
|
2146
|
+
break;
|
|
2147
|
+
case "gnu-long-link-path":
|
|
2148
|
+
this._gnuLongLinkPath = headers.decodeLongPath(buf, this._filenameEncoding);
|
|
2149
|
+
break;
|
|
2150
|
+
case "pax-global-header":
|
|
2151
|
+
this._paxGlobal = headers.decodePax(buf);
|
|
2152
|
+
break;
|
|
2153
|
+
case "pax-header":
|
|
2154
|
+
this._pax = this._paxGlobal === null ? headers.decodePax(buf) : Object.assign({}, this._paxGlobal, headers.decodePax(buf));
|
|
2155
|
+
break;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
_consumeLongHeader() {
|
|
2159
|
+
this._longHeader = false;
|
|
2160
|
+
this._missing = overflow(this._header.size);
|
|
2161
|
+
const buf = this._buffer.shift(this._header.size);
|
|
2162
|
+
try {
|
|
2163
|
+
this._decodeLongHeader(buf);
|
|
2164
|
+
} catch (err) {
|
|
2165
|
+
this._continueWrite(err);
|
|
2166
|
+
return false;
|
|
2167
|
+
}
|
|
2168
|
+
return true;
|
|
2169
|
+
}
|
|
2170
|
+
_consumeStream() {
|
|
2171
|
+
const buf = this._buffer.shiftFirst(this._missing);
|
|
2172
|
+
if (buf === null) return false;
|
|
2173
|
+
this._missing -= buf.byteLength;
|
|
2174
|
+
const drained = this._stream.push(buf);
|
|
2175
|
+
if (this._missing === 0) {
|
|
2176
|
+
this._stream.push(null);
|
|
2177
|
+
if (drained) this._stream._detach();
|
|
2178
|
+
return drained && this._locked === false;
|
|
2179
|
+
}
|
|
2180
|
+
return drained;
|
|
2181
|
+
}
|
|
2182
|
+
_createStream() {
|
|
2183
|
+
return new Source(this, this._header, this._offset);
|
|
2184
|
+
}
|
|
2185
|
+
_update() {
|
|
2186
|
+
while (this._buffer.buffered > 0 && !this.destroying) {
|
|
2187
|
+
if (this._missing > 0) {
|
|
2188
|
+
if (this._stream !== null) {
|
|
2189
|
+
if (this._consumeStream() === false) return;
|
|
2190
|
+
continue;
|
|
2191
|
+
}
|
|
2192
|
+
if (this._longHeader === true) {
|
|
2193
|
+
if (this._missing > this._buffer.buffered) break;
|
|
2194
|
+
if (this._consumeLongHeader() === false) return false;
|
|
2195
|
+
continue;
|
|
2196
|
+
}
|
|
2197
|
+
const ignore = this._buffer.shiftFirst(this._missing);
|
|
2198
|
+
if (ignore !== null) this._missing -= ignore.byteLength;
|
|
2199
|
+
continue;
|
|
2200
|
+
}
|
|
2201
|
+
if (this._buffer.buffered < 512) break;
|
|
2202
|
+
if (this._stream !== null || this._consumeHeader() === false) return;
|
|
2203
|
+
}
|
|
2204
|
+
this._continueWrite(null);
|
|
2205
|
+
}
|
|
2206
|
+
_continueWrite(err) {
|
|
2207
|
+
const cb = this._callback;
|
|
2208
|
+
this._callback = noop;
|
|
2209
|
+
cb(err);
|
|
2210
|
+
}
|
|
2211
|
+
_write(data, cb) {
|
|
2212
|
+
this._callback = cb;
|
|
2213
|
+
this._buffer.push(data);
|
|
2214
|
+
this._update();
|
|
2215
|
+
}
|
|
2216
|
+
_final(cb) {
|
|
2217
|
+
this._finished = this._missing === 0 && this._buffer.buffered === 0;
|
|
2218
|
+
cb(this._finished ? null : new Error("Unexpected end of data"));
|
|
2219
|
+
}
|
|
2220
|
+
_predestroy() {
|
|
2221
|
+
this._continueWrite(null);
|
|
2222
|
+
}
|
|
2223
|
+
_destroy(cb) {
|
|
2224
|
+
if (this._stream) this._stream.destroy(getStreamError(this));
|
|
2225
|
+
cb(null);
|
|
2226
|
+
}
|
|
2227
|
+
[Symbol.asyncIterator]() {
|
|
2228
|
+
let error = null;
|
|
2229
|
+
let promiseResolve = null;
|
|
2230
|
+
let promiseReject = null;
|
|
2231
|
+
let entryStream = null;
|
|
2232
|
+
let entryCallback = null;
|
|
2233
|
+
const extract3 = this;
|
|
2234
|
+
this.on("entry", onentry);
|
|
2235
|
+
this.on("error", (err) => {
|
|
2236
|
+
error = err;
|
|
2237
|
+
});
|
|
2238
|
+
this.on("close", onclose);
|
|
2239
|
+
return {
|
|
2240
|
+
[Symbol.asyncIterator]() {
|
|
2241
|
+
return this;
|
|
2242
|
+
},
|
|
2243
|
+
next() {
|
|
2244
|
+
return new Promise(onnext);
|
|
2245
|
+
},
|
|
2246
|
+
return() {
|
|
2247
|
+
return destroy(null);
|
|
2248
|
+
},
|
|
2249
|
+
throw(err) {
|
|
2250
|
+
return destroy(err);
|
|
2251
|
+
}
|
|
2252
|
+
};
|
|
2253
|
+
function consumeCallback(err) {
|
|
2254
|
+
if (!entryCallback) return;
|
|
2255
|
+
const cb = entryCallback;
|
|
2256
|
+
entryCallback = null;
|
|
2257
|
+
cb(err);
|
|
2258
|
+
}
|
|
2259
|
+
function onnext(resolve3, reject) {
|
|
2260
|
+
if (error) {
|
|
2261
|
+
return reject(error);
|
|
2262
|
+
}
|
|
2263
|
+
if (entryStream) {
|
|
2264
|
+
resolve3({ value: entryStream, done: false });
|
|
2265
|
+
entryStream = null;
|
|
2266
|
+
return;
|
|
2267
|
+
}
|
|
2268
|
+
promiseResolve = resolve3;
|
|
2269
|
+
promiseReject = reject;
|
|
2270
|
+
consumeCallback(null);
|
|
2271
|
+
if (extract3._finished && promiseResolve) {
|
|
2272
|
+
promiseResolve({ value: void 0, done: true });
|
|
2273
|
+
promiseResolve = promiseReject = null;
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
function onentry(header, stream, callback) {
|
|
2277
|
+
entryCallback = callback;
|
|
2278
|
+
stream.on("error", noop);
|
|
2279
|
+
if (promiseResolve) {
|
|
2280
|
+
promiseResolve({ value: stream, done: false });
|
|
2281
|
+
promiseResolve = promiseReject = null;
|
|
2282
|
+
} else {
|
|
2283
|
+
entryStream = stream;
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
function onclose() {
|
|
2287
|
+
consumeCallback(error);
|
|
2288
|
+
if (!promiseResolve) return;
|
|
2289
|
+
if (error) promiseReject(error);
|
|
2290
|
+
else promiseResolve({ value: void 0, done: true });
|
|
2291
|
+
promiseResolve = promiseReject = null;
|
|
2292
|
+
}
|
|
2293
|
+
function destroy(err) {
|
|
2294
|
+
extract3.destroy(err);
|
|
2295
|
+
consumeCallback(err);
|
|
2296
|
+
return new Promise((resolve3, reject) => {
|
|
2297
|
+
if (extract3.destroyed) return resolve3({ value: void 0, done: true });
|
|
2298
|
+
extract3.once("close", function() {
|
|
2299
|
+
if (err) reject(err);
|
|
2300
|
+
else resolve3({ value: void 0, done: true });
|
|
2301
|
+
});
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
};
|
|
2306
|
+
module.exports = function extract3(opts) {
|
|
2307
|
+
return new Extract(opts);
|
|
2308
|
+
};
|
|
2309
|
+
function noop() {
|
|
2310
|
+
}
|
|
2311
|
+
function overflow(size) {
|
|
2312
|
+
size &= 511;
|
|
2313
|
+
return size && 512 - size;
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
});
|
|
2317
|
+
|
|
2318
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-stream/constants.js
|
|
2319
|
+
var require_constants = __commonJS({
|
|
2320
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-stream/constants.js"(exports, module) {
|
|
2321
|
+
var constants = {
|
|
2322
|
+
// just for envs without fs
|
|
2323
|
+
S_IFMT: 61440,
|
|
2324
|
+
S_IFDIR: 16384,
|
|
2325
|
+
S_IFCHR: 8192,
|
|
2326
|
+
S_IFBLK: 24576,
|
|
2327
|
+
S_IFIFO: 4096,
|
|
2328
|
+
S_IFLNK: 40960
|
|
2329
|
+
};
|
|
2330
|
+
try {
|
|
2331
|
+
module.exports = __require("fs").constants || constants;
|
|
2332
|
+
} catch {
|
|
2333
|
+
module.exports = constants;
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
});
|
|
2337
|
+
|
|
2338
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-stream/pack.js
|
|
2339
|
+
var require_pack = __commonJS({
|
|
2340
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-stream/pack.js"(exports, module) {
|
|
2341
|
+
var { Readable: Readable2, Writable, getStreamError } = require_streamx();
|
|
2342
|
+
var b4a = require_b4a();
|
|
2343
|
+
var constants = require_constants();
|
|
2344
|
+
var headers = require_headers();
|
|
2345
|
+
var DMODE = 493;
|
|
2346
|
+
var FMODE = 420;
|
|
2347
|
+
var END_OF_TAR = b4a.alloc(1024);
|
|
2348
|
+
var Sink = class extends Writable {
|
|
2349
|
+
constructor(pack, header, callback) {
|
|
2350
|
+
super({ mapWritable, eagerOpen: true });
|
|
2351
|
+
this.written = 0;
|
|
2352
|
+
this.header = header;
|
|
2353
|
+
this._callback = callback;
|
|
2354
|
+
this._linkname = null;
|
|
2355
|
+
this._isLinkname = header.type === "symlink" && !header.linkname;
|
|
2356
|
+
this._isVoid = header.type !== "file" && header.type !== "contiguous-file";
|
|
2357
|
+
this._finished = false;
|
|
2358
|
+
this._pack = pack;
|
|
2359
|
+
this._openCallback = null;
|
|
2360
|
+
if (this._pack._stream === null) this._pack._stream = this;
|
|
2361
|
+
else this._pack._pending.push(this);
|
|
2362
|
+
}
|
|
2363
|
+
_open(cb) {
|
|
2364
|
+
this._openCallback = cb;
|
|
2365
|
+
if (this._pack._stream === this) this._continueOpen();
|
|
2366
|
+
}
|
|
2367
|
+
_continuePack(err) {
|
|
2368
|
+
if (this._callback === null) return;
|
|
2369
|
+
const callback = this._callback;
|
|
2370
|
+
this._callback = null;
|
|
2371
|
+
callback(err);
|
|
2372
|
+
}
|
|
2373
|
+
_continueOpen() {
|
|
2374
|
+
if (this._pack._stream === null) this._pack._stream = this;
|
|
2375
|
+
const cb = this._openCallback;
|
|
2376
|
+
this._openCallback = null;
|
|
2377
|
+
if (cb === null) return;
|
|
2378
|
+
if (this._pack.destroying) return cb(new Error("pack stream destroyed"));
|
|
2379
|
+
if (this._pack._finalized) return cb(new Error("pack stream is already finalized"));
|
|
2380
|
+
this._pack._stream = this;
|
|
2381
|
+
if (!this._isLinkname) {
|
|
2382
|
+
this._pack._encode(this.header);
|
|
2383
|
+
}
|
|
2384
|
+
if (this._isVoid) {
|
|
2385
|
+
this._finish();
|
|
2386
|
+
this._continuePack(null);
|
|
2387
|
+
}
|
|
2388
|
+
cb(null);
|
|
2389
|
+
}
|
|
2390
|
+
_write(data, cb) {
|
|
2391
|
+
if (this._isLinkname) {
|
|
2392
|
+
this._linkname = this._linkname ? b4a.concat([this._linkname, data]) : data;
|
|
2393
|
+
return cb(null);
|
|
2394
|
+
}
|
|
2395
|
+
if (this._isVoid) {
|
|
2396
|
+
if (data.byteLength > 0) {
|
|
2397
|
+
return cb(new Error("No body allowed for this entry"));
|
|
2398
|
+
}
|
|
2399
|
+
return cb();
|
|
2400
|
+
}
|
|
2401
|
+
this.written += data.byteLength;
|
|
2402
|
+
if (this._pack.push(data)) return cb();
|
|
2403
|
+
this._pack._drain = cb;
|
|
2404
|
+
}
|
|
2405
|
+
_finish() {
|
|
2406
|
+
if (this._finished) return;
|
|
2407
|
+
this._finished = true;
|
|
2408
|
+
if (this._isLinkname) {
|
|
2409
|
+
this.header.linkname = this._linkname ? b4a.toString(this._linkname, "utf-8") : "";
|
|
2410
|
+
this._pack._encode(this.header);
|
|
2411
|
+
}
|
|
2412
|
+
overflow(this._pack, this.header.size);
|
|
2413
|
+
this._pack._done(this);
|
|
2414
|
+
}
|
|
2415
|
+
_final(cb) {
|
|
2416
|
+
if (this.written !== this.header.size) {
|
|
2417
|
+
return cb(new Error("Size mismatch"));
|
|
2418
|
+
}
|
|
2419
|
+
this._finish();
|
|
2420
|
+
cb(null);
|
|
2421
|
+
}
|
|
2422
|
+
_getError() {
|
|
2423
|
+
return getStreamError(this) || new Error("tar entry destroyed");
|
|
2424
|
+
}
|
|
2425
|
+
_predestroy() {
|
|
2426
|
+
this._pack.destroy(this._getError());
|
|
2427
|
+
}
|
|
2428
|
+
_destroy(cb) {
|
|
2429
|
+
this._pack._done(this);
|
|
2430
|
+
this._continuePack(this._finished ? null : this._getError());
|
|
2431
|
+
cb();
|
|
2432
|
+
}
|
|
2433
|
+
};
|
|
2434
|
+
var Pack = class extends Readable2 {
|
|
2435
|
+
constructor(opts) {
|
|
2436
|
+
super(opts);
|
|
2437
|
+
this._drain = noop;
|
|
2438
|
+
this._finalized = false;
|
|
2439
|
+
this._finalizing = false;
|
|
2440
|
+
this._pending = [];
|
|
2441
|
+
this._stream = null;
|
|
2442
|
+
}
|
|
2443
|
+
entry(header, buffer, callback) {
|
|
2444
|
+
if (this._finalized || this.destroying) throw new Error("already finalized or destroyed");
|
|
2445
|
+
if (typeof buffer === "function") {
|
|
2446
|
+
callback = buffer;
|
|
2447
|
+
buffer = null;
|
|
2448
|
+
}
|
|
2449
|
+
if (!callback) callback = noop;
|
|
2450
|
+
if (!header.size || header.type === "symlink") header.size = 0;
|
|
2451
|
+
if (!header.type) header.type = modeToType(header.mode);
|
|
2452
|
+
if (!header.mode) header.mode = header.type === "directory" ? DMODE : FMODE;
|
|
2453
|
+
if (!header.uid) header.uid = 0;
|
|
2454
|
+
if (!header.gid) header.gid = 0;
|
|
2455
|
+
if (!header.mtime) header.mtime = /* @__PURE__ */ new Date();
|
|
2456
|
+
if (typeof buffer === "string") buffer = b4a.from(buffer);
|
|
2457
|
+
const sink = new Sink(this, header, callback);
|
|
2458
|
+
if (b4a.isBuffer(buffer)) {
|
|
2459
|
+
header.size = buffer.byteLength;
|
|
2460
|
+
sink.write(buffer);
|
|
2461
|
+
sink.end();
|
|
2462
|
+
return sink;
|
|
2463
|
+
}
|
|
2464
|
+
if (sink._isVoid) {
|
|
2465
|
+
return sink;
|
|
2466
|
+
}
|
|
2467
|
+
return sink;
|
|
2468
|
+
}
|
|
2469
|
+
finalize() {
|
|
2470
|
+
if (this._stream || this._pending.length > 0) {
|
|
2471
|
+
this._finalizing = true;
|
|
2472
|
+
return;
|
|
2473
|
+
}
|
|
2474
|
+
if (this._finalized) return;
|
|
2475
|
+
this._finalized = true;
|
|
2476
|
+
this.push(END_OF_TAR);
|
|
2477
|
+
this.push(null);
|
|
2478
|
+
}
|
|
2479
|
+
_done(stream) {
|
|
2480
|
+
if (stream !== this._stream) return;
|
|
2481
|
+
this._stream = null;
|
|
2482
|
+
if (this._finalizing) this.finalize();
|
|
2483
|
+
if (this._pending.length) this._pending.shift()._continueOpen();
|
|
2484
|
+
}
|
|
2485
|
+
_encode(header) {
|
|
2486
|
+
if (!header.pax) {
|
|
2487
|
+
const buf = headers.encode(header);
|
|
2488
|
+
if (buf) {
|
|
2489
|
+
this.push(buf);
|
|
2490
|
+
return;
|
|
2491
|
+
}
|
|
2492
|
+
}
|
|
2493
|
+
this._encodePax(header);
|
|
2494
|
+
}
|
|
2495
|
+
_encodePax(header) {
|
|
2496
|
+
const paxHeader = headers.encodePax({
|
|
2497
|
+
name: header.name,
|
|
2498
|
+
linkname: header.linkname,
|
|
2499
|
+
pax: header.pax
|
|
2500
|
+
});
|
|
2501
|
+
const newHeader = {
|
|
2502
|
+
name: "PaxHeader",
|
|
2503
|
+
mode: header.mode,
|
|
2504
|
+
uid: header.uid,
|
|
2505
|
+
gid: header.gid,
|
|
2506
|
+
size: paxHeader.byteLength,
|
|
2507
|
+
mtime: header.mtime,
|
|
2508
|
+
type: "pax-header",
|
|
2509
|
+
linkname: header.linkname && "PaxHeader",
|
|
2510
|
+
uname: header.uname,
|
|
2511
|
+
gname: header.gname,
|
|
2512
|
+
devmajor: header.devmajor,
|
|
2513
|
+
devminor: header.devminor
|
|
2514
|
+
};
|
|
2515
|
+
this.push(headers.encode(newHeader));
|
|
2516
|
+
this.push(paxHeader);
|
|
2517
|
+
overflow(this, paxHeader.byteLength);
|
|
2518
|
+
newHeader.size = header.size;
|
|
2519
|
+
newHeader.type = header.type;
|
|
2520
|
+
this.push(headers.encode(newHeader));
|
|
2521
|
+
}
|
|
2522
|
+
_doDrain() {
|
|
2523
|
+
const drain = this._drain;
|
|
2524
|
+
this._drain = noop;
|
|
2525
|
+
drain();
|
|
2526
|
+
}
|
|
2527
|
+
_predestroy() {
|
|
2528
|
+
const err = getStreamError(this);
|
|
2529
|
+
if (this._stream) this._stream.destroy(err);
|
|
2530
|
+
while (this._pending.length) {
|
|
2531
|
+
const stream = this._pending.shift();
|
|
2532
|
+
stream.destroy(err);
|
|
2533
|
+
stream._continueOpen();
|
|
2534
|
+
}
|
|
2535
|
+
this._doDrain();
|
|
2536
|
+
}
|
|
2537
|
+
_read(cb) {
|
|
2538
|
+
this._doDrain();
|
|
2539
|
+
cb();
|
|
2540
|
+
}
|
|
2541
|
+
};
|
|
2542
|
+
module.exports = function pack(opts) {
|
|
2543
|
+
return new Pack(opts);
|
|
2544
|
+
};
|
|
2545
|
+
function modeToType(mode) {
|
|
2546
|
+
switch (mode & constants.S_IFMT) {
|
|
2547
|
+
case constants.S_IFBLK:
|
|
2548
|
+
return "block-device";
|
|
2549
|
+
case constants.S_IFCHR:
|
|
2550
|
+
return "character-device";
|
|
2551
|
+
case constants.S_IFDIR:
|
|
2552
|
+
return "directory";
|
|
2553
|
+
case constants.S_IFIFO:
|
|
2554
|
+
return "fifo";
|
|
2555
|
+
case constants.S_IFLNK:
|
|
2556
|
+
return "symlink";
|
|
2557
|
+
}
|
|
2558
|
+
return "file";
|
|
2559
|
+
}
|
|
2560
|
+
function noop() {
|
|
2561
|
+
}
|
|
2562
|
+
function overflow(self, size) {
|
|
2563
|
+
size &= 511;
|
|
2564
|
+
if (size) self.push(END_OF_TAR.subarray(0, 512 - size));
|
|
2565
|
+
}
|
|
2566
|
+
function mapWritable(buf) {
|
|
2567
|
+
return b4a.isBuffer(buf) ? buf : b4a.from(buf);
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
});
|
|
2571
|
+
|
|
2572
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-stream/index.js
|
|
2573
|
+
var require_tar_stream = __commonJS({
|
|
2574
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-stream/index.js"(exports) {
|
|
2575
|
+
exports.extract = require_extract();
|
|
2576
|
+
exports.pack = require_pack();
|
|
2577
|
+
}
|
|
2578
|
+
});
|
|
2579
|
+
|
|
2580
|
+
// ../../node_modules/wrappy/wrappy.js
|
|
2581
|
+
var require_wrappy = __commonJS({
|
|
2582
|
+
"../../node_modules/wrappy/wrappy.js"(exports, module) {
|
|
2583
|
+
module.exports = wrappy;
|
|
2584
|
+
function wrappy(fn, cb) {
|
|
2585
|
+
if (fn && cb) return wrappy(fn)(cb);
|
|
2586
|
+
if (typeof fn !== "function")
|
|
2587
|
+
throw new TypeError("need wrapper function");
|
|
2588
|
+
Object.keys(fn).forEach(function(k) {
|
|
2589
|
+
wrapper[k] = fn[k];
|
|
2590
|
+
});
|
|
2591
|
+
return wrapper;
|
|
2592
|
+
function wrapper() {
|
|
2593
|
+
var args = new Array(arguments.length);
|
|
2594
|
+
for (var i = 0; i < args.length; i++) {
|
|
2595
|
+
args[i] = arguments[i];
|
|
2596
|
+
}
|
|
2597
|
+
var ret = fn.apply(this, args);
|
|
2598
|
+
var cb2 = args[args.length - 1];
|
|
2599
|
+
if (typeof ret === "function" && ret !== cb2) {
|
|
2600
|
+
Object.keys(cb2).forEach(function(k) {
|
|
2601
|
+
ret[k] = cb2[k];
|
|
2602
|
+
});
|
|
2603
|
+
}
|
|
2604
|
+
return ret;
|
|
2605
|
+
}
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
});
|
|
2609
|
+
|
|
2610
|
+
// ../../node_modules/once/once.js
|
|
2611
|
+
var require_once = __commonJS({
|
|
2612
|
+
"../../node_modules/once/once.js"(exports, module) {
|
|
2613
|
+
var wrappy = require_wrappy();
|
|
2614
|
+
module.exports = wrappy(once);
|
|
2615
|
+
module.exports.strict = wrappy(onceStrict);
|
|
2616
|
+
once.proto = once(function() {
|
|
2617
|
+
Object.defineProperty(Function.prototype, "once", {
|
|
2618
|
+
value: function() {
|
|
2619
|
+
return once(this);
|
|
2620
|
+
},
|
|
2621
|
+
configurable: true
|
|
2622
|
+
});
|
|
2623
|
+
Object.defineProperty(Function.prototype, "onceStrict", {
|
|
2624
|
+
value: function() {
|
|
2625
|
+
return onceStrict(this);
|
|
2626
|
+
},
|
|
2627
|
+
configurable: true
|
|
2628
|
+
});
|
|
2629
|
+
});
|
|
2630
|
+
function once(fn) {
|
|
2631
|
+
var f = function() {
|
|
2632
|
+
if (f.called) return f.value;
|
|
2633
|
+
f.called = true;
|
|
2634
|
+
return f.value = fn.apply(this, arguments);
|
|
2635
|
+
};
|
|
2636
|
+
f.called = false;
|
|
2637
|
+
return f;
|
|
2638
|
+
}
|
|
2639
|
+
function onceStrict(fn) {
|
|
2640
|
+
var f = function() {
|
|
2641
|
+
if (f.called)
|
|
2642
|
+
throw new Error(f.onceError);
|
|
2643
|
+
f.called = true;
|
|
2644
|
+
return f.value = fn.apply(this, arguments);
|
|
2645
|
+
};
|
|
2646
|
+
var name = fn.name || "Function wrapped with `once`";
|
|
2647
|
+
f.onceError = name + " shouldn't be called more than once";
|
|
2648
|
+
f.called = false;
|
|
2649
|
+
return f;
|
|
2650
|
+
}
|
|
2651
|
+
}
|
|
2652
|
+
});
|
|
2653
|
+
|
|
2654
|
+
// ../../node_modules/end-of-stream/index.js
|
|
2655
|
+
var require_end_of_stream = __commonJS({
|
|
2656
|
+
"../../node_modules/end-of-stream/index.js"(exports, module) {
|
|
2657
|
+
var once = require_once();
|
|
2658
|
+
var noop = function() {
|
|
2659
|
+
};
|
|
2660
|
+
var qnt = global.Bare ? queueMicrotask : process.nextTick.bind(process);
|
|
2661
|
+
var isRequest = function(stream) {
|
|
2662
|
+
return stream.setHeader && typeof stream.abort === "function";
|
|
2663
|
+
};
|
|
2664
|
+
var isChildProcess = function(stream) {
|
|
2665
|
+
return stream.stdio && Array.isArray(stream.stdio) && stream.stdio.length === 3;
|
|
2666
|
+
};
|
|
2667
|
+
var eos = function(stream, opts, callback) {
|
|
2668
|
+
if (typeof opts === "function") return eos(stream, null, opts);
|
|
2669
|
+
if (!opts) opts = {};
|
|
2670
|
+
callback = once(callback || noop);
|
|
2671
|
+
var ws = stream._writableState;
|
|
2672
|
+
var rs = stream._readableState;
|
|
2673
|
+
var readable = opts.readable || opts.readable !== false && stream.readable;
|
|
2674
|
+
var writable = opts.writable || opts.writable !== false && stream.writable;
|
|
2675
|
+
var cancelled = false;
|
|
2676
|
+
var onlegacyfinish = function() {
|
|
2677
|
+
if (!stream.writable) onfinish();
|
|
2678
|
+
};
|
|
2679
|
+
var onfinish = function() {
|
|
2680
|
+
writable = false;
|
|
2681
|
+
if (!readable) callback.call(stream);
|
|
2682
|
+
};
|
|
2683
|
+
var onend = function() {
|
|
2684
|
+
readable = false;
|
|
2685
|
+
if (!writable) callback.call(stream);
|
|
2686
|
+
};
|
|
2687
|
+
var onexit = function(exitCode) {
|
|
2688
|
+
callback.call(stream, exitCode ? new Error("exited with error code: " + exitCode) : null);
|
|
2689
|
+
};
|
|
2690
|
+
var onerror = function(err) {
|
|
2691
|
+
callback.call(stream, err);
|
|
2692
|
+
};
|
|
2693
|
+
var onclose = function() {
|
|
2694
|
+
qnt(onclosenexttick);
|
|
2695
|
+
};
|
|
2696
|
+
var onclosenexttick = function() {
|
|
2697
|
+
if (cancelled) return;
|
|
2698
|
+
if (readable && !(rs && (rs.ended && !rs.destroyed))) return callback.call(stream, new Error("premature close"));
|
|
2699
|
+
if (writable && !(ws && (ws.ended && !ws.destroyed))) return callback.call(stream, new Error("premature close"));
|
|
2700
|
+
};
|
|
2701
|
+
var onrequest = function() {
|
|
2702
|
+
stream.req.on("finish", onfinish);
|
|
2703
|
+
};
|
|
2704
|
+
if (isRequest(stream)) {
|
|
2705
|
+
stream.on("complete", onfinish);
|
|
2706
|
+
stream.on("abort", onclose);
|
|
2707
|
+
if (stream.req) onrequest();
|
|
2708
|
+
else stream.on("request", onrequest);
|
|
2709
|
+
} else if (writable && !ws) {
|
|
2710
|
+
stream.on("end", onlegacyfinish);
|
|
2711
|
+
stream.on("close", onlegacyfinish);
|
|
2712
|
+
}
|
|
2713
|
+
if (isChildProcess(stream)) stream.on("exit", onexit);
|
|
2714
|
+
stream.on("end", onend);
|
|
2715
|
+
stream.on("finish", onfinish);
|
|
2716
|
+
if (opts.error !== false) stream.on("error", onerror);
|
|
2717
|
+
stream.on("close", onclose);
|
|
2718
|
+
return function() {
|
|
2719
|
+
cancelled = true;
|
|
2720
|
+
stream.removeListener("complete", onfinish);
|
|
2721
|
+
stream.removeListener("abort", onclose);
|
|
2722
|
+
stream.removeListener("request", onrequest);
|
|
2723
|
+
if (stream.req) stream.req.removeListener("finish", onfinish);
|
|
2724
|
+
stream.removeListener("end", onlegacyfinish);
|
|
2725
|
+
stream.removeListener("close", onlegacyfinish);
|
|
2726
|
+
stream.removeListener("finish", onfinish);
|
|
2727
|
+
stream.removeListener("exit", onexit);
|
|
2728
|
+
stream.removeListener("end", onend);
|
|
2729
|
+
stream.removeListener("error", onerror);
|
|
2730
|
+
stream.removeListener("close", onclose);
|
|
2731
|
+
};
|
|
2732
|
+
};
|
|
2733
|
+
module.exports = eos;
|
|
2734
|
+
}
|
|
2735
|
+
});
|
|
2736
|
+
|
|
2737
|
+
// ../../node_modules/pump/index.js
|
|
2738
|
+
var require_pump = __commonJS({
|
|
2739
|
+
"../../node_modules/pump/index.js"(exports, module) {
|
|
2740
|
+
var once = require_once();
|
|
2741
|
+
var eos = require_end_of_stream();
|
|
2742
|
+
var fs;
|
|
2743
|
+
try {
|
|
2744
|
+
fs = __require("fs");
|
|
2745
|
+
} catch (e) {
|
|
2746
|
+
}
|
|
2747
|
+
var noop = function() {
|
|
2748
|
+
};
|
|
2749
|
+
var ancient = typeof process === "undefined" ? false : /^v?\.0/.test(process.version);
|
|
2750
|
+
var isFn = function(fn) {
|
|
2751
|
+
return typeof fn === "function";
|
|
2752
|
+
};
|
|
2753
|
+
var isFS = function(stream) {
|
|
2754
|
+
if (!ancient) return false;
|
|
2755
|
+
if (!fs) return false;
|
|
2756
|
+
return (stream instanceof (fs.ReadStream || noop) || stream instanceof (fs.WriteStream || noop)) && isFn(stream.close);
|
|
2757
|
+
};
|
|
2758
|
+
var isRequest = function(stream) {
|
|
2759
|
+
return stream.setHeader && isFn(stream.abort);
|
|
2760
|
+
};
|
|
2761
|
+
var destroyer = function(stream, reading, writing, callback) {
|
|
2762
|
+
callback = once(callback);
|
|
2763
|
+
var closed = false;
|
|
2764
|
+
stream.on("close", function() {
|
|
2765
|
+
closed = true;
|
|
2766
|
+
});
|
|
2767
|
+
eos(stream, { readable: reading, writable: writing }, function(err) {
|
|
2768
|
+
if (err) return callback(err);
|
|
2769
|
+
closed = true;
|
|
2770
|
+
callback();
|
|
2771
|
+
});
|
|
2772
|
+
var destroyed = false;
|
|
2773
|
+
return function(err) {
|
|
2774
|
+
if (closed) return;
|
|
2775
|
+
if (destroyed) return;
|
|
2776
|
+
destroyed = true;
|
|
2777
|
+
if (isFS(stream)) return stream.close(noop);
|
|
2778
|
+
if (isRequest(stream)) return stream.abort();
|
|
2779
|
+
if (isFn(stream.destroy)) return stream.destroy();
|
|
2780
|
+
callback(err || new Error("stream was destroyed"));
|
|
2781
|
+
};
|
|
2782
|
+
};
|
|
2783
|
+
var call = function(fn) {
|
|
2784
|
+
fn();
|
|
2785
|
+
};
|
|
2786
|
+
var pipe = function(from, to) {
|
|
2787
|
+
return from.pipe(to);
|
|
2788
|
+
};
|
|
2789
|
+
var pump = function() {
|
|
2790
|
+
var streams = Array.prototype.slice.call(arguments);
|
|
2791
|
+
var callback = isFn(streams[streams.length - 1] || noop) && streams.pop() || noop;
|
|
2792
|
+
if (Array.isArray(streams[0])) streams = streams[0];
|
|
2793
|
+
if (streams.length < 2) throw new Error("pump requires two streams per minimum");
|
|
2794
|
+
var error;
|
|
2795
|
+
var destroys = streams.map(function(stream, i) {
|
|
2796
|
+
var reading = i < streams.length - 1;
|
|
2797
|
+
var writing = i > 0;
|
|
2798
|
+
return destroyer(stream, reading, writing, function(err) {
|
|
2799
|
+
if (!error) error = err;
|
|
2800
|
+
if (err) destroys.forEach(call);
|
|
2801
|
+
if (reading) return;
|
|
2802
|
+
destroys.forEach(call);
|
|
2803
|
+
callback(error);
|
|
2804
|
+
});
|
|
2805
|
+
});
|
|
2806
|
+
return streams.reduce(pipe);
|
|
2807
|
+
};
|
|
2808
|
+
module.exports = pump;
|
|
2809
|
+
}
|
|
2810
|
+
});
|
|
17
2811
|
|
|
18
|
-
//
|
|
19
|
-
var
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
2812
|
+
// ../../node_modules/@sparticuz/chromium/node_modules/tar-fs/index.js
|
|
2813
|
+
var require_tar_fs = __commonJS({
|
|
2814
|
+
"../../node_modules/@sparticuz/chromium/node_modules/tar-fs/index.js"(exports) {
|
|
2815
|
+
var tar = require_tar_stream();
|
|
2816
|
+
var pump = require_pump();
|
|
2817
|
+
var fs = __require("fs");
|
|
2818
|
+
var path = __require("path");
|
|
2819
|
+
var win32 = (global.Bare ? global.Bare.platform : process.platform) === "win32";
|
|
2820
|
+
exports.pack = function pack(cwd, opts) {
|
|
2821
|
+
if (!cwd) cwd = ".";
|
|
2822
|
+
if (!opts) opts = {};
|
|
2823
|
+
const xfs = opts.fs || fs;
|
|
2824
|
+
const ignore = opts.ignore || opts.filter || noop;
|
|
2825
|
+
const mapStream = opts.mapStream || echo;
|
|
2826
|
+
const statNext = statAll(xfs, opts.dereference ? xfs.stat : xfs.lstat, cwd, ignore, opts.entries, opts.sort);
|
|
2827
|
+
const strict = opts.strict !== false;
|
|
2828
|
+
const umask = typeof opts.umask === "number" ? ~opts.umask : ~processUmask();
|
|
2829
|
+
const pack2 = opts.pack || tar.pack();
|
|
2830
|
+
const finish = opts.finish || noop;
|
|
2831
|
+
let map = opts.map || noop;
|
|
2832
|
+
let dmode = typeof opts.dmode === "number" ? opts.dmode : 0;
|
|
2833
|
+
let fmode = typeof opts.fmode === "number" ? opts.fmode : 0;
|
|
2834
|
+
if (opts.strip) map = strip(map, opts.strip);
|
|
2835
|
+
if (opts.readable) {
|
|
2836
|
+
dmode |= parseInt(555, 8);
|
|
2837
|
+
fmode |= parseInt(444, 8);
|
|
29
2838
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
2839
|
+
if (opts.writable) {
|
|
2840
|
+
dmode |= parseInt(333, 8);
|
|
2841
|
+
fmode |= parseInt(222, 8);
|
|
2842
|
+
}
|
|
2843
|
+
onnextentry();
|
|
2844
|
+
function onsymlink(filename, header) {
|
|
2845
|
+
xfs.readlink(path.join(cwd, filename), function(err, linkname) {
|
|
2846
|
+
if (err) return pack2.destroy(err);
|
|
2847
|
+
header.linkname = normalize(linkname);
|
|
2848
|
+
pack2.entry(header, onnextentry);
|
|
2849
|
+
});
|
|
2850
|
+
}
|
|
2851
|
+
function onstat(err, filename, stat) {
|
|
2852
|
+
if (pack2.destroyed) return;
|
|
2853
|
+
if (err) return pack2.destroy(err);
|
|
2854
|
+
if (!filename) {
|
|
2855
|
+
if (opts.finalize !== false) pack2.finalize();
|
|
2856
|
+
return finish(pack2);
|
|
2857
|
+
}
|
|
2858
|
+
if (stat.isSocket()) return onnextentry();
|
|
2859
|
+
let header = {
|
|
2860
|
+
name: normalize(filename),
|
|
2861
|
+
mode: (stat.mode | (stat.isDirectory() ? dmode : fmode)) & umask,
|
|
2862
|
+
mtime: stat.mtime,
|
|
2863
|
+
size: stat.size,
|
|
2864
|
+
type: "file",
|
|
2865
|
+
uid: stat.uid,
|
|
2866
|
+
gid: stat.gid
|
|
2867
|
+
};
|
|
2868
|
+
if (stat.isDirectory()) {
|
|
2869
|
+
header.size = 0;
|
|
2870
|
+
header.type = "directory";
|
|
2871
|
+
header = map(header) || header;
|
|
2872
|
+
return pack2.entry(header, onnextentry);
|
|
2873
|
+
}
|
|
2874
|
+
if (stat.isSymbolicLink()) {
|
|
2875
|
+
header.size = 0;
|
|
2876
|
+
header.type = "symlink";
|
|
2877
|
+
header = map(header) || header;
|
|
2878
|
+
return onsymlink(filename, header);
|
|
2879
|
+
}
|
|
2880
|
+
header = map(header) || header;
|
|
2881
|
+
if (!stat.isFile()) {
|
|
2882
|
+
if (strict) return pack2.destroy(new Error("unsupported type for " + filename));
|
|
2883
|
+
return onnextentry();
|
|
2884
|
+
}
|
|
2885
|
+
const entry = pack2.entry(header, onnextentry);
|
|
2886
|
+
const rs = mapStream(xfs.createReadStream(path.join(cwd, filename), { start: 0, end: header.size > 0 ? header.size - 1 : header.size }), header);
|
|
2887
|
+
rs.on("error", function(err2) {
|
|
2888
|
+
entry.destroy(err2);
|
|
2889
|
+
});
|
|
2890
|
+
pump(rs, entry);
|
|
2891
|
+
}
|
|
2892
|
+
function onnextentry(err) {
|
|
2893
|
+
if (err) return pack2.destroy(err);
|
|
2894
|
+
statNext(onstat);
|
|
2895
|
+
}
|
|
2896
|
+
return pack2;
|
|
2897
|
+
};
|
|
2898
|
+
function head(list) {
|
|
2899
|
+
return list.length ? list[list.length - 1] : null;
|
|
2900
|
+
}
|
|
2901
|
+
function processGetuid() {
|
|
2902
|
+
return !global.Bare && process.getuid ? process.getuid() : -1;
|
|
2903
|
+
}
|
|
2904
|
+
function processUmask() {
|
|
2905
|
+
return !global.Bare && process.umask ? process.umask() : 0;
|
|
2906
|
+
}
|
|
2907
|
+
exports.extract = function extract3(cwd, opts) {
|
|
2908
|
+
if (!cwd) cwd = ".";
|
|
2909
|
+
if (!opts) opts = {};
|
|
2910
|
+
cwd = path.resolve(cwd);
|
|
2911
|
+
const xfs = opts.fs || fs;
|
|
2912
|
+
const ignore = opts.ignore || opts.filter || noop;
|
|
2913
|
+
const mapStream = opts.mapStream || echo;
|
|
2914
|
+
const own = opts.chown !== false && !win32 && processGetuid() === 0;
|
|
2915
|
+
const extract4 = opts.extract || tar.extract();
|
|
2916
|
+
const stack = [];
|
|
2917
|
+
const now = /* @__PURE__ */ new Date();
|
|
2918
|
+
const umask = typeof opts.umask === "number" ? ~opts.umask : ~processUmask();
|
|
2919
|
+
const strict = opts.strict !== false;
|
|
2920
|
+
const validateSymLinks = opts.validateSymlinks !== false;
|
|
2921
|
+
let map = opts.map || noop;
|
|
2922
|
+
let dmode = typeof opts.dmode === "number" ? opts.dmode : 0;
|
|
2923
|
+
let fmode = typeof opts.fmode === "number" ? opts.fmode : 0;
|
|
2924
|
+
if (opts.strip) map = strip(map, opts.strip);
|
|
2925
|
+
if (opts.readable) {
|
|
2926
|
+
dmode |= parseInt(555, 8);
|
|
2927
|
+
fmode |= parseInt(444, 8);
|
|
2928
|
+
}
|
|
2929
|
+
if (opts.writable) {
|
|
2930
|
+
dmode |= parseInt(333, 8);
|
|
2931
|
+
fmode |= parseInt(222, 8);
|
|
2932
|
+
}
|
|
2933
|
+
extract4.on("entry", onentry);
|
|
2934
|
+
if (opts.finish) extract4.on("finish", opts.finish);
|
|
2935
|
+
return extract4;
|
|
2936
|
+
function onentry(header, stream, next) {
|
|
2937
|
+
header = map(header) || header;
|
|
2938
|
+
header.name = normalize(header.name);
|
|
2939
|
+
const name = path.join(cwd, path.join("/", header.name));
|
|
2940
|
+
if (ignore(name, header)) {
|
|
2941
|
+
stream.resume();
|
|
2942
|
+
return next();
|
|
2943
|
+
}
|
|
2944
|
+
const dir = path.join(name, ".") === path.join(cwd, ".") ? cwd : path.dirname(name);
|
|
2945
|
+
validate(xfs, dir, path.join(cwd, "."), function(err, valid) {
|
|
2946
|
+
if (err) return next(err);
|
|
2947
|
+
if (!valid) return next(new Error(dir + " is not a valid path"));
|
|
2948
|
+
if (header.type === "directory") {
|
|
2949
|
+
stack.push([name, header.mtime]);
|
|
2950
|
+
return mkdirfix(name, {
|
|
2951
|
+
uid: header.uid,
|
|
2952
|
+
gid: header.gid,
|
|
2953
|
+
mode: header.mode
|
|
2954
|
+
}, stat);
|
|
2955
|
+
}
|
|
2956
|
+
mkdirfix(dir, {
|
|
2957
|
+
uid: header.uid,
|
|
2958
|
+
gid: header.gid,
|
|
2959
|
+
// normally, the folders with rights and owner should be part of the TAR file
|
|
2960
|
+
// if this is not the case, create folder for same user as file and with
|
|
2961
|
+
// standard permissions of 0o755 (rwxr-xr-x)
|
|
2962
|
+
mode: 493
|
|
2963
|
+
}, function(err2) {
|
|
2964
|
+
if (err2) return next(err2);
|
|
2965
|
+
switch (header.type) {
|
|
2966
|
+
case "file":
|
|
2967
|
+
return onfile();
|
|
2968
|
+
case "link":
|
|
2969
|
+
return onlink();
|
|
2970
|
+
case "symlink":
|
|
2971
|
+
return onsymlink();
|
|
2972
|
+
}
|
|
2973
|
+
if (strict) return next(new Error("unsupported type for " + name + " (" + header.type + ")"));
|
|
2974
|
+
stream.resume();
|
|
2975
|
+
next();
|
|
2976
|
+
});
|
|
2977
|
+
});
|
|
2978
|
+
function stat(err) {
|
|
2979
|
+
if (err) return next(err);
|
|
2980
|
+
if (path.join(name, ".") === path.join(cwd, ".")) return next();
|
|
2981
|
+
utimes(name, header, function(err2) {
|
|
2982
|
+
if (err2) return next(err2);
|
|
2983
|
+
if (win32) return next();
|
|
2984
|
+
chperm(name, header, next);
|
|
2985
|
+
});
|
|
2986
|
+
}
|
|
2987
|
+
function onsymlink() {
|
|
2988
|
+
if (win32) return next();
|
|
2989
|
+
xfs.unlink(name, function() {
|
|
2990
|
+
const dst = path.resolve(path.dirname(name), header.linkname);
|
|
2991
|
+
if (!inCwd(dst) && (validateSymLinks || opts.strip)) return next(new Error(name + " is not a valid symlink"));
|
|
2992
|
+
validateNotSymlink(xfs, dst, path.join(cwd, "."), function(err, valid) {
|
|
2993
|
+
if (err) return next(err);
|
|
2994
|
+
if (!valid && validateSymLinks) return next(new Error(name + " is not a valid symlink"));
|
|
2995
|
+
xfs.symlink(header.linkname, name, stat);
|
|
2996
|
+
});
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2999
|
+
function onlink() {
|
|
3000
|
+
if (win32) return next();
|
|
3001
|
+
xfs.unlink(name, function() {
|
|
3002
|
+
const link = path.join(cwd, path.join("/", header.linkname));
|
|
3003
|
+
xfs.realpath(link, function(err, dst) {
|
|
3004
|
+
if (err || !inCwd(dst)) return next(new Error(name + " is not a valid hardlink"));
|
|
3005
|
+
xfs.link(dst, name, function(err2) {
|
|
3006
|
+
if (err2 && err2.code === "EPERM" && opts.hardlinkAsFilesFallback) {
|
|
3007
|
+
stream = xfs.createReadStream(dst);
|
|
3008
|
+
return onfile();
|
|
3009
|
+
}
|
|
3010
|
+
stat(err2);
|
|
3011
|
+
});
|
|
3012
|
+
});
|
|
3013
|
+
});
|
|
3014
|
+
}
|
|
3015
|
+
function inCwd(dst) {
|
|
3016
|
+
return dst === cwd || dst.startsWith(cwd + path.sep);
|
|
3017
|
+
}
|
|
3018
|
+
function onfile() {
|
|
3019
|
+
xfs.lstat(name, function(err, st) {
|
|
3020
|
+
if (!err && st.isSymbolicLink()) return xfs.unlink(name, onwrite);
|
|
3021
|
+
onwrite();
|
|
3022
|
+
});
|
|
3023
|
+
function onwrite(err) {
|
|
3024
|
+
if (err) return next(err);
|
|
3025
|
+
const ws = xfs.createWriteStream(name);
|
|
3026
|
+
const rs = mapStream(stream, header);
|
|
3027
|
+
ws.on("error", function(err2) {
|
|
3028
|
+
rs.destroy(err2);
|
|
3029
|
+
});
|
|
3030
|
+
pump(rs, ws, function(err2) {
|
|
3031
|
+
if (err2) return next(err2);
|
|
3032
|
+
ws.on("close", stat);
|
|
3033
|
+
});
|
|
3034
|
+
}
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
function utimesParent(name, cb) {
|
|
3038
|
+
let top;
|
|
3039
|
+
while ((top = head(stack)) && name.slice(0, top[0].length) !== top[0]) stack.pop();
|
|
3040
|
+
if (!top) return cb();
|
|
3041
|
+
xfs.utimes(top[0], now, top[1], cb);
|
|
3042
|
+
}
|
|
3043
|
+
function utimes(name, header, cb) {
|
|
3044
|
+
if (opts.utimes === false) return cb();
|
|
3045
|
+
if (header.type === "directory") return xfs.utimes(name, now, header.mtime, cb);
|
|
3046
|
+
if (header.type === "symlink") return utimesParent(name, cb);
|
|
3047
|
+
xfs.utimes(name, now, header.mtime, function(err) {
|
|
3048
|
+
if (err) return cb(err);
|
|
3049
|
+
utimesParent(name, cb);
|
|
3050
|
+
});
|
|
3051
|
+
}
|
|
3052
|
+
function chperm(name, header, cb) {
|
|
3053
|
+
const link = header.type === "symlink";
|
|
3054
|
+
const chmod = link ? xfs.lchmod : xfs.chmod;
|
|
3055
|
+
const chown = link ? xfs.lchown : xfs.chown;
|
|
3056
|
+
if (!chmod) return cb();
|
|
3057
|
+
const mode = (header.mode | (header.type === "directory" ? dmode : fmode)) & umask & 511;
|
|
3058
|
+
if (chown && own) chown.call(xfs, name, header.uid, header.gid, onchown);
|
|
3059
|
+
else onchown(null);
|
|
3060
|
+
function onchown(err) {
|
|
3061
|
+
if (err) return cb(err);
|
|
3062
|
+
if (!chmod) return cb();
|
|
3063
|
+
chmod.call(xfs, name, mode, cb);
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
function mkdirfix(name, opts2, cb) {
|
|
3067
|
+
xfs.stat(name, function(err) {
|
|
3068
|
+
if (!err) return cb(null);
|
|
3069
|
+
if (err.code !== "ENOENT") return cb(err);
|
|
3070
|
+
xfs.mkdir(name, { mode: opts2.mode, recursive: true }, function(err2, made) {
|
|
3071
|
+
if (err2) return cb(err2);
|
|
3072
|
+
chperm(name, opts2, cb);
|
|
3073
|
+
});
|
|
3074
|
+
});
|
|
35
3075
|
}
|
|
36
3076
|
};
|
|
3077
|
+
function validateNotSymlink(fs2, name, root, cb) {
|
|
3078
|
+
if (name === root) return cb(null, true);
|
|
3079
|
+
if (!name.startsWith(root + path.sep)) return cb(null, false);
|
|
3080
|
+
fs2.lstat(name, function(err, st) {
|
|
3081
|
+
if (err && err.code !== "ENOENT" && err.code !== "EPERM") return cb(err);
|
|
3082
|
+
if (err || !st.isSymbolicLink()) return validateNotSymlink(fs2, path.join(name, ".."), root, cb);
|
|
3083
|
+
cb(null, false);
|
|
3084
|
+
});
|
|
3085
|
+
}
|
|
3086
|
+
function validate(fs2, name, root, cb) {
|
|
3087
|
+
if (name === root) return cb(null, true);
|
|
3088
|
+
fs2.lstat(name, function(err, st) {
|
|
3089
|
+
if (err && err.code !== "ENOENT" && err.code !== "EPERM") return cb(err);
|
|
3090
|
+
if (err || st.isDirectory()) return validate(fs2, path.join(name, ".."), root, cb);
|
|
3091
|
+
cb(null, false);
|
|
3092
|
+
});
|
|
3093
|
+
}
|
|
3094
|
+
function inside(root, name) {
|
|
3095
|
+
return name === root || name.startsWith(root + path.sep);
|
|
3096
|
+
}
|
|
3097
|
+
function noop() {
|
|
3098
|
+
}
|
|
3099
|
+
function echo(name) {
|
|
3100
|
+
return name;
|
|
3101
|
+
}
|
|
3102
|
+
function normalize(name) {
|
|
3103
|
+
return win32 ? name.replace(/\\/g, "/").replace(/[:?<>|]/g, "_") : name;
|
|
3104
|
+
}
|
|
3105
|
+
function statAll(fs2, stat, cwd, ignore, entries, sort) {
|
|
3106
|
+
if (!entries) entries = ["."];
|
|
3107
|
+
const queue = entries.slice(0);
|
|
3108
|
+
const root = path.resolve(cwd);
|
|
3109
|
+
return function loop(callback) {
|
|
3110
|
+
if (!queue.length) return callback(null);
|
|
3111
|
+
const next = queue.shift();
|
|
3112
|
+
const nextAbs = path.join(cwd, next);
|
|
3113
|
+
if (!inside(root, path.resolve(cwd, next))) return callback(new Error(next + " is not a valid path"));
|
|
3114
|
+
stat.call(fs2, nextAbs, function(err, stat2) {
|
|
3115
|
+
if (err) return callback(entries.indexOf(next) === -1 && err.code === "ENOENT" ? null : err);
|
|
3116
|
+
if (!stat2.isDirectory()) return callback(null, next, stat2);
|
|
3117
|
+
fs2.readdir(nextAbs, function(err2, files) {
|
|
3118
|
+
if (err2) return callback(err2);
|
|
3119
|
+
if (sort) files.sort();
|
|
3120
|
+
for (let i = 0; i < files.length; i++) {
|
|
3121
|
+
if (!ignore(path.join(cwd, next, files[i]))) queue.push(path.join(next, files[i]));
|
|
3122
|
+
}
|
|
3123
|
+
callback(null, next, stat2);
|
|
3124
|
+
});
|
|
3125
|
+
});
|
|
3126
|
+
};
|
|
3127
|
+
}
|
|
3128
|
+
function strip(map, level) {
|
|
3129
|
+
return function(header) {
|
|
3130
|
+
header.name = header.name.split("/").slice(level).join("/");
|
|
3131
|
+
const linkname = header.linkname;
|
|
3132
|
+
if (linkname && (header.type === "link" || path.isAbsolute(linkname))) {
|
|
3133
|
+
header.linkname = linkname.split("/").slice(level).join("/");
|
|
3134
|
+
}
|
|
3135
|
+
return map(header);
|
|
3136
|
+
};
|
|
3137
|
+
}
|
|
37
3138
|
}
|
|
38
3139
|
});
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
3140
|
+
var import_tar_fs, setupLambdaEnvironment, isValidUrl, isRunningInAmazonLinux2023, downloadAndExtract;
|
|
3141
|
+
var init_helper = __esm({
|
|
3142
|
+
"../../node_modules/@sparticuz/chromium/build/helper.js"() {
|
|
3143
|
+
import_tar_fs = __toESM(require_tar_fs());
|
|
3144
|
+
setupLambdaEnvironment = (baseLibPath) => {
|
|
3145
|
+
process.env["FONTCONFIG_PATH"] ??= join(tmpdir(), "fonts");
|
|
3146
|
+
process.env["HOME"] ??= tmpdir();
|
|
3147
|
+
if (process.env["LD_LIBRARY_PATH"] === void 0) {
|
|
3148
|
+
process.env["LD_LIBRARY_PATH"] = baseLibPath;
|
|
3149
|
+
} else if (!process.env["LD_LIBRARY_PATH"].startsWith(baseLibPath)) {
|
|
3150
|
+
process.env["LD_LIBRARY_PATH"] = [
|
|
3151
|
+
baseLibPath,
|
|
3152
|
+
...new Set(process.env["LD_LIBRARY_PATH"].split(":"))
|
|
3153
|
+
].join(":");
|
|
3154
|
+
}
|
|
3155
|
+
};
|
|
3156
|
+
isValidUrl = (input) => {
|
|
3157
|
+
try {
|
|
3158
|
+
const url = new URL(input);
|
|
3159
|
+
if (url.protocol === "https:")
|
|
3160
|
+
return true;
|
|
3161
|
+
if (url.protocol === "http:" && (url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "[::1]")) {
|
|
3162
|
+
return true;
|
|
3163
|
+
}
|
|
3164
|
+
return false;
|
|
3165
|
+
} catch {
|
|
3166
|
+
return false;
|
|
3167
|
+
}
|
|
3168
|
+
};
|
|
3169
|
+
isRunningInAmazonLinux2023 = (nodeMajorVersion2) => {
|
|
3170
|
+
const awsExecEnv = process.env["AWS_EXECUTION_ENV"] ?? "";
|
|
3171
|
+
const awsLambdaJsRuntime = process.env["AWS_LAMBDA_JS_RUNTIME"] ?? "";
|
|
3172
|
+
const codebuildImage = process.env["CODEBUILD_BUILD_IMAGE"] ?? "";
|
|
3173
|
+
if (awsExecEnv.includes("20.x") || awsExecEnv.includes("22.x") || awsExecEnv.includes("24.x") || awsLambdaJsRuntime.includes("20.x") || awsLambdaJsRuntime.includes("22.x") || awsLambdaJsRuntime.includes("24.x") || codebuildImage.includes("nodejs20") || codebuildImage.includes("nodejs22") || codebuildImage.includes("nodejs24")) {
|
|
3174
|
+
return true;
|
|
3175
|
+
}
|
|
3176
|
+
if (process.env["VERCEL"] && nodeMajorVersion2 >= 20) {
|
|
3177
|
+
return true;
|
|
3178
|
+
}
|
|
3179
|
+
return false;
|
|
3180
|
+
};
|
|
3181
|
+
downloadAndExtract = async (url) => {
|
|
3182
|
+
const destDir = join(tmpdir(), "chromium-pack");
|
|
3183
|
+
const response = await fetch(url, {
|
|
3184
|
+
redirect: "follow",
|
|
3185
|
+
signal: AbortSignal.timeout(3e5)
|
|
3186
|
+
});
|
|
3187
|
+
if (!response.ok) {
|
|
3188
|
+
throw new Error(`Unexpected status code: ${String(response.status)}.`);
|
|
3189
|
+
}
|
|
3190
|
+
if (!response.body) {
|
|
3191
|
+
throw new Error("Response body is empty.");
|
|
3192
|
+
}
|
|
3193
|
+
try {
|
|
3194
|
+
await pipeline(Readable.fromWeb(response.body), (0, import_tar_fs.extract)(destDir));
|
|
3195
|
+
} catch (error) {
|
|
3196
|
+
await new Promise((resolve3) => {
|
|
3197
|
+
rm(destDir, { force: true, recursive: true }, () => {
|
|
3198
|
+
resolve3();
|
|
3199
|
+
});
|
|
3200
|
+
});
|
|
3201
|
+
throw error;
|
|
3202
|
+
}
|
|
3203
|
+
return destDir;
|
|
3204
|
+
};
|
|
3205
|
+
}
|
|
44
3206
|
});
|
|
45
|
-
var
|
|
46
|
-
var
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
3207
|
+
var import_tar_fs2, ARCHIVE_EXTENSION_REGEX, TAR_EXTENSION_REGEX, BROTLI_EXTENSION_REGEX, GZIP_EXTENSION_REGEX, inflate;
|
|
3208
|
+
var init_lambdafs = __esm({
|
|
3209
|
+
"../../node_modules/@sparticuz/chromium/build/lambdafs.js"() {
|
|
3210
|
+
import_tar_fs2 = __toESM(require_tar_fs());
|
|
3211
|
+
ARCHIVE_EXTENSION_REGEX = /\.(?:t(?:ar(?:\.(?:br|gz))?|br|gz)|br|gz)$/i;
|
|
3212
|
+
TAR_EXTENSION_REGEX = /\.t(?:ar(?:\.(?:br|gz))?|br|gz)$/i;
|
|
3213
|
+
BROTLI_EXTENSION_REGEX = /br$/i;
|
|
3214
|
+
GZIP_EXTENSION_REGEX = /gz$/i;
|
|
3215
|
+
inflate = (filePath) => {
|
|
3216
|
+
const output = filePath.includes("swiftshader") ? tmpdir() : join(tmpdir(), basename(filePath).replace(ARCHIVE_EXTENSION_REGEX, ""));
|
|
3217
|
+
return new Promise((resolve3, reject) => {
|
|
3218
|
+
if (filePath.includes("swiftshader")) {
|
|
3219
|
+
if (existsSync(`${output}/libGLESv2.so`)) {
|
|
3220
|
+
resolve3(output);
|
|
3221
|
+
return;
|
|
3222
|
+
}
|
|
3223
|
+
} else if (existsSync(output)) {
|
|
3224
|
+
resolve3(output);
|
|
3225
|
+
return;
|
|
3226
|
+
}
|
|
3227
|
+
const isBrotli = BROTLI_EXTENSION_REGEX.test(filePath);
|
|
3228
|
+
const isGzip = GZIP_EXTENSION_REGEX.test(filePath);
|
|
3229
|
+
const isTar = TAR_EXTENSION_REGEX.test(filePath);
|
|
3230
|
+
const highWaterMark = 2 ** 22;
|
|
3231
|
+
const source = createReadStream(filePath, { highWaterMark });
|
|
3232
|
+
let target;
|
|
3233
|
+
const handleError = (error) => {
|
|
3234
|
+
reject(error);
|
|
59
3235
|
};
|
|
3236
|
+
source.once("error", handleError);
|
|
3237
|
+
if (isTar) {
|
|
3238
|
+
target = (0, import_tar_fs2.extract)(output);
|
|
3239
|
+
target.once("finish", () => {
|
|
3240
|
+
resolve3(output);
|
|
3241
|
+
});
|
|
3242
|
+
} else {
|
|
3243
|
+
target = createWriteStream(output, { mode: 448 });
|
|
3244
|
+
target.once("close", () => {
|
|
3245
|
+
resolve3(output);
|
|
3246
|
+
});
|
|
3247
|
+
}
|
|
3248
|
+
target.once("error", handleError);
|
|
3249
|
+
if (isBrotli || isGzip) {
|
|
3250
|
+
const decompressor = isBrotli ? createBrotliDecompress({ chunkSize: 2 ** 21 }) : createUnzip({ chunkSize: 2 ** 21 });
|
|
3251
|
+
decompressor.once("error", handleError);
|
|
3252
|
+
source.pipe(decompressor).pipe(target);
|
|
3253
|
+
} else {
|
|
3254
|
+
source.pipe(target);
|
|
3255
|
+
}
|
|
3256
|
+
});
|
|
3257
|
+
};
|
|
3258
|
+
}
|
|
3259
|
+
});
|
|
3260
|
+
function getBinPath() {
|
|
3261
|
+
return join(dirname(fileURLToPath(import.meta.url)), "..", "bin");
|
|
3262
|
+
}
|
|
3263
|
+
var init_paths = __esm({
|
|
3264
|
+
"../../node_modules/@sparticuz/chromium/build/paths.js"() {
|
|
3265
|
+
}
|
|
3266
|
+
});
|
|
3267
|
+
|
|
3268
|
+
// ../../node_modules/@sparticuz/chromium/build/index.js
|
|
3269
|
+
var build_exports = {};
|
|
3270
|
+
__export(build_exports, {
|
|
3271
|
+
default: () => build_default,
|
|
3272
|
+
inflate: () => inflate,
|
|
3273
|
+
setupLambdaEnvironment: () => setupLambdaEnvironment
|
|
3274
|
+
});
|
|
3275
|
+
var nodeMajorVersion, Chromium, build_default;
|
|
3276
|
+
var init_build = __esm({
|
|
3277
|
+
"../../node_modules/@sparticuz/chromium/build/index.js"() {
|
|
3278
|
+
init_helper();
|
|
3279
|
+
init_lambdafs();
|
|
3280
|
+
init_paths();
|
|
3281
|
+
init_helper();
|
|
3282
|
+
init_lambdafs();
|
|
3283
|
+
nodeMajorVersion = Number.parseInt(process.versions.node.split(".")[0] ?? "");
|
|
3284
|
+
if (isRunningInAmazonLinux2023(nodeMajorVersion)) {
|
|
3285
|
+
setupLambdaEnvironment(join(tmpdir(), "al2023", "lib"));
|
|
3286
|
+
}
|
|
3287
|
+
Chromium = class {
|
|
3288
|
+
/**
|
|
3289
|
+
* Returns a list of additional Chromium flags recommended for serverless environments.
|
|
3290
|
+
* The canonical list of flags can be found on https://peter.sh/experiments/chromium-command-line-switches/.
|
|
3291
|
+
* Most of below can be found here: https://github.com/GoogleChrome/chrome-launcher/blob/main/docs/chrome-flags-for-tools.md
|
|
3292
|
+
*/
|
|
3293
|
+
static get args() {
|
|
3294
|
+
const chromiumFlags = [
|
|
3295
|
+
"--ash-no-nudges",
|
|
3296
|
+
// Avoids blue bubble "user education" nudges (eg., "… give your browser a new look", Memory Saver)
|
|
3297
|
+
"--disable-domain-reliability",
|
|
3298
|
+
// Disables Domain Reliability Monitoring, which tracks whether the browser has difficulty contacting Google-owned sites and uploads reports to Google.
|
|
3299
|
+
"--disable-print-preview",
|
|
3300
|
+
// https://source.chromium.org/search?q=lang:cpp+symbol:kDisablePrintPreview&ss=chromium
|
|
3301
|
+
"--disk-cache-size=33554432",
|
|
3302
|
+
// https://source.chromium.org/search?q=lang:cpp+symbol:kDiskCacheSize&ss=chromium Forces the maximum disk space to be used by the disk cache, in bytes.
|
|
3303
|
+
"--no-default-browser-check",
|
|
3304
|
+
// Disable the default browser check, do not prompt to set it as such. (This is already set by Playwright, but not Puppeteer)
|
|
3305
|
+
"--no-pings",
|
|
3306
|
+
// Don't send hyperlink auditing pings
|
|
3307
|
+
"--single-process",
|
|
3308
|
+
// Runs the renderer and plugins in the same process as the browser. NOTES: Needs to be single-process to avoid `prctl(PR_SET_NO_NEW_PRIVS) failed` error
|
|
3309
|
+
"--font-render-hinting=none"
|
|
3310
|
+
// https://github.com/puppeteer/puppeteer/issues/2410#issuecomment-560573612
|
|
3311
|
+
];
|
|
3312
|
+
const chromiumDisableFeatures = [
|
|
3313
|
+
"AudioServiceOutOfProcess",
|
|
3314
|
+
"IsolateOrigins",
|
|
3315
|
+
"site-per-process"
|
|
3316
|
+
// Disables OOPIF. https://www.chromium.org/Home/chromium-security/site-isolation
|
|
3317
|
+
];
|
|
3318
|
+
const chromiumEnableFeatures = ["SharedArrayBuffer"];
|
|
3319
|
+
const graphicsFlags = [
|
|
3320
|
+
"--ignore-gpu-blocklist",
|
|
3321
|
+
// https://source.chromium.org/search?q=lang:cpp+symbol:kIgnoreGpuBlocklist&ss=chromium
|
|
3322
|
+
"--in-process-gpu"
|
|
3323
|
+
// Saves some memory by moving GPU process into a browser process thread
|
|
3324
|
+
];
|
|
3325
|
+
if (this.graphics) {
|
|
3326
|
+
graphicsFlags.push(
|
|
3327
|
+
// As the unsafe WebGL fallback, SwANGLE (ANGLE + SwiftShader Vulkan)
|
|
3328
|
+
"--use-gl=angle",
|
|
3329
|
+
"--use-angle=swiftshader",
|
|
3330
|
+
"--enable-unsafe-swiftshader"
|
|
3331
|
+
);
|
|
3332
|
+
} else {
|
|
3333
|
+
graphicsFlags.push("--disable-webgl");
|
|
3334
|
+
}
|
|
3335
|
+
const insecureFlags = [
|
|
3336
|
+
"--allow-running-insecure-content",
|
|
3337
|
+
// https://source.chromium.org/search?q=lang:cpp+symbol:kAllowRunningInsecureContent&ss=chromium
|
|
3338
|
+
"--disable-setuid-sandbox",
|
|
3339
|
+
// Lambda runs as root, so this is required to allow Chromium to run as root
|
|
3340
|
+
"--disable-site-isolation-trials",
|
|
3341
|
+
// https://source.chromium.org/search?q=lang:cpp+symbol:kDisableSiteIsolation&ss=chromium
|
|
3342
|
+
"--disable-web-security"
|
|
3343
|
+
// https://source.chromium.org/search?q=lang:cpp+symbol:kDisableWebSecurity&ss=chromium
|
|
3344
|
+
];
|
|
3345
|
+
const headlessFlags = [
|
|
3346
|
+
"--headless='shell'",
|
|
3347
|
+
// We only support running chrome-headless-shell
|
|
3348
|
+
"--no-sandbox",
|
|
3349
|
+
// https://source.chromium.org/search?q=lang:cpp+symbol:kNoSandbox&ss=chromium
|
|
3350
|
+
"--no-zygote"
|
|
3351
|
+
// https://source.chromium.org/search?q=lang:cpp+symbol:kNoZygote&ss=chromium
|
|
3352
|
+
];
|
|
3353
|
+
return [
|
|
3354
|
+
...chromiumFlags,
|
|
3355
|
+
`--disable-features=${[...chromiumDisableFeatures].join(",")}`,
|
|
3356
|
+
`--enable-features=${[...chromiumEnableFeatures].join(",")}`,
|
|
3357
|
+
...graphicsFlags,
|
|
3358
|
+
...insecureFlags,
|
|
3359
|
+
...headlessFlags
|
|
3360
|
+
];
|
|
60
3361
|
}
|
|
61
|
-
config;
|
|
62
|
-
baseUrl;
|
|
63
|
-
headers;
|
|
64
3362
|
/**
|
|
65
|
-
*
|
|
3363
|
+
* Returns whether the graphics stack is enabled or disabled
|
|
3364
|
+
* @returns boolean
|
|
66
3365
|
*/
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
3366
|
+
static get graphics() {
|
|
3367
|
+
return this.graphicsMode;
|
|
3368
|
+
}
|
|
3369
|
+
/**
|
|
3370
|
+
* Sets whether the graphics stack is enabled or disabled.
|
|
3371
|
+
* @param true means the stack is enabled. WebGL will work.
|
|
3372
|
+
* @param false means that the stack is disabled. WebGL will not work.
|
|
3373
|
+
* @default true
|
|
3374
|
+
*/
|
|
3375
|
+
static set setGraphicsMode(value) {
|
|
3376
|
+
if (typeof value !== "boolean") {
|
|
3377
|
+
throw new TypeError(`Graphics mode must be a boolean, you entered '${String(value)}'`);
|
|
78
3378
|
}
|
|
79
|
-
|
|
3379
|
+
this.graphicsMode = value;
|
|
80
3380
|
}
|
|
81
3381
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
3382
|
+
* If true, the graphics stack and webgl is enabled,
|
|
3383
|
+
* If false, webgl will be disabled.
|
|
3384
|
+
* (If false, the swiftshader.tar.br file will also not extract)
|
|
84
3385
|
*/
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
|
|
94
|
-
const message = errorBody.error?.message ?? response.statusText;
|
|
95
|
-
throw new OpenRouterError(message, response.status, void 0, response.headers);
|
|
3386
|
+
static graphicsMode = true;
|
|
3387
|
+
/**
|
|
3388
|
+
* Inflates the included version of Chromium
|
|
3389
|
+
* @param input The location of the `bin` folder
|
|
3390
|
+
* @returns The path to the `chromium` binary
|
|
3391
|
+
*/
|
|
3392
|
+
static async executablePath(input) {
|
|
3393
|
+
if (existsSync(join(tmpdir(), "chromium"))) {
|
|
3394
|
+
return join(tmpdir(), "chromium");
|
|
96
3395
|
}
|
|
97
|
-
if (
|
|
98
|
-
|
|
3396
|
+
if (input && isValidUrl(input)) {
|
|
3397
|
+
return this.executablePath(await downloadAndExtract(input));
|
|
99
3398
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
try {
|
|
104
|
-
while (true) {
|
|
105
|
-
const { done, value } = await reader.read();
|
|
106
|
-
if (done) break;
|
|
107
|
-
buffer += decoder.decode(value, { stream: true });
|
|
108
|
-
const lines = buffer.split("\n");
|
|
109
|
-
buffer = lines.pop() ?? "";
|
|
110
|
-
for (const line of lines) {
|
|
111
|
-
const trimmed = line.trim();
|
|
112
|
-
if (!trimmed || trimmed.startsWith(":")) continue;
|
|
113
|
-
if (trimmed === "data: [DONE]") return;
|
|
114
|
-
if (!trimmed.startsWith("data: ")) continue;
|
|
115
|
-
const json = trimmed.slice("data: ".length);
|
|
116
|
-
try {
|
|
117
|
-
yield JSON.parse(json);
|
|
118
|
-
} catch {
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
} finally {
|
|
123
|
-
reader.releaseLock();
|
|
3399
|
+
input ??= getBinPath();
|
|
3400
|
+
if (!existsSync(input)) {
|
|
3401
|
+
throw new Error(`The input directory "${input}" does not exist. If you are using a bundler (esbuild, webpack, etc.), you must externalize @sparticuz/chromium so it is not relocated. See: https://github.com/Sparticuz/chromium#bundler-configuration`);
|
|
124
3402
|
}
|
|
3403
|
+
const promises = [
|
|
3404
|
+
inflate(join(input, "chromium.br")),
|
|
3405
|
+
inflate(join(input, "fonts.tar.br")),
|
|
3406
|
+
inflate(join(input, "swiftshader.tar.br"))
|
|
3407
|
+
];
|
|
3408
|
+
if (isRunningInAmazonLinux2023(nodeMajorVersion)) {
|
|
3409
|
+
promises.push(inflate(join(input, "al2023.tar.br")));
|
|
3410
|
+
}
|
|
3411
|
+
const result = await Promise.all(promises);
|
|
3412
|
+
return result.shift();
|
|
125
3413
|
}
|
|
126
3414
|
};
|
|
3415
|
+
build_default = Chromium;
|
|
127
3416
|
}
|
|
128
3417
|
});
|
|
129
3418
|
|
|
@@ -354,20 +3643,51 @@ Intentional custom colors (status indicators) are acceptable when no semantic to
|
|
|
354
3643
|
Only list ACTUAL violations. Use 'fail' only for pervasive violations.`
|
|
355
3644
|
}
|
|
356
3645
|
];
|
|
357
|
-
|
|
358
|
-
|
|
3646
|
+
var FREE_DESIGN_CRITERIA_OVERRIDES = [
|
|
3647
|
+
{
|
|
3648
|
+
id: "tokens",
|
|
3649
|
+
name: "Color tokens",
|
|
3650
|
+
priority: "P1",
|
|
3651
|
+
tier: 0,
|
|
3652
|
+
failOutcome: "warn",
|
|
3653
|
+
codingGuidance: "Every color is a bare var(--ggui-color-*) from the token manifest \u2014 no hex, rgb()/hsl(), CSS named colors or literal fallbacks, in style props and <style> blocks alike. Spacing, typography, radius and shadow geometry may be literals.",
|
|
3654
|
+
evalInstruction: "Flag hardcoded hex colors, rgba/hsl functions, CSS named colors, and literal fallbacks inside var(--ggui-*) references. Do NOT flag literal spacing, font sizes, radii or pixel values \u2014 they are allowed in this mode."
|
|
3655
|
+
},
|
|
3656
|
+
{
|
|
3657
|
+
id: "visual",
|
|
3658
|
+
name: "Visual composition",
|
|
3659
|
+
priority: "P2",
|
|
3660
|
+
tier: 2,
|
|
3661
|
+
failOutcome: "warn",
|
|
3662
|
+
codingGuidance: "Compose deliberately: one clear focal point, consistent spacing rhythm, a coherent theme-token palette, a fit to the rendering canvas.",
|
|
3663
|
+
evalInstruction: `Evaluate VISUAL COMPOSITION: Is the component composed deliberately for its canvas?
|
|
3664
|
+
|
|
3665
|
+
Judge: visual hierarchy (one clear focal point, headings distinct from body text), consistent spacing rhythm and alignment, a coherent palette drawn from the theme tokens, fit to the canvas (fluid width, no fixed widths, nothing cramped or stretched).
|
|
3666
|
+
Do NOT reward or penalise the use of design-system primitives \u2014 raw HTML with inline CSS is a first-class choice here. Literal spacing / typography / radius values are fine.
|
|
3667
|
+
|
|
3668
|
+
Only list ACTUAL composition problems. Use 'fail' only for a fundamentally incoherent composition.`
|
|
3669
|
+
}
|
|
3670
|
+
];
|
|
3671
|
+
function criteriaFor(designMode = "constrained") {
|
|
3672
|
+
if (designMode === "constrained") return CRITERIA;
|
|
3673
|
+
return CRITERIA.map(
|
|
3674
|
+
(c) => FREE_DESIGN_CRITERIA_OVERRIDES.find((o) => o.id === c.id) ?? c
|
|
3675
|
+
);
|
|
3676
|
+
}
|
|
3677
|
+
function getCriteriaByPriority(priority, designMode = "constrained") {
|
|
3678
|
+
return criteriaFor(designMode).filter((c) => c.priority === priority);
|
|
359
3679
|
}
|
|
360
|
-
function getCriterionById(id) {
|
|
361
|
-
return
|
|
3680
|
+
function getCriterionById(id, designMode = "constrained") {
|
|
3681
|
+
return criteriaFor(designMode).find((c) => c.id === id);
|
|
362
3682
|
}
|
|
363
|
-
function getLLMCriteria() {
|
|
364
|
-
return
|
|
3683
|
+
function getLLMCriteria(designMode = "constrained") {
|
|
3684
|
+
return criteriaFor(designMode).filter((c) => c.tier > 0);
|
|
365
3685
|
}
|
|
366
|
-
function buildCodingCriteriaSummary() {
|
|
3686
|
+
function buildCodingCriteriaSummary(designMode = "constrained") {
|
|
367
3687
|
const lines = ["## Priority (P0 first, then P1, then P2)", ""];
|
|
368
3688
|
for (const priority of ["P0", "P1", "P2"]) {
|
|
369
3689
|
const label = priority === "P0" ? "Must (compile + complete)" : priority === "P1" ? "Should (safety)" : "Nice (quality)";
|
|
370
|
-
const criteria = getCriteriaByPriority(priority);
|
|
3690
|
+
const criteria = getCriteriaByPriority(priority, designMode);
|
|
371
3691
|
lines.push(`**${priority} \u2014 ${label}:**`);
|
|
372
3692
|
for (const c of criteria) {
|
|
373
3693
|
lines.push(`- ${c.codingGuidance}`);
|
|
@@ -501,7 +3821,7 @@ function extractRetryAfterSec(e) {
|
|
|
501
3821
|
return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : void 0;
|
|
502
3822
|
}
|
|
503
3823
|
function sleep(ms) {
|
|
504
|
-
return new Promise((
|
|
3824
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
505
3825
|
}
|
|
506
3826
|
var MAX_RETRY_ATTEMPTS = 2;
|
|
507
3827
|
var RETRY_AFTER_CAP_SEC = 15;
|
|
@@ -2238,6 +5558,9 @@ function mkIssue(subcategory, description, fix, result = "fail") {
|
|
|
2238
5558
|
function cap(s) {
|
|
2239
5559
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
2240
5560
|
}
|
|
5561
|
+
function axisCheckTraceEnabled() {
|
|
5562
|
+
return process.env["GGUI_AXIS_CHECK_TRACE"] === "1";
|
|
5563
|
+
}
|
|
2241
5564
|
|
|
2242
5565
|
// src/evaluation/axis-checks/checks/universal.ts
|
|
2243
5566
|
var ALL_RENDER_VALUES = [
|
|
@@ -2339,9 +5662,174 @@ function runPropSeedNoResync(input) {
|
|
|
2339
5662
|
)
|
|
2340
5663
|
);
|
|
2341
5664
|
}
|
|
2342
|
-
return issues;
|
|
5665
|
+
return issues;
|
|
5666
|
+
}
|
|
5667
|
+
var KNOWN_ICON_KEYS = new Set(
|
|
5668
|
+
LUCIDE_ICON_NAMES.map((n) => n.replace(/[-_]/g, "").toLowerCase())
|
|
5669
|
+
);
|
|
5670
|
+
function isKnownIconName(name) {
|
|
5671
|
+
return KNOWN_ICON_KEYS.has(name.replace(/[-_]/g, "").toLowerCase());
|
|
5672
|
+
}
|
|
5673
|
+
var ICON_NAME_LITERAL_RX = /<Icon\b[^>]*?\bname\s*=\s*(?:"([^"]*)"|'([^']*)'|\{\s*"([^"]*)"\s*\}|\{\s*'([^']*)'\s*\})/g;
|
|
5674
|
+
function findUnknownIconNames(sourceCode) {
|
|
5675
|
+
const unknown = /* @__PURE__ */ new Set();
|
|
5676
|
+
for (const m of sourceCode.matchAll(ICON_NAME_LITERAL_RX)) {
|
|
5677
|
+
const name = m[1] ?? m[2] ?? m[3] ?? m[4] ?? "";
|
|
5678
|
+
if (name.length === 0) continue;
|
|
5679
|
+
if (/[^\x20-\x7e]/.test(name)) continue;
|
|
5680
|
+
if (!isKnownIconName(name)) unknown.add(name);
|
|
5681
|
+
}
|
|
5682
|
+
return [...unknown];
|
|
5683
|
+
}
|
|
5684
|
+
function runIconNameKnown(input) {
|
|
5685
|
+
if (input.compiledCode === null) return [];
|
|
5686
|
+
const unknown = findUnknownIconNames(input.sourceCode);
|
|
5687
|
+
if (unknown.length === 0) return [];
|
|
5688
|
+
const list = unknown.map((n) => `"${n}"`).join(", ");
|
|
5689
|
+
return [
|
|
5690
|
+
mkIssue(
|
|
5691
|
+
"universal.icon_name_known",
|
|
5692
|
+
`<Icon name=\u2026> uses ${unknown.length} name(s) outside the design system's Lucide subset: ${list} \u2014 an unknown name renders an empty box.`,
|
|
5693
|
+
"Call get_available_icons and pick a listed name (kebab-case), or use an emoji directly."
|
|
5694
|
+
)
|
|
5695
|
+
];
|
|
5696
|
+
}
|
|
5697
|
+
var LADDER_STOP_AS_TEXT_RX = /(?<![\w-])color\s*(?:=\s*\{?\s*|:\s*)["'`]?\s*var\(--ggui-color-primary-(\d{2,3})\s*[,)]/g;
|
|
5698
|
+
var TEXT_INK_STOP_MIN = 300;
|
|
5699
|
+
var TEXT_INK_STOP_MAX = 600;
|
|
5700
|
+
function findLadderStopsAsText(sourceCode) {
|
|
5701
|
+
const found = /* @__PURE__ */ new Set();
|
|
5702
|
+
for (const m of sourceCode.matchAll(LADDER_STOP_AS_TEXT_RX)) {
|
|
5703
|
+
const digits = m[1] ?? "";
|
|
5704
|
+
const stop = Number(digits);
|
|
5705
|
+
if (stop >= TEXT_INK_STOP_MIN && stop <= TEXT_INK_STOP_MAX) found.add(`primary-${digits}`);
|
|
5706
|
+
}
|
|
5707
|
+
return [...found];
|
|
5708
|
+
}
|
|
5709
|
+
function runAccentTextInk(input) {
|
|
5710
|
+
if (input.compiledCode === null) return [];
|
|
5711
|
+
const stops = findLadderStopsAsText(input.sourceCode);
|
|
5712
|
+
if (stops.length === 0) return [];
|
|
5713
|
+
const list = stops.map((s) => `\`${s}\``).join(", ");
|
|
5714
|
+
return [
|
|
5715
|
+
mkIssue(
|
|
5716
|
+
"universal.accent_text_ink",
|
|
5717
|
+
`Text is painted with a brand-ladder fill stop as its color (${list}) \u2014 on a low-saturation brand these stops are mid-grey on the surface and the text fails readability.`,
|
|
5718
|
+
'Accent text (eyebrows, taglines, links, labels, inline arrows) takes var(--ggui-color-link) or <Text tone="emphasized">; body text takes var(--ggui-color-onContainer); keep primary-* stops on fills and borders.'
|
|
5719
|
+
)
|
|
5720
|
+
];
|
|
5721
|
+
}
|
|
5722
|
+
var SCOPED_SURFACE_TAG_RX = /<(Card|Box)\b([^<>]*?)surface\s*=\s*["'](inverted|hero)["']([^<>]*?)>/g;
|
|
5723
|
+
var STYLE_BACKGROUND_RX = /\bstyle\s*=\s*\{\{[^}]*\b(background|backgroundColor|backgroundImage)\s*:/;
|
|
5724
|
+
function findScopedSurfaceBackgrounds(sourceCode) {
|
|
5725
|
+
const hits = [];
|
|
5726
|
+
for (const m of sourceCode.matchAll(SCOPED_SURFACE_TAG_RX)) {
|
|
5727
|
+
const attrs = `${m[2] ?? ""} ${m[4] ?? ""}`;
|
|
5728
|
+
if (STYLE_BACKGROUND_RX.test(attrs)) hits.push([m[1] ?? "", m[3] ?? ""]);
|
|
5729
|
+
}
|
|
5730
|
+
return hits;
|
|
5731
|
+
}
|
|
5732
|
+
function runScopedSurfaceOwnsGround(input) {
|
|
5733
|
+
if (input.compiledCode === null) return [];
|
|
5734
|
+
if (input.designMode === "free") return [];
|
|
5735
|
+
const hits = findScopedSurfaceBackgrounds(input.sourceCode);
|
|
5736
|
+
if (hits.length === 0) return [];
|
|
5737
|
+
const [tag, surface] = hits[0];
|
|
5738
|
+
return [
|
|
5739
|
+
mkIssue(
|
|
5740
|
+
"universal.scoped_surface_owns_ground",
|
|
5741
|
+
`<${tag} surface="${surface}"> sets its own background in style \u2014 a scoped surface owns its ground; repainting it puts the scope's swapped inks over the wrong ground (ink on ink).`,
|
|
5742
|
+
`Remove the background from that ${tag}'s style \u2014 surface="${surface}" paints the ground; pick another surface if a different ground is wanted.`
|
|
5743
|
+
)
|
|
5744
|
+
];
|
|
5745
|
+
}
|
|
5746
|
+
var CAPS_TEXT_RX = /<Text\b(?=[^>]*\bcaps\b)[^>]*>([\s\S]*?)<\/Text>/g;
|
|
5747
|
+
function findInventedCapsLabels(sourceCode) {
|
|
5748
|
+
const out = [];
|
|
5749
|
+
for (const m of sourceCode.matchAll(CAPS_TEXT_RX)) {
|
|
5750
|
+
const inner = (m[1] ?? "").trim();
|
|
5751
|
+
if (inner.length === 0) continue;
|
|
5752
|
+
if (inner.includes("{")) continue;
|
|
5753
|
+
out.push(inner.replace(/\s+/g, " ").slice(0, 60));
|
|
5754
|
+
}
|
|
5755
|
+
return out;
|
|
5756
|
+
}
|
|
5757
|
+
function runCapsLabelInvented(input) {
|
|
5758
|
+
if (input.compiledCode === null) return [];
|
|
5759
|
+
const invented = findInventedCapsLabels(input.sourceCode);
|
|
5760
|
+
if (invented.length === 0) return [];
|
|
5761
|
+
const list = invented.map((t) => `"${t}"`).join(", ");
|
|
5762
|
+
return [
|
|
5763
|
+
mkIssue(
|
|
5764
|
+
"universal.caps_label_invented",
|
|
5765
|
+
`${invented.length} caps label(s) carry invented copy the props do not supply: ${list} \u2014 an eyebrow, kicker or overline the agent cannot change is chatter on every render.`,
|
|
5766
|
+
"Remove the label, or bind its text to a prop (`<Text caps>{props.section}</Text>`); copy comes from the contract, never from the component."
|
|
5767
|
+
)
|
|
5768
|
+
];
|
|
5769
|
+
}
|
|
5770
|
+
var VIEWPORT_UNIT = String.raw`(?:calc\(\s*)?100(?:vh|dvh|svh|lvh)\b(?:[^)"'\x60;\n]*\))?`;
|
|
5771
|
+
var VIEWPORT_STYLE_OBJECT_RX = new RegExp(
|
|
5772
|
+
String.raw`\b(?:minHeight|height|minBlockSize|blockSize)\s*:\s*["'\x60]\s*${VIEWPORT_UNIT}["'\x60]?`,
|
|
5773
|
+
"g"
|
|
5774
|
+
);
|
|
5775
|
+
var VIEWPORT_CSS_RX = new RegExp(
|
|
5776
|
+
String.raw`(?<![\w-])(?:min-)?(?:height|block-size)\s*:\s*${VIEWPORT_UNIT}`,
|
|
5777
|
+
"g"
|
|
5778
|
+
);
|
|
5779
|
+
var VIEWPORT_CLASS_RX = /(?<![\w-])(?:min-)?h-(?:screen|dvh|svh|lvh)\b/g;
|
|
5780
|
+
function findViewportSizing(sourceCode) {
|
|
5781
|
+
const hits = [];
|
|
5782
|
+
for (const rx of [VIEWPORT_STYLE_OBJECT_RX, VIEWPORT_CSS_RX, VIEWPORT_CLASS_RX]) {
|
|
5783
|
+
for (const m of sourceCode.matchAll(rx)) {
|
|
5784
|
+
hits.push({ at: m.index ?? 0, text: m[0].replace(/\s+/g, " ").trim().slice(0, 60) });
|
|
5785
|
+
}
|
|
5786
|
+
}
|
|
5787
|
+
return hits.sort((a, b) => a.at - b.at).map((h) => h.text);
|
|
5788
|
+
}
|
|
5789
|
+
function runViewportSized(input) {
|
|
5790
|
+
if (input.compiledCode === null) return [];
|
|
5791
|
+
const sized = findViewportSizing(input.sourceCode);
|
|
5792
|
+
if (sized.length === 0) return [];
|
|
5793
|
+
const list = sized.map((t) => "`" + t + "`").join(", ");
|
|
5794
|
+
return [
|
|
5795
|
+
mkIssue(
|
|
5796
|
+
"universal.viewport_sized",
|
|
5797
|
+
`${sized.length} element(s) are sized to the viewport: ${list} \u2014 the frame owns the height; a content-sized frame is measured from the content, so a viewport-sized root never shrinks and grows the frame on every re-measure.`,
|
|
5798
|
+
"Remove the viewport height \u2014 size to content, never to the viewport. Under fullscreen the frame stretches your root already (centre inside it with `display: flex; flex-direction: column; justify-content: center`); to fill a parent that has a height use `height: 100%` or `flex: 1`."
|
|
5799
|
+
)
|
|
5800
|
+
];
|
|
2343
5801
|
}
|
|
2344
5802
|
var UNIVERSAL_CHECKS = [
|
|
5803
|
+
{
|
|
5804
|
+
id: "universal.icon_name_known",
|
|
5805
|
+
axis: "render",
|
|
5806
|
+
values: ALL_RENDER_VALUES,
|
|
5807
|
+
run: runIconNameKnown
|
|
5808
|
+
},
|
|
5809
|
+
{
|
|
5810
|
+
id: "universal.caps_label_invented",
|
|
5811
|
+
axis: "render",
|
|
5812
|
+
values: ALL_RENDER_VALUES,
|
|
5813
|
+
run: runCapsLabelInvented
|
|
5814
|
+
},
|
|
5815
|
+
{
|
|
5816
|
+
id: "universal.viewport_sized",
|
|
5817
|
+
axis: "render",
|
|
5818
|
+
values: ALL_RENDER_VALUES,
|
|
5819
|
+
run: runViewportSized
|
|
5820
|
+
},
|
|
5821
|
+
{
|
|
5822
|
+
id: "universal.accent_text_ink",
|
|
5823
|
+
axis: "render",
|
|
5824
|
+
values: ALL_RENDER_VALUES,
|
|
5825
|
+
run: runAccentTextInk
|
|
5826
|
+
},
|
|
5827
|
+
{
|
|
5828
|
+
id: "universal.scoped_surface_owns_ground",
|
|
5829
|
+
axis: "render",
|
|
5830
|
+
values: ALL_RENDER_VALUES,
|
|
5831
|
+
run: runScopedSurfaceOwnsGround
|
|
5832
|
+
},
|
|
2345
5833
|
{
|
|
2346
5834
|
id: "universal.prop_coverage",
|
|
2347
5835
|
axis: "render",
|
|
@@ -3144,6 +6632,87 @@ var TOOLING_CHECKS = [
|
|
|
3144
6632
|
}
|
|
3145
6633
|
];
|
|
3146
6634
|
|
|
6635
|
+
// src/evaluation/axis-checks/checks/grid.ts
|
|
6636
|
+
var BOARD_PROP_RX = /^(columns?|lanes?|stages?|lists?|buckets?|swimlanes?)$/i;
|
|
6637
|
+
var BOARD_PROMPT_RX = /\b(kanban|board)\b/i;
|
|
6638
|
+
var BOARD_NAMES = ["columns", "lanes", "stages", "lists", "buckets", "swimlanes"];
|
|
6639
|
+
var LAYOUT_TAG_RX = /<(\/?)(Grid|Row|Stack|Card|Box|Container|ScrollArea|div|section)\b([^<>]*?)>/g;
|
|
6640
|
+
var SIDE_BY_SIDE = /* @__PURE__ */ new Set(["Grid", "Row"]);
|
|
6641
|
+
function boardPropNames(contract) {
|
|
6642
|
+
const propsField = contract?.propsSpec;
|
|
6643
|
+
const properties = propsField?.properties ?? {};
|
|
6644
|
+
return Object.entries(properties).filter(([name, p]) => BOARD_PROP_RX.test(name) && (p?.type === "array" || p?.schema?.type === "array")).map(([name]) => name);
|
|
6645
|
+
}
|
|
6646
|
+
function jsxMapPositions(sourceCode, name) {
|
|
6647
|
+
const rx = new RegExp(
|
|
6648
|
+
`\\b${name}(?:\\?\\.)?\\.map\\(\\s*\\(?\\s*\\w+(?:\\s*,\\s*\\w+)?\\s*\\)?\\s*=>\\s*(?:\\(?\\s*<|\\{[^{}]{0,600}?\\breturn\\s*\\(?\\s*<)`,
|
|
6649
|
+
"g"
|
|
6650
|
+
);
|
|
6651
|
+
return [...sourceCode.matchAll(rx)].map((m) => m.index ?? 0);
|
|
6652
|
+
}
|
|
6653
|
+
function enclosingLayoutTag(sourceCode, pos) {
|
|
6654
|
+
const stack = [];
|
|
6655
|
+
for (const m of sourceCode.slice(0, pos).matchAll(LAYOUT_TAG_RX)) {
|
|
6656
|
+
const closing = m[1] === "/";
|
|
6657
|
+
const name = m[2] ?? "";
|
|
6658
|
+
const attrs = m[3] ?? "";
|
|
6659
|
+
if (closing) {
|
|
6660
|
+
if (stack[stack.length - 1] === name) stack.pop();
|
|
6661
|
+
continue;
|
|
6662
|
+
}
|
|
6663
|
+
if (attrs.trimEnd().endsWith("/")) continue;
|
|
6664
|
+
stack.push(name);
|
|
6665
|
+
}
|
|
6666
|
+
return stack[stack.length - 1];
|
|
6667
|
+
}
|
|
6668
|
+
function describeBoardRead(input) {
|
|
6669
|
+
const declared = boardPropNames(input.contract);
|
|
6670
|
+
const names = declared.length > 0 ? declared : BOARD_PROMPT_RX.test(input.originalPrompt) ? [...BOARD_NAMES] : BOARD_NAMES.filter((n) => jsxMapPositions(input.sourceCode, n).length > 0);
|
|
6671
|
+
const perName = names.map((name) => {
|
|
6672
|
+
const positions = jsxMapPositions(input.sourceCode, name);
|
|
6673
|
+
return { name, maps: positions.length, enclosing: positions.map((pos) => enclosingLayoutTag(input.sourceCode, pos) ?? "nothing") };
|
|
6674
|
+
});
|
|
6675
|
+
return { declared, names, perName };
|
|
6676
|
+
}
|
|
6677
|
+
function findStackedBoardColumns(input) {
|
|
6678
|
+
const stacked = [];
|
|
6679
|
+
for (const { name, enclosing } of describeBoardRead(input).perName) {
|
|
6680
|
+
for (const tag of enclosing) if (!SIDE_BY_SIDE.has(tag)) stacked.push([name, tag]);
|
|
6681
|
+
}
|
|
6682
|
+
return stacked;
|
|
6683
|
+
}
|
|
6684
|
+
function runBoardColumnsSideBySide(input) {
|
|
6685
|
+
if (input.compiledCode === null) return [];
|
|
6686
|
+
const standDown = input.designMode === "free";
|
|
6687
|
+
const stacked = standDown ? [] : findStackedBoardColumns(input);
|
|
6688
|
+
if (axisCheckTraceEnabled()) {
|
|
6689
|
+
const line = {
|
|
6690
|
+
...describeBoardRead(input),
|
|
6691
|
+
designMode: input.designMode ?? "constrained",
|
|
6692
|
+
standDown,
|
|
6693
|
+
result: standDown ? "stand-down" : stacked.length > 0 ? "fail" : "pass"
|
|
6694
|
+
};
|
|
6695
|
+
console.log(JSON.stringify({ boardColumnsTrace: line }));
|
|
6696
|
+
}
|
|
6697
|
+
if (stacked.length === 0) return [];
|
|
6698
|
+
const [name, tag] = stacked[0];
|
|
6699
|
+
return [
|
|
6700
|
+
mkIssue(
|
|
6701
|
+
"grid.board_columns_side_by_side",
|
|
6702
|
+
`The board's \`${name}\` are composed under <${tag}> \u2014 a vertical stack of column sections; at md and wider the columns must sit side by side.`,
|
|
6703
|
+
`Wrap the ${name} map in <Grid columns={{ base: 1, md: ${name}.length }} gap="md"> (each column its own <Stack> of cards); never a <Stack> of column sections.`
|
|
6704
|
+
)
|
|
6705
|
+
];
|
|
6706
|
+
}
|
|
6707
|
+
var GRID_CHECKS = [
|
|
6708
|
+
{
|
|
6709
|
+
id: "grid.board_columns_side_by_side",
|
|
6710
|
+
axis: "render",
|
|
6711
|
+
values: ["grid"],
|
|
6712
|
+
run: runBoardColumnsSideBySide
|
|
6713
|
+
}
|
|
6714
|
+
];
|
|
6715
|
+
|
|
3147
6716
|
// src/evaluation/axis-checks/extras.ts
|
|
3148
6717
|
function mkIssue2(subcategory, description, fix, result = "warn") {
|
|
3149
6718
|
return { tier: 0, result, category: "mode", subcategory, description, fix };
|
|
@@ -3233,6 +6802,7 @@ var stepperAdopted = {
|
|
|
3233
6802
|
values: ["multi-step"],
|
|
3234
6803
|
run(input) {
|
|
3235
6804
|
if (input.compiledCode === null) return [];
|
|
6805
|
+
if (input.designMode === "free") return [];
|
|
3236
6806
|
if (/<Stepper[\s/>]/.test(input.sourceCode)) return [];
|
|
3237
6807
|
return [
|
|
3238
6808
|
mkIssue2(
|
|
@@ -3282,34 +6852,545 @@ var REGISTRY = [
|
|
|
3282
6852
|
...WRITES_CHECKS,
|
|
3283
6853
|
...STATE_PAYLOAD_CHECKS,
|
|
3284
6854
|
...TOOLING_CHECKS,
|
|
6855
|
+
...GRID_CHECKS,
|
|
3285
6856
|
...EXTRA_CHECKS
|
|
3286
6857
|
];
|
|
3287
|
-
|
|
3288
|
-
// src/evaluation/axis-checks/dispatch.ts
|
|
3289
6858
|
function runAxisChecks(classification, input) {
|
|
3290
|
-
|
|
3291
|
-
const axisInput = {
|
|
6859
|
+
const facts = {
|
|
3292
6860
|
sourceCode: input.sourceCode,
|
|
3293
|
-
compiledCode: input.compiledCode,
|
|
3294
6861
|
...input.contract !== void 0 ? { contract: input.contract } : {},
|
|
3295
6862
|
originalPrompt: input.originalPrompt,
|
|
3296
|
-
classification
|
|
6863
|
+
classification,
|
|
6864
|
+
...input.designMode !== void 0 ? { designMode: input.designMode } : {}
|
|
3297
6865
|
};
|
|
6866
|
+
if (input.compiledCode === null) {
|
|
6867
|
+
traceAxisChecksSkipped(facts, "compiledCode null \u2014 no check ran");
|
|
6868
|
+
return [];
|
|
6869
|
+
}
|
|
6870
|
+
const axisInput = { ...facts, compiledCode: input.compiledCode };
|
|
6871
|
+
return runGatedAxisChecks(
|
|
6872
|
+
REGISTRY.filter((check) => matches(classification.vector, check)),
|
|
6873
|
+
axisInput
|
|
6874
|
+
).issues;
|
|
6875
|
+
}
|
|
6876
|
+
function runGatedAxisChecks(checks, input) {
|
|
3298
6877
|
const issues = [];
|
|
3299
|
-
const firedIds =
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
if (
|
|
3303
|
-
|
|
3304
|
-
|
|
6878
|
+
const firedIds = [];
|
|
6879
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6880
|
+
for (const check of checks) {
|
|
6881
|
+
if (seen.has(check.id)) continue;
|
|
6882
|
+
seen.add(check.id);
|
|
6883
|
+
firedIds.push(check.id);
|
|
6884
|
+
issues.push(...check.run(input));
|
|
6885
|
+
}
|
|
6886
|
+
if (axisCheckTraceEnabled()) {
|
|
6887
|
+
const line = {
|
|
6888
|
+
...traceFacts(input),
|
|
6889
|
+
matched: [...firedIds],
|
|
6890
|
+
issues: issues.map((i) => ({ id: i.subcategory ?? i.category, result: i.result }))
|
|
6891
|
+
};
|
|
6892
|
+
console.log(JSON.stringify({ axisCheckTrace: line }));
|
|
6893
|
+
}
|
|
6894
|
+
return { issues, firedIds };
|
|
6895
|
+
}
|
|
6896
|
+
function traceAxisChecksSkipped(facts, note) {
|
|
6897
|
+
if (!axisCheckTraceEnabled()) return;
|
|
6898
|
+
const line = { ...traceFacts(facts), matched: [], issues: [], note };
|
|
6899
|
+
console.log(JSON.stringify({ axisCheckTrace: line }));
|
|
6900
|
+
}
|
|
6901
|
+
function traceFacts(input) {
|
|
6902
|
+
const propsSpec = input.contract?.propsSpec;
|
|
6903
|
+
return {
|
|
6904
|
+
sourceSha256: createHash("sha256").update(input.sourceCode, "utf8").digest("hex"),
|
|
6905
|
+
originalPrompt: input.originalPrompt,
|
|
6906
|
+
designMode: input.designMode ?? "constrained",
|
|
6907
|
+
classification: input.classification.vector,
|
|
6908
|
+
propsSpecKeys: Object.keys(propsSpec ?? {}),
|
|
6909
|
+
propsSpecPropertyKeys: Object.keys(propsSpec?.properties ?? {})
|
|
6910
|
+
};
|
|
6911
|
+
}
|
|
6912
|
+
var STYLING_PROFILE_TRUNCATION_MARKER = " \u2026[truncated at the profile bound]";
|
|
6913
|
+
var STYLING_PROFILE_JUDGE_FRAME = `The app's operator declared the styling profile below. Judge visual treatment RELATIVE to it \u2014 a dense profile is not "cramped", a flat one is not "unpolished", a sparse one is not "empty", and a directed composition is not missing what its Direction leaves out; completeness, hierarchy, accessibility and correctness are unchanged by it.`;
|
|
6914
|
+
var AESTHETIC_BRIEF_MAX_CHARS = 2e3;
|
|
6915
|
+
function sanitizeProfileMember(text, member) {
|
|
6916
|
+
return sanitizeProfileText(text, APP_GENERATION_PROFILE_BOUNDS[member]);
|
|
6917
|
+
}
|
|
6918
|
+
function sanitizeProfileText(text, bound) {
|
|
6919
|
+
if (typeof text !== "string") return "";
|
|
6920
|
+
const lines = [];
|
|
6921
|
+
let inFence = false;
|
|
6922
|
+
for (const raw of text.split(/\r?\n/)) {
|
|
6923
|
+
const line = raw.replace(/[ \t]+/g, " ").trim();
|
|
6924
|
+
if (line.startsWith("```")) {
|
|
6925
|
+
inFence = !inFence;
|
|
6926
|
+
continue;
|
|
6927
|
+
}
|
|
6928
|
+
if (inFence || line.length === 0 || line.startsWith("#")) continue;
|
|
6929
|
+
lines.push(line);
|
|
6930
|
+
}
|
|
6931
|
+
let out = lines.join("\n").replace(/`/g, "");
|
|
6932
|
+
if (out.length > bound) out = out.slice(0, bound) + STYLING_PROFILE_TRUNCATION_MARKER;
|
|
6933
|
+
return out;
|
|
6934
|
+
}
|
|
6935
|
+
function aestheticRefLabel(profile) {
|
|
6936
|
+
const ref = profile?.aesthetic;
|
|
6937
|
+
if (ref === void 0 || sanitizeProfileText(profile?.aestheticBrief, AESTHETIC_BRIEF_MAX_CHARS).length === 0) return "";
|
|
6938
|
+
return ref.version !== void 0 ? `${ref.id}@${ref.version}` : ref.id;
|
|
6939
|
+
}
|
|
6940
|
+
function sanitizeProfile(profile) {
|
|
6941
|
+
const aestheticRef = aestheticRefLabel(profile);
|
|
6942
|
+
return {
|
|
6943
|
+
styling: sanitizeProfileMember(profile?.styling, "styling"),
|
|
6944
|
+
density: sanitizeProfileMember(profile?.density, "density"),
|
|
6945
|
+
layout: sanitizeProfileMember(profile?.layout, "layout"),
|
|
6946
|
+
direction: sanitizeProfileMember(profile?.direction, "direction"),
|
|
6947
|
+
aesthetic: aestheticRef.length > 0 ? sanitizeProfileText(profile?.aestheticBrief, AESTHETIC_BRIEF_MAX_CHARS) : "",
|
|
6948
|
+
aestheticRef
|
|
6949
|
+
};
|
|
6950
|
+
}
|
|
6951
|
+
function renderProfileQuote(profile) {
|
|
6952
|
+
const p = sanitizeProfile(profile);
|
|
6953
|
+
const parts = [];
|
|
6954
|
+
if (p.styling.length > 0) parts.push(p.styling.split("\n").map((line) => `> ${line}`).join("\n"));
|
|
6955
|
+
if (p.density.length > 0) parts.push(`> **Density**: ${p.density}`);
|
|
6956
|
+
if (p.layout.length > 0) parts.push(`> **Layout**: ${p.layout}`);
|
|
6957
|
+
if (p.direction.length > 0) parts.push(`> **Direction**: ${p.direction}`);
|
|
6958
|
+
if (p.aesthetic.length > 0) {
|
|
6959
|
+
const [first, ...rest] = p.aesthetic.split("\n");
|
|
6960
|
+
parts.push([`> **Aesthetic** (\`${p.aestheticRef}\`): ${first ?? ""}`, ...rest.map((line) => `> ${line}`)].join("\n"));
|
|
6961
|
+
}
|
|
6962
|
+
return parts.join("\n>\n");
|
|
6963
|
+
}
|
|
6964
|
+
function buildStylingProfileJudgeBlock(profile) {
|
|
6965
|
+
const quote = renderProfileQuote(profile);
|
|
6966
|
+
if (quote.length === 0) return "";
|
|
6967
|
+
return ["## Declared styling profile", "", STYLING_PROFILE_JUDGE_FRAME, "", quote].join("\n");
|
|
6968
|
+
}
|
|
6969
|
+
function isDesignRenderingInput(relativePath) {
|
|
6970
|
+
const rel = relativePath.split("\\").join("/");
|
|
6971
|
+
if (rel.startsWith("__tests__/") || rel.includes("/__tests__/")) return false;
|
|
6972
|
+
if (/\.test\.[cm]?[jt]sx?$/.test(rel)) return false;
|
|
6973
|
+
if (/\.stories\.[cm]?[jt]sx?$/.test(rel)) return false;
|
|
6974
|
+
if (rel.endsWith(".md")) return false;
|
|
6975
|
+
return true;
|
|
6976
|
+
}
|
|
6977
|
+
function designTreeSha256(root) {
|
|
6978
|
+
const files = [];
|
|
6979
|
+
const walk = (dir) => {
|
|
6980
|
+
for (const name of readdirSync(dir).sort()) {
|
|
6981
|
+
const full = resolve(dir, name);
|
|
6982
|
+
if (statSync(full).isDirectory()) walk(full);
|
|
6983
|
+
else if (isDesignRenderingInput(full.slice(root.length + 1))) files.push(full);
|
|
6984
|
+
}
|
|
6985
|
+
};
|
|
6986
|
+
walk(root);
|
|
6987
|
+
const h = createHash("sha256");
|
|
6988
|
+
for (const f of files) {
|
|
6989
|
+
h.update(f.slice(root.length + 1) + "\n");
|
|
6990
|
+
h.update(readFileSync(f));
|
|
6991
|
+
h.update("\n");
|
|
6992
|
+
}
|
|
6993
|
+
return h.digest("hex");
|
|
6994
|
+
}
|
|
6995
|
+
var identityCache = /* @__PURE__ */ new Map();
|
|
6996
|
+
function judgeDesignIdentity(src) {
|
|
6997
|
+
const key = resolve(src);
|
|
6998
|
+
const cached = identityCache.get(key);
|
|
6999
|
+
if (cached !== void 0) return cached;
|
|
7000
|
+
let identity;
|
|
7001
|
+
try {
|
|
7002
|
+
identity = { src: key, srcSha256: designTreeSha256(key) };
|
|
7003
|
+
} catch (e) {
|
|
7004
|
+
const reason = e instanceof Error ? e.message : String(e);
|
|
7005
|
+
console.warn(`[visual-eval] design tree unreadable at ${key} \u2014 the judgement carries no design identity (${reason})`);
|
|
7006
|
+
identity = null;
|
|
7007
|
+
}
|
|
7008
|
+
identityCache.set(key, identity);
|
|
7009
|
+
return identity;
|
|
7010
|
+
}
|
|
7011
|
+
function resetJudgeDesignIdentityCache() {
|
|
7012
|
+
identityCache.clear();
|
|
7013
|
+
}
|
|
7014
|
+
|
|
7015
|
+
// src/design-mode.ts
|
|
7016
|
+
var CANVAS_CLASSES = [
|
|
7017
|
+
"xs-chat-card",
|
|
7018
|
+
"mobile-fullscreen-small",
|
|
7019
|
+
"md",
|
|
7020
|
+
"lg",
|
|
7021
|
+
"xl"
|
|
7022
|
+
];
|
|
7023
|
+
var CANVAS_VIEWPORTS = {
|
|
7024
|
+
"xs-chat-card": { width: 400, height: 640 },
|
|
7025
|
+
"mobile-fullscreen-small": { width: 390, height: 844 },
|
|
7026
|
+
md: { width: 768, height: 1024 },
|
|
7027
|
+
lg: { width: 1024, height: 768 },
|
|
7028
|
+
xl: { width: 1440, height: 900 }
|
|
7029
|
+
};
|
|
7030
|
+
function displayModeForCanvas(canvas) {
|
|
7031
|
+
return canvas === "xs-chat-card" ? "inline" : "fullscreen";
|
|
7032
|
+
}
|
|
7033
|
+
function canvasDisplayModeForShell(shell) {
|
|
7034
|
+
return shell === "chat" || shell === "inline" ? "inline" : "fullscreen";
|
|
7035
|
+
}
|
|
7036
|
+
var CANVAS_BREAKPOINTS = { md: 600, lg: 1024, xl: 1440 };
|
|
7037
|
+
function canvasForViewportWidth(mode, width) {
|
|
7038
|
+
if (mode === "inline") return "xs-chat-card";
|
|
7039
|
+
if (width < CANVAS_BREAKPOINTS.md) return "mobile-fullscreen-small";
|
|
7040
|
+
if (width < CANVAS_BREAKPOINTS.lg) return "md";
|
|
7041
|
+
if (width < CANVAS_BREAKPOINTS.xl) return "lg";
|
|
7042
|
+
return "xl";
|
|
7043
|
+
}
|
|
7044
|
+
function canvasForRendering(shellType, screen) {
|
|
7045
|
+
const shell = shellType ?? "fullscreen";
|
|
7046
|
+
if (canvasDisplayModeForShell(shell) === "inline") return "xs-chat-card";
|
|
7047
|
+
if (shell === "spatial") return "md";
|
|
7048
|
+
switch (screen ?? "universal") {
|
|
7049
|
+
case "mobile":
|
|
7050
|
+
return "mobile-fullscreen-small";
|
|
7051
|
+
case "tablet":
|
|
7052
|
+
return "md";
|
|
7053
|
+
default:
|
|
7054
|
+
return "lg";
|
|
7055
|
+
}
|
|
7056
|
+
}
|
|
7057
|
+
var CANVAS_DESCRIPTORS = {
|
|
7058
|
+
"xs-chat-card": {
|
|
7059
|
+
label: "extra-small chat card",
|
|
7060
|
+
minWidthPx: 320,
|
|
7061
|
+
maxWidthPx: 480,
|
|
7062
|
+
host: "an inline card inside a chat message bubble \u2014 the host draws the card border, shadow and rounded corners; the component fills the bubble width and takes its natural height"
|
|
7063
|
+
},
|
|
7064
|
+
"mobile-fullscreen-small": {
|
|
7065
|
+
label: "small mobile fullscreen",
|
|
7066
|
+
minWidthPx: 320,
|
|
7067
|
+
maxWidthPx: 599,
|
|
7068
|
+
host: "a phone-sized viewport the component owns edge to edge \u2014 single column, touch targets at least 44px, the component manages its own scroll"
|
|
7069
|
+
},
|
|
7070
|
+
md: {
|
|
7071
|
+
label: "medium panel",
|
|
7072
|
+
minWidthPx: 600,
|
|
7073
|
+
maxWidthPx: 1023,
|
|
7074
|
+
host: "a tablet viewport or a floating panel (spatial / picture-in-picture) \u2014 one or two columns, medium density"
|
|
7075
|
+
},
|
|
7076
|
+
lg: {
|
|
7077
|
+
label: "large fullscreen",
|
|
7078
|
+
minWidthPx: 1024,
|
|
7079
|
+
maxWidthPx: 1439,
|
|
7080
|
+
host: "a desktop viewport the component owns edge to edge \u2014 multi-column layouts, hover states and pointer interactions are available"
|
|
7081
|
+
},
|
|
7082
|
+
xl: {
|
|
7083
|
+
label: "extra-large fullscreen",
|
|
7084
|
+
minWidthPx: 1440,
|
|
7085
|
+
maxWidthPx: 1920,
|
|
7086
|
+
host: "a wide desktop viewport the component owns edge to edge \u2014 cap content width or use the extra room deliberately; never stretch a single column across the whole width"
|
|
7087
|
+
}
|
|
7088
|
+
};
|
|
7089
|
+
function describeCanvas(canvas) {
|
|
7090
|
+
const d = CANVAS_DESCRIPTORS[canvas];
|
|
7091
|
+
return `This component renders on the \`${canvas}\` canvas (${d.label}): ${d.minWidthPx}\u2013${d.maxWidthPx}px wide, ${d.host}. Design for the whole range \u2014 the host may size the iframe anywhere inside it, and the host owns the height: size to your content, never to the viewport.`;
|
|
7092
|
+
}
|
|
7093
|
+
|
|
7094
|
+
// src/evaluation/visual-evaluator.ts
|
|
7095
|
+
function canvasFitPolicy(canvas) {
|
|
7096
|
+
switch (canvas) {
|
|
7097
|
+
case "xs-chat-card":
|
|
7098
|
+
return { capture: "viewport", overflow: "fail" };
|
|
7099
|
+
case "mobile-fullscreen-small":
|
|
7100
|
+
return { capture: "full-page", overflow: "warn" };
|
|
7101
|
+
default:
|
|
7102
|
+
return { capture: "full-page", overflow: "none" };
|
|
7103
|
+
}
|
|
7104
|
+
}
|
|
7105
|
+
var JUDGE_SCOPE_CLASS = "ggui-judge-scope";
|
|
7106
|
+
function canvasFit(canvas) {
|
|
7107
|
+
return displayModeForCanvas(canvas) === "fullscreen" ? "fill" : void 0;
|
|
7108
|
+
}
|
|
7109
|
+
function canvasOverflowIssue(canvas, viewport, contentHeight, verdict) {
|
|
7110
|
+
const hidden = contentHeight - viewport.height;
|
|
7111
|
+
return {
|
|
7112
|
+
dimension: "canvas-overflow",
|
|
7113
|
+
severity: verdict === "fail" ? "critical" : "major",
|
|
7114
|
+
description: `Rendered content is ${contentHeight}px tall on the ${canvas} canvas (${viewport.width}\xD7${viewport.height}) \u2014 ${hidden}px ${verdict === "fail" ? "is cut off: the inline card does not scroll" : "sits below the first screen"}.`,
|
|
7115
|
+
fix: "Fit the composition to the canvas: fewer and shorter sections, one compact row of chips, no hero taller than a third of the box, no fixed min-heights or tall paddings \u2014 measure against the canvas, not the page."
|
|
7116
|
+
};
|
|
7117
|
+
}
|
|
7118
|
+
function resolveUiGenPackageDir() {
|
|
7119
|
+
const selfDir = dirname(fileURLToPath(import.meta.url));
|
|
7120
|
+
return resolve(selfDir, "..", "..");
|
|
7121
|
+
}
|
|
7122
|
+
function resolveWirePackageDir() {
|
|
7123
|
+
const uiGenDir = resolveUiGenPackageDir();
|
|
7124
|
+
const candidates = [
|
|
7125
|
+
resolve(uiGenDir, "node_modules", "@ggui-ai", "wire"),
|
|
7126
|
+
// workspace / nested install
|
|
7127
|
+
resolve(uiGenDir, "..", "wire"),
|
|
7128
|
+
// pnpm deploy: `.pnpm/<ui-gen>@<ver>/node_modules/@ggui-ai/{ui-gen,wire}`
|
|
7129
|
+
resolve(uiGenDir, "..", "..", "@ggui-ai", "wire")
|
|
7130
|
+
// hoisted flat install beside the scope dir
|
|
7131
|
+
];
|
|
7132
|
+
for (const dir of candidates) {
|
|
7133
|
+
if (existsSync(resolve(dir, "package.json"))) return dir;
|
|
7134
|
+
}
|
|
7135
|
+
try {
|
|
7136
|
+
const entry = fileURLToPath(import.meta.resolve("@ggui-ai/wire"));
|
|
7137
|
+
let dir = dirname(entry);
|
|
7138
|
+
for (let i = 0; i < 6; i++) {
|
|
7139
|
+
if (existsSync(resolve(dir, "package.json"))) return dir;
|
|
7140
|
+
dir = dirname(dir);
|
|
7141
|
+
}
|
|
7142
|
+
} catch {
|
|
7143
|
+
}
|
|
7144
|
+
return null;
|
|
7145
|
+
}
|
|
7146
|
+
function resolveDesignPackageDir() {
|
|
7147
|
+
try {
|
|
7148
|
+
return dirname(createRequire(import.meta.url).resolve("@ggui-ai/design/package.json"));
|
|
7149
|
+
} catch {
|
|
7150
|
+
const selfDir = dirname(fileURLToPath(import.meta.url));
|
|
7151
|
+
return resolve(selfDir, "..", "..", "..", "design");
|
|
7152
|
+
}
|
|
7153
|
+
}
|
|
7154
|
+
async function bundleForRendering(compiledCode, sampleProps, designSrc = resolve(resolveDesignPackageDir(), "src")) {
|
|
7155
|
+
const tmpDir = resolve(tmpdir(), "ggui-visual-eval-" + Date.now());
|
|
7156
|
+
mkdirSync(tmpDir, { recursive: true });
|
|
7157
|
+
const componentFile = resolve(tmpDir, "component.tsx");
|
|
7158
|
+
const entryFile = resolve(tmpDir, "entry.tsx");
|
|
7159
|
+
const designPkgDir = resolve(designSrc, "..");
|
|
7160
|
+
const wirePkgDir = resolveWirePackageDir();
|
|
7161
|
+
writeFileSync(componentFile, compiledCode);
|
|
7162
|
+
const entryCode = `
|
|
7163
|
+
import React from 'react';
|
|
7164
|
+
import { createRoot } from 'react-dom/client';
|
|
7165
|
+
import { GguiWireProvider } from '@ggui-ai/wire';
|
|
7166
|
+
import Component from './component.tsx';
|
|
7167
|
+
|
|
7168
|
+
const props = ${JSON.stringify(sampleProps)};
|
|
7169
|
+
const wireConfig = {
|
|
7170
|
+
app: { appId: 'visual-eval', appName: 'Visual evaluation' },
|
|
7171
|
+
render: { sessionId: 'visual-eval', isConnected: true },
|
|
7172
|
+
auth: { isAuthenticated: false },
|
|
7173
|
+
dispatch: () => {},
|
|
7174
|
+
subscribe: () => () => {},
|
|
7175
|
+
};
|
|
7176
|
+
class RenderErrorBoundary extends React.Component<{ children: React.ReactNode }, { message: string | null }> {
|
|
7177
|
+
state = { message: null as string | null };
|
|
7178
|
+
static getDerivedStateFromError(err: unknown) { return { message: err instanceof Error ? err.message : String(err) }; }
|
|
7179
|
+
render() {
|
|
7180
|
+
return this.state.message === null
|
|
7181
|
+
? this.props.children
|
|
7182
|
+
: React.createElement('div', { className: 'error' }, 'Render error: ' + this.state.message);
|
|
3305
7183
|
}
|
|
3306
|
-
return issues;
|
|
3307
7184
|
}
|
|
3308
|
-
|
|
7185
|
+
const root = createRoot(document.getElementById('root')!);
|
|
7186
|
+
try {
|
|
7187
|
+
root.render(
|
|
7188
|
+
React.createElement(GguiWireProvider, { config: wireConfig },
|
|
7189
|
+
React.createElement(RenderErrorBoundary, null, React.createElement(Component, props))),
|
|
7190
|
+
);
|
|
7191
|
+
} catch (err) {
|
|
7192
|
+
root.render(React.createElement('div', { className: 'error' }, 'Render error: ' + (err as Error).message));
|
|
7193
|
+
}
|
|
7194
|
+
`;
|
|
7195
|
+
writeFileSync(entryFile, entryCode);
|
|
7196
|
+
try {
|
|
7197
|
+
const result = await build({
|
|
7198
|
+
entryPoints: [entryFile],
|
|
7199
|
+
bundle: true,
|
|
7200
|
+
write: false,
|
|
7201
|
+
format: "esm",
|
|
7202
|
+
platform: "browser",
|
|
7203
|
+
target: "es2020",
|
|
7204
|
+
jsx: "automatic",
|
|
7205
|
+
jsxImportSource: "react",
|
|
7206
|
+
external: ["react", "react-dom", "react-dom/client", "react/jsx-runtime"],
|
|
7207
|
+
alias: {
|
|
7208
|
+
// The wire hooks: resolved from ui-gen's own module graph so the
|
|
7209
|
+
// alias holds in a workspace checkout AND in a `pnpm deploy` image
|
|
7210
|
+
// (where deps are siblings, not children, of this package).
|
|
7211
|
+
...wirePkgDir !== null ? { "@ggui-ai/wire": wirePkgDir } : {},
|
|
7212
|
+
// D1: generated code imports the single `@ggui-ai/design` barrel.
|
|
7213
|
+
// The subpath aliases stay for any first-party / legacy code.
|
|
7214
|
+
"@ggui-ai/design": resolve(designPkgDir, "src", "index.ts"),
|
|
7215
|
+
"@ggui-ai/design/primitives": resolve(designPkgDir, "src", "primitives", "index.ts"),
|
|
7216
|
+
"@ggui-ai/design/components": resolve(designPkgDir, "src", "components", "index.ts"),
|
|
7217
|
+
"@ggui-ai/design/compositions": resolve(designPkgDir, "src", "compositions", "index.ts"),
|
|
7218
|
+
"@ggui-ai/design/interact": resolve(designPkgDir, "src", "interact", "index.ts")
|
|
7219
|
+
},
|
|
7220
|
+
// Bare imports in the generated component resolve against ui-gen's
|
|
7221
|
+
// own node_modules — the temp entry dir has none. Without this every
|
|
7222
|
+
// wire-bearing component (`@ggui-ai/wire`) failed to bundle.
|
|
7223
|
+
// Workspace layout (deps under this package's node_modules) and the
|
|
7224
|
+
// `pnpm deploy` layout (deps as siblings of this package) — both
|
|
7225
|
+
// searched for any other allowlisted bare import.
|
|
7226
|
+
nodePaths: [resolve(resolveUiGenPackageDir(), "node_modules"), resolve(resolveUiGenPackageDir(), "..")],
|
|
7227
|
+
logLevel: "silent"
|
|
7228
|
+
});
|
|
7229
|
+
return result.outputFiles[0]?.text ?? "";
|
|
7230
|
+
} finally {
|
|
7231
|
+
try {
|
|
7232
|
+
unlinkSync(entryFile);
|
|
7233
|
+
} catch {
|
|
7234
|
+
}
|
|
7235
|
+
try {
|
|
7236
|
+
unlinkSync(componentFile);
|
|
7237
|
+
} catch {
|
|
7238
|
+
}
|
|
7239
|
+
}
|
|
7240
|
+
}
|
|
7241
|
+
function buildRenderHTML(bundledCode, cssTokens, fit) {
|
|
7242
|
+
const tokens = cssTokens ?? getCssTokens();
|
|
7243
|
+
return `<!DOCTYPE html>
|
|
7244
|
+
<html>
|
|
7245
|
+
<head>
|
|
7246
|
+
<meta charset="utf-8">
|
|
7247
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7248
|
+
<style>
|
|
7249
|
+
${tokens}
|
|
7250
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
7251
|
+
body {
|
|
7252
|
+
font-family: var(--ggui-font-family-sans, system-ui, -apple-system, sans-serif);
|
|
7253
|
+
background: var(--ggui-color-neutral-50, #ffffff);
|
|
7254
|
+
color: var(--ggui-color-neutral-900, #111827);
|
|
7255
|
+
}
|
|
7256
|
+
.error { color: #dc2626; padding: 16px; font-family: monospace; white-space: pre-wrap; }
|
|
7257
|
+
${fit === "fill" ? fillFitRule(JUDGE_SCOPE_CLASS) : ""}
|
|
7258
|
+
</style>
|
|
7259
|
+
</head>
|
|
7260
|
+
<body>
|
|
7261
|
+
<div id="root"${fit === "fill" ? ` class="${JUDGE_SCOPE_CLASS}"` : ""}></div>
|
|
7262
|
+
<script type="importmap">
|
|
7263
|
+
{
|
|
7264
|
+
"imports": {
|
|
7265
|
+
"react": "https://esm.sh/react@18",
|
|
7266
|
+
"react-dom": "https://esm.sh/react-dom@18",
|
|
7267
|
+
"react-dom/client": "https://esm.sh/react-dom@18/client",
|
|
7268
|
+
"react/jsx-runtime": "https://esm.sh/react@18/jsx-runtime"
|
|
7269
|
+
}
|
|
7270
|
+
}
|
|
7271
|
+
</script>
|
|
7272
|
+
<script type="module">
|
|
7273
|
+
${bundledCode}
|
|
7274
|
+
</script>
|
|
7275
|
+
</body>
|
|
7276
|
+
</html>`;
|
|
7277
|
+
}
|
|
7278
|
+
var EXECUTABLE_PATH_LAUNCH_ARGS = ["--no-sandbox", "--disable-dev-shm-usage"];
|
|
7279
|
+
var DEFAULT_SCREENSHOT_VIEWPORT = { width: 1280, height: 800 };
|
|
7280
|
+
async function loadSparticuzChromium() {
|
|
7281
|
+
const chromium = await Promise.resolve().then(() => (init_build(), build_exports));
|
|
7282
|
+
return chromium.default;
|
|
7283
|
+
}
|
|
7284
|
+
async function resolveLaunchOptions(viewport, deps = {}) {
|
|
7285
|
+
const env = deps.env ?? process.env;
|
|
7286
|
+
const override = env.PUPPETEER_EXECUTABLE_PATH?.trim();
|
|
7287
|
+
if (override) {
|
|
7288
|
+
return {
|
|
7289
|
+
executablePath: override,
|
|
7290
|
+
args: [...EXECUTABLE_PATH_LAUNCH_ARGS],
|
|
7291
|
+
defaultViewport: viewport,
|
|
7292
|
+
headless: true
|
|
7293
|
+
};
|
|
7294
|
+
}
|
|
7295
|
+
const chromium = await (deps.loadChromium ?? loadSparticuzChromium)();
|
|
7296
|
+
return {
|
|
7297
|
+
args: chromium.args,
|
|
7298
|
+
defaultViewport: viewport,
|
|
7299
|
+
executablePath: await chromium.executablePath(),
|
|
7300
|
+
headless: true
|
|
7301
|
+
};
|
|
7302
|
+
}
|
|
7303
|
+
async function launchWithPuppeteer(options) {
|
|
7304
|
+
const puppeteer = await import('puppeteer-core');
|
|
7305
|
+
return puppeteer.default.launch(options);
|
|
7306
|
+
}
|
|
7307
|
+
var CONTENT_HEIGHT_EXPRESSION = "Math.max(document.documentElement.scrollHeight, document.body ? document.body.scrollHeight : 0)";
|
|
7308
|
+
async function measureContentHeight(page) {
|
|
7309
|
+
try {
|
|
7310
|
+
const h = await page.evaluate(CONTENT_HEIGHT_EXPRESSION);
|
|
7311
|
+
return typeof h === "number" && Number.isFinite(h) ? Math.round(h) : null;
|
|
7312
|
+
} catch (e) {
|
|
7313
|
+
console.warn(`[visual-eval] content height unavailable: ${e instanceof Error ? e.message : String(e)}`);
|
|
7314
|
+
return null;
|
|
7315
|
+
}
|
|
7316
|
+
}
|
|
7317
|
+
async function captureScreenshotDetailed(html, viewport = DEFAULT_SCREENSHOT_VIEWPORT, deps = {}, capture = "full-page") {
|
|
7318
|
+
try {
|
|
7319
|
+
const launchOptions = await resolveLaunchOptions(viewport, deps);
|
|
7320
|
+
const browser = await (deps.launch ?? launchWithPuppeteer)(launchOptions);
|
|
7321
|
+
try {
|
|
7322
|
+
const page = await browser.newPage();
|
|
7323
|
+
await page.setContent(html, { waitUntil: "load", timeout: 15e3 });
|
|
7324
|
+
await page.waitForNetworkIdle({ idleTime: 500, timeout: 15e3 }).catch(() => {
|
|
7325
|
+
});
|
|
7326
|
+
await page.waitForSelector("#root > *", { timeout: 1e4 }).catch(() => {
|
|
7327
|
+
});
|
|
7328
|
+
await new Promise((r) => setTimeout(r, deps.settleMs ?? 1e3));
|
|
7329
|
+
const contentHeight = await measureContentHeight(page);
|
|
7330
|
+
const screenshot = await page.screenshot({ type: "png", fullPage: capture === "full-page" });
|
|
7331
|
+
return { png: Buffer.from(screenshot), contentHeight };
|
|
7332
|
+
} finally {
|
|
7333
|
+
await browser.close();
|
|
7334
|
+
}
|
|
7335
|
+
} catch (e) {
|
|
7336
|
+
const reason = `screenshot failed: ${e instanceof Error ? e.message : String(e)}`;
|
|
7337
|
+
console.warn(`[visual-eval] ${reason}`);
|
|
7338
|
+
return { png: null, reason, contentHeight: null };
|
|
7339
|
+
}
|
|
7340
|
+
}
|
|
7341
|
+
async function captureScreenshot(html, viewport = DEFAULT_SCREENSHOT_VIEWPORT, deps = {}) {
|
|
7342
|
+
return (await captureScreenshotDetailed(html, viewport, deps)).png;
|
|
7343
|
+
}
|
|
7344
|
+
var VISUAL_EVAL_PROMPT = `You are a visual quality evaluator for ggui \u2014 a platform where AI agents generate React UI components on demand.
|
|
7345
|
+
|
|
7346
|
+
## Context
|
|
7347
|
+
The screenshot shows a generated React component built from a design system with CSS variable theming. The component was created by an LLM to fulfill a user's request. Your job is to evaluate whether the generated UI achieves the user's goal AND looks professionally designed.
|
|
7348
|
+
|
|
7349
|
+
## Scoring Dimensions (0-100 each)
|
|
7350
|
+
|
|
7351
|
+
1. **completeness** (25%): Does the screenshot show ALL features the user requested? Are all sections, controls, data fields, and interactive elements present? Missing features or sections = major deduction. Compare against the original request carefully.
|
|
7352
|
+
|
|
7353
|
+
2. **layout** (25%): Is the layout well-composed? Clear sections and grouping? No overlapping elements? Proper spacing between elements? Responsive-looking? Does it look like a professional app UI, not a homework project?
|
|
7354
|
+
|
|
7355
|
+
3. **hierarchy** (25%): Clear visual hierarchy? Headings are visually distinct from body text? Primary actions (buttons) are prominent? Information grouped logically with clear section breaks? Color and size used to guide the eye?
|
|
7356
|
+
|
|
7357
|
+
4. **aesthetics** (25%): Professional, polished appearance? Consistent color palette? Good use of whitespace \u2014 not too sparse, not too cluttered? Cards, shadows, and borders used effectively? Does it look like something a designer would approve? Would you be comfortable showing this to a client?
|
|
7358
|
+
|
|
7359
|
+
## Scoring Guide
|
|
7360
|
+
- 90-100: Production-ready. Would ship to real users. Polished layout, clear hierarchy, professional aesthetics.
|
|
7361
|
+
- 80-89: Good quality. Minor improvements needed (slightly tight spacing, one section could be better grouped).
|
|
7362
|
+
- 70-79: Acceptable but generic. Works correctly but lacks design polish or visual refinement.
|
|
7363
|
+
- 60-69: Below standard. Noticeable problems \u2014 cramped layout, poor hierarchy, or missing sections.
|
|
7364
|
+
- Below 60: Broken or fundamentally incomplete. Error messages visible, blank areas, or critical features missing.
|
|
7365
|
+
|
|
7366
|
+
## Important
|
|
7367
|
+
- Check the screenshot against the "Original Request" \u2014 does it actually deliver what was asked for?
|
|
7368
|
+
- Error messages like "Render error" or blank white space = rendering score 0
|
|
7369
|
+
- A component that renders but is just a wall of text with no structure should score low on layout and hierarchy
|
|
7370
|
+
|
|
7371
|
+
List AT MOST 6 issues, most severe first, one sentence each for "description" and "fix" \u2014 a longer list is cut off and lost.
|
|
7372
|
+
|
|
7373
|
+
Respond with ONLY a JSON object (no markdown, no explanation):
|
|
7374
|
+
{
|
|
7375
|
+
"completeness": <0-100>,
|
|
7376
|
+
"layout": <0-100>,
|
|
7377
|
+
"hierarchy": <0-100>,
|
|
7378
|
+
"aesthetics": <0-100>,
|
|
7379
|
+
"issues": [
|
|
7380
|
+
{ "dimension": "<dimension>", "severity": "<critical|major|minor>", "description": "<what's wrong>", "fix": "<specific fix>" }
|
|
7381
|
+
],
|
|
7382
|
+
"critique": "<2-3 sentences: what's good, what needs improvement, does it achieve the user's goal?>"
|
|
7383
|
+
}`;
|
|
7384
|
+
var VISUAL_JUDGE_MAX_OUTPUT_TOKENS = 4096;
|
|
7385
|
+
var VISUAL_JUDGE_PROMPT_VERSION = "v2-bounded-issues";
|
|
7386
|
+
var VISUAL_JUDGE_PROMPT_DIGEST = createHash("sha256").update(VISUAL_EVAL_PROMPT, "utf8").digest("hex");
|
|
7387
|
+
async function callMultimodalLLM(config, model, prompt, screenshot, originalPrompt, profileBlock = "") {
|
|
3309
7388
|
const userPrompt = `## Original Request
|
|
3310
7389
|
${originalPrompt}
|
|
3311
7390
|
|
|
3312
|
-
|
|
7391
|
+
` + (profileBlock.length > 0 ? `${profileBlock}
|
|
7392
|
+
|
|
7393
|
+
` : "") + "Evaluate the screenshot of the generated component.";
|
|
3313
7394
|
const agent = createVisionAgent({
|
|
3314
7395
|
provider: config.provider === "claude" ? "anthropic" : config.provider,
|
|
3315
7396
|
routeOverride: config.routeOverride,
|
|
@@ -3320,10 +7401,324 @@ Evaluate the screenshot of the generated component.`;
|
|
|
3320
7401
|
prompt,
|
|
3321
7402
|
userPrompt,
|
|
3322
7403
|
{ mediaType: "image/png", base64: screenshot.toString("base64") },
|
|
3323
|
-
|
|
7404
|
+
VISUAL_JUDGE_MAX_OUTPUT_TOKENS
|
|
7405
|
+
);
|
|
7406
|
+
}
|
|
7407
|
+
function judgeCountFor(config, canvas) {
|
|
7408
|
+
const k = Math.max(1, Math.floor(config.judgeK ?? 1));
|
|
7409
|
+
if (k === 1) return 1;
|
|
7410
|
+
return config.judgeKCanvases === void 0 || config.judgeKCanvases.includes(canvas) ? k : 1;
|
|
7411
|
+
}
|
|
7412
|
+
function medianOf(values) {
|
|
7413
|
+
const sorted = [...values].sort((a, b) => a - b);
|
|
7414
|
+
return sorted[Math.floor((sorted.length - 1) / 2)];
|
|
7415
|
+
}
|
|
7416
|
+
function populationSigma(values) {
|
|
7417
|
+
if (values.length < 2) return 0;
|
|
7418
|
+
const mean = values.reduce((a, b) => a + b, 0) / values.length;
|
|
7419
|
+
const variance = values.reduce((a, b) => a + (b - mean) ** 2, 0) / values.length;
|
|
7420
|
+
return Math.round(Math.sqrt(variance) * 10) / 10;
|
|
7421
|
+
}
|
|
7422
|
+
async function judgeAndParse(judge, config, model, screenshot, originalPrompt, profileBlock, canvas) {
|
|
7423
|
+
let firstReason;
|
|
7424
|
+
for (let attempt = 1; attempt <= 2; attempt++) {
|
|
7425
|
+
const response = await judge(config, model, VISUAL_EVAL_PROMPT, screenshot, originalPrompt, profileBlock);
|
|
7426
|
+
try {
|
|
7427
|
+
const result = parseVisualResponse(response.text, config.passThreshold);
|
|
7428
|
+
return { kind: "ok", result, inputTokens: response.inputTokens, outputTokens: response.outputTokens };
|
|
7429
|
+
} catch (e) {
|
|
7430
|
+
const salvaged = salvageTruncatedVisualAnswer(response.text, config.passThreshold);
|
|
7431
|
+
if (salvaged !== null) {
|
|
7432
|
+
console.warn(`[visual-eval] visual_judge_truncated${canvas ? ` canvas=${canvas}` : ""}: answer cut after ${response.text.length} chars \u2014 score recovered from the closed prefix, issues list partial`);
|
|
7433
|
+
return { kind: "ok", result: salvaged, inputTokens: response.inputTokens, outputTokens: response.outputTokens };
|
|
7434
|
+
}
|
|
7435
|
+
const reason = `judge answer unparsable: ${e instanceof Error ? e.message : String(e)}`;
|
|
7436
|
+
if (attempt === 1) {
|
|
7437
|
+
firstReason = reason;
|
|
7438
|
+
console.warn(`[visual-eval] visual_judge_retry${canvas ? ` canvas=${canvas}` : ""}: ${reason}`);
|
|
7439
|
+
} else {
|
|
7440
|
+
console.warn(`[visual-eval] visual_judge_retry failed again${canvas ? ` canvas=${canvas}` : ""}: ${reason}`);
|
|
7441
|
+
}
|
|
7442
|
+
}
|
|
7443
|
+
}
|
|
7444
|
+
return { kind: "unparsable", reason: firstReason ?? "judge answer unparsable" };
|
|
7445
|
+
}
|
|
7446
|
+
async function runVisualEvaluation(context, config, deps = {}) {
|
|
7447
|
+
return (await runVisualEvaluationDetailed(context, config, deps)).result;
|
|
7448
|
+
}
|
|
7449
|
+
async function runVisualEvaluationDetailed(context, config, deps = {}) {
|
|
7450
|
+
const startTime = Date.now();
|
|
7451
|
+
const judge = deps.judge ?? callMultimodalLLM;
|
|
7452
|
+
const designSrc = config.designSrcDir ?? resolve(resolveDesignPackageDir(), "src");
|
|
7453
|
+
const design = judgeDesignIdentity(designSrc);
|
|
7454
|
+
const stamp = (r) => ({
|
|
7455
|
+
...r,
|
|
7456
|
+
...design !== null ? { design } : {},
|
|
7457
|
+
...config.themeMode !== void 0 ? { themeMode: config.themeMode } : {}
|
|
7458
|
+
});
|
|
7459
|
+
let bundledCode;
|
|
7460
|
+
try {
|
|
7461
|
+
bundledCode = await bundleForRendering(context.compiledCode, config.sampleProps ?? {}, designSrc);
|
|
7462
|
+
} catch (e) {
|
|
7463
|
+
const unavailableReason = `bundle failed: ${e instanceof Error ? e.message : String(e)}`;
|
|
7464
|
+
console.warn(`[visual-eval] ${unavailableReason}`);
|
|
7465
|
+
return { result: null, unavailableReason };
|
|
7466
|
+
}
|
|
7467
|
+
console.log(`[visual-eval] bundled: ${bundledCode.length}B (${Date.now() - startTime}ms)`);
|
|
7468
|
+
const html = buildRenderHTML(bundledCode, context.cssTokens);
|
|
7469
|
+
const model = config.model ?? getDefaultVisualModel(config.provider);
|
|
7470
|
+
if (config.canvases !== void 0 && config.canvases.length > 0) {
|
|
7471
|
+
const perCanvas = [];
|
|
7472
|
+
const perCanvasResults = [];
|
|
7473
|
+
for (const canvas of config.canvases) {
|
|
7474
|
+
const viewport = CANVAS_VIEWPORTS[canvas];
|
|
7475
|
+
const policy = canvasFitPolicy(canvas);
|
|
7476
|
+
const fit = canvasFit(canvas);
|
|
7477
|
+
const canvasHtml = fit !== void 0 ? buildRenderHTML(bundledCode, context.cssTokens, fit) : html;
|
|
7478
|
+
const attempt2 = await captureScreenshotDetailed(canvasHtml, viewport, deps, policy.capture);
|
|
7479
|
+
const screenshot2 = attempt2.png;
|
|
7480
|
+
if (!screenshot2) {
|
|
7481
|
+
const unavailableReason = attempt2.reason ?? "no browser available";
|
|
7482
|
+
console.warn(`[visual-eval] ${unavailableReason} at canvas ${canvas} \u2014 skipping visual evaluation`);
|
|
7483
|
+
return { result: null, unavailableReason, canvas };
|
|
7484
|
+
}
|
|
7485
|
+
const k = judgeCountFor(config, canvas);
|
|
7486
|
+
const profileBlock = buildStylingProfileJudgeBlock(context.profile);
|
|
7487
|
+
const answers = await Promise.all(
|
|
7488
|
+
Array.from({ length: k }, () => judgeAndParse(judge, config, model, screenshot2, context.originalPrompt, profileBlock, canvas))
|
|
7489
|
+
);
|
|
7490
|
+
const parsed = answers.filter((a) => a.kind === "ok");
|
|
7491
|
+
if (parsed.length === 0) {
|
|
7492
|
+
const first = answers.find((a) => a.kind === "unparsable");
|
|
7493
|
+
return { result: null, unavailableReason: first?.reason ?? "judge answer unparsable", canvas };
|
|
7494
|
+
}
|
|
7495
|
+
const samples = parsed.map((a) => a.result.finalScore);
|
|
7496
|
+
const median = medianOf(samples);
|
|
7497
|
+
const representative = parsed[samples.indexOf(median)];
|
|
7498
|
+
const result2 = representative.result;
|
|
7499
|
+
result2.finalScore = median;
|
|
7500
|
+
result2.passed = median >= config.passThreshold;
|
|
7501
|
+
result2.inputTokens = parsed.reduce((sum, a) => sum + a.inputTokens, 0);
|
|
7502
|
+
result2.outputTokens = parsed.reduce((sum, a) => sum + a.outputTokens, 0);
|
|
7503
|
+
const response2 = { inputTokens: result2.inputTokens, outputTokens: result2.outputTokens };
|
|
7504
|
+
const judgeRecord = {
|
|
7505
|
+
k,
|
|
7506
|
+
rule: "median",
|
|
7507
|
+
samples,
|
|
7508
|
+
sigma: populationSigma(samples),
|
|
7509
|
+
notes: parsed.map((a) => a.result.critique ?? "")
|
|
7510
|
+
};
|
|
7511
|
+
const contentHeight = attempt2.contentHeight;
|
|
7512
|
+
const overflow = contentHeight !== null && contentHeight > viewport.height;
|
|
7513
|
+
if (contentHeight !== null && contentHeight > viewport.height && policy.overflow !== "none") {
|
|
7514
|
+
result2.issues.push(canvasOverflowIssue(canvas, viewport, contentHeight, policy.overflow));
|
|
7515
|
+
if (policy.overflow === "fail") result2.passed = false;
|
|
7516
|
+
}
|
|
7517
|
+
perCanvasResults.push(result2);
|
|
7518
|
+
perCanvas.push({
|
|
7519
|
+
canvas,
|
|
7520
|
+
viewport,
|
|
7521
|
+
score: result2.finalScore,
|
|
7522
|
+
passed: result2.passed,
|
|
7523
|
+
screenshotPng: screenshot2,
|
|
7524
|
+
contentHeight,
|
|
7525
|
+
overflow,
|
|
7526
|
+
judge: judgeRecord,
|
|
7527
|
+
...fit !== void 0 ? { fit } : {}
|
|
7528
|
+
});
|
|
7529
|
+
console.log(
|
|
7530
|
+
`[visual-eval] canvas=${canvas} ${viewport.width}\xD7${viewport.height} score=${result2.finalScore}${k > 1 ? ` (median of ${judgeRecord.samples.length}/${k}: ${judgeRecord.samples.join(",")} \u03C3=${judgeRecord.sigma})` : ""} ${result2.passed ? "pass" : "FAIL"} | content=${contentHeight ?? "?"}px${overflow ? ` OVERFLOW (${policy.overflow})` : ""} | in=${response2.inputTokens} out=${response2.outputTokens}`
|
|
7531
|
+
);
|
|
7532
|
+
}
|
|
7533
|
+
const aggregate = aggregateCanvasResults(perCanvas, perCanvasResults);
|
|
7534
|
+
const elapsed2 = Date.now() - startTime;
|
|
7535
|
+
console.log(
|
|
7536
|
+
`[visual-eval] score=${aggregate.finalScore} (mean of ${perCanvas.length} canvases; ${aggregate.passed ? "every canvas passed" : `${perCanvas.filter((c) => !c.passed).length} failed`}) (${elapsed2}ms)`
|
|
7537
|
+
);
|
|
7538
|
+
return { result: stamp(aggregate) };
|
|
7539
|
+
}
|
|
7540
|
+
const attempt = await captureScreenshotDetailed(html, config.viewport, deps);
|
|
7541
|
+
const screenshot = attempt.png;
|
|
7542
|
+
if (!screenshot) {
|
|
7543
|
+
const unavailableReason = attempt.reason ?? "no browser available";
|
|
7544
|
+
console.warn(`[visual-eval] ${unavailableReason} \u2014 skipping visual evaluation`);
|
|
7545
|
+
return { result: null, unavailableReason };
|
|
7546
|
+
}
|
|
7547
|
+
console.log(`[visual-eval] screenshot: ${screenshot.length}B (${Date.now() - startTime}ms)`);
|
|
7548
|
+
const answer = await judgeAndParse(
|
|
7549
|
+
judge,
|
|
7550
|
+
config,
|
|
7551
|
+
model,
|
|
7552
|
+
screenshot,
|
|
7553
|
+
context.originalPrompt,
|
|
7554
|
+
buildStylingProfileJudgeBlock(context.profile)
|
|
7555
|
+
);
|
|
7556
|
+
if (answer.kind === "unparsable") {
|
|
7557
|
+
return { result: null, unavailableReason: answer.reason };
|
|
7558
|
+
}
|
|
7559
|
+
const result = answer.result;
|
|
7560
|
+
result.inputTokens = answer.inputTokens;
|
|
7561
|
+
result.outputTokens = answer.outputTokens;
|
|
7562
|
+
const response = { inputTokens: answer.inputTokens, outputTokens: answer.outputTokens };
|
|
7563
|
+
const elapsed = Date.now() - startTime;
|
|
7564
|
+
console.log(`[visual-eval] score=${result.finalScore} (${elapsed}ms) | in=${response.inputTokens} out=${response.outputTokens}`);
|
|
7565
|
+
return { result: stamp(result) };
|
|
7566
|
+
}
|
|
7567
|
+
function aggregateCanvasResults(perCanvas, results) {
|
|
7568
|
+
const n = results.length;
|
|
7569
|
+
const mean = (pick) => Math.round(results.reduce((sum, r) => sum + pick(r), 0) / n);
|
|
7570
|
+
const dimensions = {
|
|
7571
|
+
completeness: mean((r) => r.dimensions.completeness),
|
|
7572
|
+
visualPolish: mean((r) => r.dimensions.visualPolish),
|
|
7573
|
+
interactivity: mean((r) => r.dimensions.interactivity),
|
|
7574
|
+
accessibility: mean((r) => r.dimensions.accessibility),
|
|
7575
|
+
codeQuality: mean((r) => r.dimensions.codeQuality)
|
|
7576
|
+
};
|
|
7577
|
+
const issues = [];
|
|
7578
|
+
const critiques = [];
|
|
7579
|
+
let inputTokens = 0;
|
|
7580
|
+
let outputTokens = 0;
|
|
7581
|
+
results.forEach((r, i) => {
|
|
7582
|
+
const canvas = perCanvas[i].canvas;
|
|
7583
|
+
for (const issue of r.issues) issues.push({ ...issue, description: `[${canvas}] ${issue.description}` });
|
|
7584
|
+
if (r.critique) critiques.push(`${canvas}: ${r.critique}`);
|
|
7585
|
+
inputTokens += r.inputTokens ?? 0;
|
|
7586
|
+
outputTokens += r.outputTokens ?? 0;
|
|
7587
|
+
});
|
|
7588
|
+
return {
|
|
7589
|
+
passed: perCanvas.every((c) => c.passed),
|
|
7590
|
+
finalScore: mean((r) => r.finalScore),
|
|
7591
|
+
dimensions,
|
|
7592
|
+
issues,
|
|
7593
|
+
...critiques.length > 0 ? { critique: critiques.join("\n") } : {},
|
|
7594
|
+
inputTokens,
|
|
7595
|
+
outputTokens,
|
|
7596
|
+
canvases: [...perCanvas]
|
|
7597
|
+
};
|
|
7598
|
+
}
|
|
7599
|
+
function summarizeVisualResult(result) {
|
|
7600
|
+
if (result.canvases === void 0) return void 0;
|
|
7601
|
+
const canvases = result.canvases.map((c) => ({
|
|
7602
|
+
canvas: c.canvas,
|
|
7603
|
+
viewport: c.viewport,
|
|
7604
|
+
score: c.score,
|
|
7605
|
+
passed: c.passed,
|
|
7606
|
+
contentHeight: c.contentHeight,
|
|
7607
|
+
overflow: c.overflow,
|
|
7608
|
+
judge: c.judge,
|
|
7609
|
+
...c.fit !== void 0 ? { fit: c.fit } : {}
|
|
7610
|
+
}));
|
|
7611
|
+
return {
|
|
7612
|
+
score: result.finalScore,
|
|
7613
|
+
passed: result.passed,
|
|
7614
|
+
canvases,
|
|
7615
|
+
...result.design !== void 0 ? { design: result.design } : {},
|
|
7616
|
+
...result.themeMode !== void 0 ? { themeMode: result.themeMode } : {}
|
|
7617
|
+
};
|
|
7618
|
+
}
|
|
7619
|
+
function salvageTruncatedVisualAnswer(text, passThreshold) {
|
|
7620
|
+
const dim = (name) => {
|
|
7621
|
+
const m = text.match(new RegExp(`"${name}"\\s*:\\s*(\\d+(?:\\.\\d+)?)`));
|
|
7622
|
+
return m ? Number(m[1]) : null;
|
|
7623
|
+
};
|
|
7624
|
+
const completeness = dim("completeness");
|
|
7625
|
+
const layout = dim("layout");
|
|
7626
|
+
const hierarchy = dim("hierarchy");
|
|
7627
|
+
const aesthetics = dim("aesthetics");
|
|
7628
|
+
if (completeness === null || layout === null || hierarchy === null || aesthetics === null) return null;
|
|
7629
|
+
const issues = [];
|
|
7630
|
+
const issuesAt = text.indexOf('"issues"');
|
|
7631
|
+
if (issuesAt >= 0) {
|
|
7632
|
+
for (const m of text.slice(issuesAt).matchAll(/\{[^{}]*\}/g)) {
|
|
7633
|
+
try {
|
|
7634
|
+
const o = JSON.parse(m[0]);
|
|
7635
|
+
if (typeof o.description === "string") {
|
|
7636
|
+
issues.push({
|
|
7637
|
+
dimension: typeof o.dimension === "string" ? o.dimension : "layout",
|
|
7638
|
+
severity: typeof o.severity === "string" ? o.severity : "minor",
|
|
7639
|
+
description: o.description,
|
|
7640
|
+
fix: typeof o.fix === "string" ? o.fix : ""
|
|
7641
|
+
});
|
|
7642
|
+
}
|
|
7643
|
+
} catch {
|
|
7644
|
+
}
|
|
7645
|
+
}
|
|
7646
|
+
}
|
|
7647
|
+
const rebuilt = JSON.stringify({
|
|
7648
|
+
completeness,
|
|
7649
|
+
layout,
|
|
7650
|
+
hierarchy,
|
|
7651
|
+
aesthetics,
|
|
7652
|
+
issues,
|
|
7653
|
+
critique: `[truncated judge answer \u2014 score recovered from the closed prefix; ${issues.length} issue(s) kept, the rest and the critique were cut]`
|
|
7654
|
+
});
|
|
7655
|
+
return parseVisualResponse(rebuilt, passThreshold);
|
|
7656
|
+
}
|
|
7657
|
+
function parseVisualResponse(text, passThreshold) {
|
|
7658
|
+
const jsonMatch = text.match(/\{[\s\S]*\}/);
|
|
7659
|
+
if (!jsonMatch) {
|
|
7660
|
+
throw new Error("Visual evaluator did not return valid JSON: " + text.slice(0, 200));
|
|
7661
|
+
}
|
|
7662
|
+
const raw = JSON.parse(jsonMatch[0]);
|
|
7663
|
+
const completeness = raw.completeness ?? 0;
|
|
7664
|
+
const layout = raw.layout ?? 0;
|
|
7665
|
+
const hierarchy = raw.hierarchy ?? 0;
|
|
7666
|
+
const aesthetics = raw.aesthetics ?? 0;
|
|
7667
|
+
const finalScore = Math.round(
|
|
7668
|
+
completeness * 0.25 + layout * 0.25 + hierarchy * 0.25 + aesthetics * 0.25
|
|
3324
7669
|
);
|
|
7670
|
+
const dimensions = {
|
|
7671
|
+
completeness,
|
|
7672
|
+
visualPolish: aesthetics,
|
|
7673
|
+
interactivity: 0,
|
|
7674
|
+
// can't assess interactivity from screenshot
|
|
7675
|
+
accessibility: 0,
|
|
7676
|
+
// can't assess a11y from screenshot
|
|
7677
|
+
codeQuality: 0
|
|
7678
|
+
// can't assess code from screenshot
|
|
7679
|
+
};
|
|
7680
|
+
const issues = (raw.issues || []).map((i) => ({
|
|
7681
|
+
dimension: i.dimension || "visual",
|
|
7682
|
+
severity: i.severity || "minor",
|
|
7683
|
+
description: i.description || "",
|
|
7684
|
+
fix: i.fix || ""
|
|
7685
|
+
}));
|
|
7686
|
+
return {
|
|
7687
|
+
passed: finalScore >= passThreshold,
|
|
7688
|
+
finalScore,
|
|
7689
|
+
dimensions,
|
|
7690
|
+
issues,
|
|
7691
|
+
critique: raw.critique
|
|
7692
|
+
};
|
|
7693
|
+
}
|
|
7694
|
+
function getDefaultVisualModel(provider) {
|
|
7695
|
+
switch (provider) {
|
|
7696
|
+
case "claude":
|
|
7697
|
+
return "claude-haiku-4-5-20251001";
|
|
7698
|
+
case "google":
|
|
7699
|
+
return "gemini-3-flash-preview";
|
|
7700
|
+
}
|
|
7701
|
+
}
|
|
7702
|
+
async function runVisualEval(context, config) {
|
|
7703
|
+
const result = await runVisualEvaluation(context, config);
|
|
7704
|
+
if (!result) return { issues: [] };
|
|
7705
|
+
const issues = (result.issues || []).map((issue) => ({
|
|
7706
|
+
tier: 2,
|
|
7707
|
+
result: issue.severity === "critical" ? "fail" : "warn",
|
|
7708
|
+
category: "visual",
|
|
7709
|
+
subcategory: issue.dimension,
|
|
7710
|
+
severity: issue.severity === "critical" ? "critical" : "major",
|
|
7711
|
+
description: issue.description,
|
|
7712
|
+
fix: issue.fix || ""
|
|
7713
|
+
}));
|
|
7714
|
+
const summary = summarizeVisualResult(result);
|
|
7715
|
+
return summary === void 0 ? { issues } : { issues, summary };
|
|
7716
|
+
}
|
|
7717
|
+
function cssTokensForAppTheme(theme, mode = "light") {
|
|
7718
|
+
if (theme === void 0) return getCssTokens(mode);
|
|
7719
|
+
return composeThemeCss({ layer: "page", mode: theme.mode ?? mode, appTheme: theme });
|
|
3325
7720
|
}
|
|
3326
7721
|
|
|
3327
|
-
export { CRITERIA, DEFAULT_EVAL_MAX_ROUNDS, DEFAULT_QUALITY_CONFIG, LLM_EVAL_STATIC_CRITERIA, MAX_EVAL_ROUNDS_HARD_LIMIT, buildCodingCriteriaSummary, buildFixPrompt, callMultimodalLLM, computeEvaluationScore, createEvaluationToolsServer, extractCompiledCode, extractCompiledCodeFromMessage, extractEvalResult, extractSourceCode, extractSourceCodeFromMessage, extractToolResultTexts, getActionableIssues, getCriteriaByPriority, getCriterionById, getEvaluatorSystemPrompt, getLLMCriteria, isBlocked, matches, notApplicableCoverage, priorityForIssue, runAxisChecks, runEvaluation, runEvaluationLoop };
|
|
7722
|
+
export { CANVAS_BREAKPOINTS, CANVAS_CLASSES, CANVAS_DESCRIPTORS, CANVAS_VIEWPORTS, CONTENT_HEIGHT_EXPRESSION, CRITERIA, DEFAULT_EVAL_MAX_ROUNDS, DEFAULT_QUALITY_CONFIG, LLM_EVAL_STATIC_CRITERIA, MAX_EVAL_ROUNDS_HARD_LIMIT, VISUAL_EVAL_PROMPT, VISUAL_JUDGE_MAX_OUTPUT_TOKENS, VISUAL_JUDGE_PROMPT_DIGEST, VISUAL_JUDGE_PROMPT_VERSION, buildCodingCriteriaSummary, buildFixPrompt, callMultimodalLLM, canvasDisplayModeForShell, canvasFitPolicy, canvasForRendering, canvasForViewportWidth, canvasOverflowIssue, captureScreenshot, captureScreenshotDetailed, computeEvaluationScore, createEvaluationToolsServer, criteriaFor, cssTokensForAppTheme, describeCanvas, designTreeSha256, extractCompiledCode, extractCompiledCodeFromMessage, extractEvalResult, extractSourceCode, extractSourceCodeFromMessage, extractToolResultTexts, getActionableIssues, getCriteriaByPriority, getCriterionById, getEvaluatorSystemPrompt, getLLMCriteria, isBlocked, judgeDesignIdentity, matches, notApplicableCoverage, priorityForIssue, resetJudgeDesignIdentityCache, resolveDesignPackageDir, resolveLaunchOptions, runAxisChecks, runEvaluation, runEvaluationLoop, runVisualEval, runVisualEvaluation, runVisualEvaluationDetailed, summarizeVisualResult };
|
|
3328
7723
|
//# sourceMappingURL=index.js.map
|
|
3329
7724
|
//# sourceMappingURL=index.js.map
|