@blue-quickjs/quickjs-runtime 0.1.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/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/lib/deterministic-init.d.ts +13 -0
- package/dist/lib/deterministic-init.d.ts.map +1 -0
- package/dist/lib/deterministic-init.js +166 -0
- package/dist/lib/evaluate-errors.d.ts +38 -0
- package/dist/lib/evaluate-errors.d.ts.map +1 -0
- package/dist/lib/evaluate-errors.js +88 -0
- package/dist/lib/evaluate.d.ts +83 -0
- package/dist/lib/evaluate.d.ts.map +1 -0
- package/dist/lib/evaluate.js +284 -0
- package/dist/lib/hex-utils.d.ts +5 -0
- package/dist/lib/hex-utils.d.ts.map +1 -0
- package/dist/lib/hex-utils.js +24 -0
- package/dist/lib/host-dispatcher.d.ts +62 -0
- package/dist/lib/host-dispatcher.d.ts.map +1 -0
- package/dist/lib/host-dispatcher.js +397 -0
- package/dist/lib/quickjs-runtime.d.ts +35 -0
- package/dist/lib/quickjs-runtime.d.ts.map +1 -0
- package/dist/lib/quickjs-runtime.js +143 -0
- package/dist/lib/runtime.d.ts +33 -0
- package/dist/lib/runtime.d.ts.map +1 -0
- package/dist/lib/runtime.js +56 -0
- package/package.json +41 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { DV_LIMIT_DEFAULTS, decodeDv, } from '@blue-quickjs/dv';
|
|
2
|
+
import { initializeDeterministicVm } from './deterministic-init.js';
|
|
3
|
+
import { validateInputEnvelope, validateProgramArtifact, } from './quickjs-runtime.js';
|
|
4
|
+
import { createRuntime, } from './runtime.js';
|
|
5
|
+
import { createInvalidOutputError, mapVmError, } from './evaluate-errors.js';
|
|
6
|
+
import { parseHexToBytes } from './hex-utils.js';
|
|
7
|
+
const HOST_TAPE_MAX_CAPACITY = 1024;
|
|
8
|
+
export async function evaluate(options) {
|
|
9
|
+
const program = validateProgramArtifact(options.program);
|
|
10
|
+
const input = validateInputEnvelope(options.input, options.inputValidation);
|
|
11
|
+
const runtime = await createRuntime({
|
|
12
|
+
manifest: options.manifest,
|
|
13
|
+
handlers: options.handlers,
|
|
14
|
+
variant: options.variant,
|
|
15
|
+
buildType: options.buildType,
|
|
16
|
+
metadata: options.metadata,
|
|
17
|
+
wasmBinary: options.wasmBinary,
|
|
18
|
+
dvLimits: options.dvLimits,
|
|
19
|
+
expectedAbiId: program.abiId,
|
|
20
|
+
expectedAbiVersion: program.abiVersion,
|
|
21
|
+
});
|
|
22
|
+
assertEngineBuildHash(program, runtime);
|
|
23
|
+
const vm = initializeDeterministicVm(runtime, program, input, options.gasLimit);
|
|
24
|
+
if (options.tape) {
|
|
25
|
+
const capacity = options.tape.capacity ?? 128;
|
|
26
|
+
if (!Number.isInteger(capacity) || capacity < 0) {
|
|
27
|
+
throw new Error('tape capacity must be a non-negative integer');
|
|
28
|
+
}
|
|
29
|
+
if (capacity > HOST_TAPE_MAX_CAPACITY) {
|
|
30
|
+
throw new Error(`tape capacity exceeds max (${HOST_TAPE_MAX_CAPACITY}); received ${capacity}`);
|
|
31
|
+
}
|
|
32
|
+
vm.enableTape(capacity);
|
|
33
|
+
}
|
|
34
|
+
if (options.gasTrace) {
|
|
35
|
+
vm.enableGasTrace(true);
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const raw = vm.eval(program.code);
|
|
39
|
+
const parsed = parseEvalOutput(raw);
|
|
40
|
+
const tape = options.tape ? parseTape(vm.readTape()) : undefined;
|
|
41
|
+
const trace = options.gasTrace
|
|
42
|
+
? parseGasTrace(vm.readGasTrace())
|
|
43
|
+
: undefined;
|
|
44
|
+
if (parsed.kind === 'error') {
|
|
45
|
+
const error = mapVmError(parsed.payload, runtime.manifest);
|
|
46
|
+
return {
|
|
47
|
+
ok: false,
|
|
48
|
+
type: 'vm-error',
|
|
49
|
+
message: error.message,
|
|
50
|
+
error,
|
|
51
|
+
gasUsed: parsed.gasUsed,
|
|
52
|
+
gasRemaining: parsed.gasRemaining,
|
|
53
|
+
raw,
|
|
54
|
+
tape,
|
|
55
|
+
gasTrace: trace,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const decoded = decodeResultPayload(parsed.payload, options.outputDvLimits);
|
|
59
|
+
if (decoded.kind === 'error') {
|
|
60
|
+
const error = createInvalidOutputError(decoded.message, decoded.cause);
|
|
61
|
+
return {
|
|
62
|
+
ok: false,
|
|
63
|
+
type: 'invalid-output',
|
|
64
|
+
message: error.message,
|
|
65
|
+
error,
|
|
66
|
+
gasUsed: parsed.gasUsed,
|
|
67
|
+
gasRemaining: parsed.gasRemaining,
|
|
68
|
+
raw,
|
|
69
|
+
tape,
|
|
70
|
+
gasTrace: trace,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
ok: true,
|
|
75
|
+
value: decoded.value,
|
|
76
|
+
gasUsed: parsed.gasUsed,
|
|
77
|
+
gasRemaining: parsed.gasRemaining,
|
|
78
|
+
raw,
|
|
79
|
+
tape,
|
|
80
|
+
gasTrace: trace,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
finally {
|
|
84
|
+
vm.dispose();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function parseEvalOutput(raw) {
|
|
88
|
+
const normalized = raw.trim();
|
|
89
|
+
let kind;
|
|
90
|
+
if (normalized.startsWith('RESULT')) {
|
|
91
|
+
kind = 'RESULT';
|
|
92
|
+
}
|
|
93
|
+
else if (normalized.startsWith('ERROR')) {
|
|
94
|
+
kind = 'ERROR';
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
throw new Error(`Unexpected VM output prefix: ${normalized}`);
|
|
98
|
+
}
|
|
99
|
+
const withoutKind = normalized.slice(kind.length).trimStart();
|
|
100
|
+
const trailerMarker = ' GAS remaining=';
|
|
101
|
+
const usedMarker = ' used=';
|
|
102
|
+
const trailerIdx = withoutKind.lastIndexOf(trailerMarker);
|
|
103
|
+
if (trailerIdx < 0) {
|
|
104
|
+
throw new Error(`Missing gas trailer in VM output: ${normalized}`);
|
|
105
|
+
}
|
|
106
|
+
const payload = withoutKind.slice(0, trailerIdx).trimEnd();
|
|
107
|
+
const trailer = withoutKind.slice(trailerIdx + trailerMarker.length);
|
|
108
|
+
const usedIdx = trailer.lastIndexOf(usedMarker);
|
|
109
|
+
if (usedIdx < 0) {
|
|
110
|
+
throw new Error(`Missing used= trailer in VM output: ${normalized}`);
|
|
111
|
+
}
|
|
112
|
+
const remainingStr = trailer.slice(0, usedIdx).trim();
|
|
113
|
+
const usedStr = trailer.slice(usedIdx + usedMarker.length).trim();
|
|
114
|
+
return {
|
|
115
|
+
kind: kind === 'RESULT' ? 'result' : 'error',
|
|
116
|
+
payload,
|
|
117
|
+
gasRemaining: parseUint64(remainingStr, 'gasRemaining'),
|
|
118
|
+
gasUsed: parseUint64(usedStr, 'gasUsed'),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
function decodeResultPayload(payload, limits) {
|
|
122
|
+
const dvLimits = normalizeDvLimits(limits);
|
|
123
|
+
let bytes;
|
|
124
|
+
try {
|
|
125
|
+
bytes = parseHexToBytes(payload, dvLimits.maxEncodedBytes);
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
return {
|
|
129
|
+
kind: 'error',
|
|
130
|
+
message: `VM returned non-hex DV payload: ${err instanceof Error ? err.message : String(err)}`,
|
|
131
|
+
cause: err,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const value = decodeDv(bytes, { limits: dvLimits });
|
|
136
|
+
return { kind: 'ok', value };
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
return {
|
|
140
|
+
kind: 'error',
|
|
141
|
+
message: `VM returned non-DV value: ${err instanceof Error ? err.message : String(err)}`,
|
|
142
|
+
cause: err,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function parseTape(raw) {
|
|
147
|
+
const parsed = parseJson(raw, 'tape');
|
|
148
|
+
if (!Array.isArray(parsed)) {
|
|
149
|
+
throw new Error('tape payload is not an array');
|
|
150
|
+
}
|
|
151
|
+
return parsed.map((record, idx) => {
|
|
152
|
+
if (record === null || typeof record !== 'object') {
|
|
153
|
+
throw new Error(`tape record ${idx} is not an object`);
|
|
154
|
+
}
|
|
155
|
+
const fnId = expectUint32(record.fnId, `tape[${idx}].fnId`);
|
|
156
|
+
const reqLen = expectUint32(record.reqLen, `tape[${idx}].reqLen`);
|
|
157
|
+
const respLen = expectUint32(record.respLen, `tape[${idx}].respLen`);
|
|
158
|
+
const units = expectUint32(record.units, `tape[${idx}].units`);
|
|
159
|
+
const gasPre = expectBigIntString(record.gasPre, `tape[${idx}].gasPre`);
|
|
160
|
+
const gasPost = expectBigIntString(record.gasPost, `tape[${idx}].gasPost`);
|
|
161
|
+
const isError = Boolean(record.isError);
|
|
162
|
+
const chargeFailed = Boolean(record.chargeFailed);
|
|
163
|
+
const reqHash = expectHex(record.reqHash, `tape[${idx}].reqHash`, 64);
|
|
164
|
+
const respHash = expectHex(record.respHash, `tape[${idx}].respHash`, 64);
|
|
165
|
+
return {
|
|
166
|
+
fnId,
|
|
167
|
+
reqLen,
|
|
168
|
+
respLen,
|
|
169
|
+
units,
|
|
170
|
+
gasPre,
|
|
171
|
+
gasPost,
|
|
172
|
+
isError,
|
|
173
|
+
chargeFailed,
|
|
174
|
+
reqHash,
|
|
175
|
+
respHash,
|
|
176
|
+
};
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
function parseGasTrace(raw) {
|
|
180
|
+
const obj = expectRecord(parseJson(raw, 'gasTrace'), 'gasTrace');
|
|
181
|
+
return {
|
|
182
|
+
opcodeCount: expectBigIntString(obj.opcodeCount, 'gasTrace.opcodeCount'),
|
|
183
|
+
opcodeGas: expectBigIntString(obj.opcodeGas, 'gasTrace.opcodeGas'),
|
|
184
|
+
arrayCbBaseCount: expectBigIntString(obj.arrayCbBaseCount, 'gasTrace.arrayCbBaseCount'),
|
|
185
|
+
arrayCbBaseGas: expectBigIntString(obj.arrayCbBaseGas, 'gasTrace.arrayCbBaseGas'),
|
|
186
|
+
arrayCbPerElCount: expectBigIntString(obj.arrayCbPerElCount, 'gasTrace.arrayCbPerElCount'),
|
|
187
|
+
arrayCbPerElGas: expectBigIntString(obj.arrayCbPerElGas, 'gasTrace.arrayCbPerElGas'),
|
|
188
|
+
allocationCount: expectBigIntString(obj.allocationCount, 'gasTrace.allocationCount'),
|
|
189
|
+
allocationBytes: expectBigIntString(obj.allocationBytes, 'gasTrace.allocationBytes'),
|
|
190
|
+
allocationGas: expectBigIntString(obj.allocationGas, 'gasTrace.allocationGas'),
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function parseJson(raw, label) {
|
|
194
|
+
try {
|
|
195
|
+
return JSON.parse(raw);
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
throw new Error(`${label} payload is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
function expectUint32(value, path) {
|
|
202
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value < 0) {
|
|
203
|
+
throw new Error(`${path} must be a non-negative integer`);
|
|
204
|
+
}
|
|
205
|
+
if (value > 0xffffffff) {
|
|
206
|
+
throw new Error(`${path} exceeds uint32`);
|
|
207
|
+
}
|
|
208
|
+
return value;
|
|
209
|
+
}
|
|
210
|
+
function expectBigIntString(value, path) {
|
|
211
|
+
if (typeof value === 'bigint') {
|
|
212
|
+
if (value < 0n) {
|
|
213
|
+
throw new Error(`${path} must be non-negative`);
|
|
214
|
+
}
|
|
215
|
+
return value;
|
|
216
|
+
}
|
|
217
|
+
if (typeof value !== 'string') {
|
|
218
|
+
throw new Error(`${path} must be a string`);
|
|
219
|
+
}
|
|
220
|
+
try {
|
|
221
|
+
const parsed = BigInt(value);
|
|
222
|
+
if (parsed < 0n) {
|
|
223
|
+
throw new Error(`${path} must be non-negative`);
|
|
224
|
+
}
|
|
225
|
+
return parsed;
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
throw new Error(`${path} is not a valid bigint string: ${err instanceof Error ? err.message : String(err)}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
function expectHex(value, path, length) {
|
|
232
|
+
if (typeof value !== 'string') {
|
|
233
|
+
throw new Error(`${path} must be a hex string`);
|
|
234
|
+
}
|
|
235
|
+
if (value.length !== length) {
|
|
236
|
+
throw new Error(`${path} must be ${length} hex characters`);
|
|
237
|
+
}
|
|
238
|
+
if (!/^[0-9a-f]+$/.test(value)) {
|
|
239
|
+
throw new Error(`${path} must be lowercase hex`);
|
|
240
|
+
}
|
|
241
|
+
return value;
|
|
242
|
+
}
|
|
243
|
+
function expectRecord(value, path) {
|
|
244
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
245
|
+
throw new Error(`${path} payload is not an object`);
|
|
246
|
+
}
|
|
247
|
+
return value;
|
|
248
|
+
}
|
|
249
|
+
function normalizeDvLimits(overrides) {
|
|
250
|
+
return {
|
|
251
|
+
maxDepth: overrides?.maxDepth ?? DV_LIMIT_DEFAULTS.maxDepth,
|
|
252
|
+
maxEncodedBytes: overrides?.maxEncodedBytes ?? DV_LIMIT_DEFAULTS.maxEncodedBytes,
|
|
253
|
+
maxStringBytes: overrides?.maxStringBytes ?? DV_LIMIT_DEFAULTS.maxStringBytes,
|
|
254
|
+
maxArrayLength: overrides?.maxArrayLength ?? DV_LIMIT_DEFAULTS.maxArrayLength,
|
|
255
|
+
maxMapLength: overrides?.maxMapLength ?? DV_LIMIT_DEFAULTS.maxMapLength,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function parseUint64(text, label) {
|
|
259
|
+
try {
|
|
260
|
+
const value = BigInt(text);
|
|
261
|
+
if (value < 0n) {
|
|
262
|
+
throw new Error(`${label} must be non-negative`);
|
|
263
|
+
}
|
|
264
|
+
return value;
|
|
265
|
+
}
|
|
266
|
+
catch (err) {
|
|
267
|
+
const message = err instanceof Error ? err.message : `Invalid ${label} value`;
|
|
268
|
+
throw new Error(`${message}: ${text}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
function assertEngineBuildHash(program, runtime) {
|
|
272
|
+
if (!program.engineBuildHash) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
const runtimeHash = runtime.artifact.variantMetadata.engineBuildHash ??
|
|
276
|
+
runtime.metadata.engineBuildHash ??
|
|
277
|
+
null;
|
|
278
|
+
if (!runtimeHash) {
|
|
279
|
+
throw new Error('Engine build hash is unavailable; cannot verify program.engineBuildHash');
|
|
280
|
+
}
|
|
281
|
+
if (runtimeHash !== program.engineBuildHash) {
|
|
282
|
+
throw new Error(`engineBuildHash mismatch: program=${program.engineBuildHash} runtime=${runtimeHash}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hex-utils.d.ts","sourceRoot":"","sources":["../../src/lib/hex-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,QAAQ,CAAC,EAAE,MAAM,GAChB,UAAU,CAsBZ"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a lowercase hex string into a byte array with optional max-length enforcement.
|
|
3
|
+
*/
|
|
4
|
+
export function parseHexToBytes(payload, maxBytes) {
|
|
5
|
+
const normalized = payload.trim();
|
|
6
|
+
if (normalized.length === 0) {
|
|
7
|
+
throw new Error('payload is empty');
|
|
8
|
+
}
|
|
9
|
+
if (normalized.length % 2 !== 0) {
|
|
10
|
+
throw new Error('payload length is not even');
|
|
11
|
+
}
|
|
12
|
+
if (!/^[0-9a-f]+$/.test(normalized)) {
|
|
13
|
+
throw new Error('payload is not lowercase hex');
|
|
14
|
+
}
|
|
15
|
+
const byteLength = normalized.length / 2;
|
|
16
|
+
if (maxBytes !== undefined && byteLength > maxBytes) {
|
|
17
|
+
throw new Error(`payload exceeds maxBytes (${byteLength} > ${maxBytes})`);
|
|
18
|
+
}
|
|
19
|
+
const bytes = new Uint8Array(byteLength);
|
|
20
|
+
for (let i = 0; i < normalized.length; i += 2) {
|
|
21
|
+
bytes[i / 2] = parseInt(normalized.slice(i, i + 2), 16);
|
|
22
|
+
}
|
|
23
|
+
return bytes;
|
|
24
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type AbiManifest, type CanonicalAbiManifest } from '@blue-quickjs/abi-manifest';
|
|
2
|
+
import { type DV, type DvLimits } from '@blue-quickjs/dv';
|
|
3
|
+
export interface HostCallError {
|
|
4
|
+
code: string;
|
|
5
|
+
tag: string;
|
|
6
|
+
details?: DV;
|
|
7
|
+
}
|
|
8
|
+
export type HostCallResult<T extends DV | null = DV> = {
|
|
9
|
+
ok: T;
|
|
10
|
+
units: number;
|
|
11
|
+
} | {
|
|
12
|
+
err: HostCallError;
|
|
13
|
+
units: number;
|
|
14
|
+
};
|
|
15
|
+
export interface DocumentHostHandlers {
|
|
16
|
+
get(path: string): HostCallResult<DV>;
|
|
17
|
+
getCanonical(path: string): HostCallResult<DV>;
|
|
18
|
+
}
|
|
19
|
+
export interface EmitHostHandler {
|
|
20
|
+
emit(value: DV): HostCallResult<null>;
|
|
21
|
+
}
|
|
22
|
+
export interface HostDispatcherHandlers {
|
|
23
|
+
document: DocumentHostHandlers;
|
|
24
|
+
emit?: EmitHostHandler['emit'];
|
|
25
|
+
}
|
|
26
|
+
export interface HostDispatcherOptions {
|
|
27
|
+
/**
|
|
28
|
+
* Override DV limits applied to request decoding and response encoding.
|
|
29
|
+
*/
|
|
30
|
+
dvLimits?: Partial<DvLimits>;
|
|
31
|
+
/**
|
|
32
|
+
* Enforce a specific ABI identity (defaults to Host.v1) to avoid pairing the
|
|
33
|
+
* dispatcher with a mismatched manifest.
|
|
34
|
+
*/
|
|
35
|
+
expectedAbiId?: string;
|
|
36
|
+
expectedAbiVersion?: number;
|
|
37
|
+
}
|
|
38
|
+
export type HostDispatchResult = {
|
|
39
|
+
kind: 'response';
|
|
40
|
+
envelope: Uint8Array;
|
|
41
|
+
} | {
|
|
42
|
+
kind: 'fatal';
|
|
43
|
+
error: HostDispatcherError;
|
|
44
|
+
};
|
|
45
|
+
export type HostDispatcherErrorCode = 'UNKNOWN_FUNCTION' | 'INVALID_REQUEST' | 'INVALID_ARGUMENTS' | 'HANDLER_ERROR' | 'RESPONSE_LIMIT';
|
|
46
|
+
export declare class HostDispatcherError extends Error {
|
|
47
|
+
readonly code: HostDispatcherErrorCode;
|
|
48
|
+
constructor(code: HostDispatcherErrorCode, message: string, options?: {
|
|
49
|
+
cause?: unknown;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
export interface HostDispatcher {
|
|
53
|
+
readonly manifest: CanonicalAbiManifest;
|
|
54
|
+
dispatch(fnId: number, requestBytes: ArrayBufferView | ArrayBuffer): HostDispatchResult;
|
|
55
|
+
}
|
|
56
|
+
export interface HostCallMemory {
|
|
57
|
+
buffer: ArrayBuffer;
|
|
58
|
+
}
|
|
59
|
+
export type HostCallImport = (fnId: number, reqPtr: number, reqLen: number, respPtr: number, respCap: number) => number;
|
|
60
|
+
export declare function createHostDispatcher(manifest: AbiManifest, handlers: HostDispatcherHandlers, options?: HostDispatcherOptions): HostDispatcher;
|
|
61
|
+
export declare function createHostCallImport(dispatcher: HostDispatcher, memory: HostCallMemory): HostCallImport;
|
|
62
|
+
//# sourceMappingURL=host-dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host-dispatcher.d.ts","sourceRoot":"","sources":["../../src/lib/host-dispatcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,WAAW,EAChB,KAAK,oBAAoB,EAE1B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,KAAK,EAAE,EAEP,KAAK,QAAQ,EAKd,MAAM,kBAAkB,CAAC;AAK1B,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,EAAE,CAAC;CACd;AAED,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,EAAE,GAAG,IAAI,GAAG,EAAE,IAC/C;IAAE,EAAE,EAAE,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxB;IAAE,GAAG,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C,MAAM,WAAW,oBAAoB;IACnC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;IACtC,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAAC,EAAE,CAAC,CAAC;CAChD;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,KAAK,EAAE,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,IAAI,CAAC,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC7B;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,UAAU,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,mBAAmB,CAAA;CAAE,CAAC;AAElD,MAAM,MAAM,uBAAuB,GAC/B,kBAAkB,GAClB,iBAAiB,GACjB,mBAAmB,GACnB,eAAe,GACf,gBAAgB,CAAC;AAErB,qBAAa,mBAAoB,SAAQ,KAAK;aAE1B,IAAI,EAAE,uBAAuB;gBAA7B,IAAI,EAAE,uBAAuB,EAC7C,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAKhC;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;IACxC,QAAQ,CACN,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,eAAe,GAAG,WAAW,GAC1C,kBAAkB,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,MAAM,cAAc,GAAG,CAC3B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,KACZ,MAAM,CAAC;AAEZ,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,sBAAsB,EAChC,OAAO,CAAC,EAAE,qBAAqB,GAC9B,cAAc,CAuFhB;AAED,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,cAAc,EAC1B,MAAM,EAAE,cAAc,GACrB,cAAc,CA6ChB"}
|