@vesk/compiler 0.2.8 → 0.2.10
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/client-codegen.d.ts.map +1 -1
- package/dist/client-codegen.js +11 -1
- package/dist/ir-generator.d.ts.map +1 -1
- package/dist/ir-generator.js +99 -8
- package/dist/module-imports.d.ts +51 -0
- package/dist/module-imports.d.ts.map +1 -0
- package/dist/module-imports.js +715 -0
- package/dist/server-jsgen.d.ts.map +1 -1
- package/dist/server-jsgen.js +8 -3
- package/dist/server-render.d.ts.map +1 -1
- package/dist/server-render.js +16 -2
- package/dist/tokens.d.ts.map +1 -1
- package/dist/tokens.js +24 -1
- package/dist/typecheck.d.ts +1 -1
- package/dist/typecheck.d.ts.map +1 -1
- package/dist/typecheck.js +5 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/vesk-plugin.d.ts +1 -0
- package/dist/vesk-plugin.d.ts.map +1 -1
- package/dist/vesk-plugin.js +366 -1
- package/dist/vsk-imports.d.ts.map +1 -1
- package/dist/vsk-imports.js +3 -1
- package/dist/vsk-tsx.d.ts.map +1 -1
- package/dist/vsk-tsx.js +12 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client-codegen.d.ts","sourceRoot":"","sources":["../src/client-codegen.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAGL,cAAc,EAQd,gBAAgB,EAOjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"client-codegen.d.ts","sourceRoot":"","sources":["../src/client-codegen.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAuB,MAAM,uBAAuB,CAAC;AACzE,OAAO,EAGL,cAAc,EAQd,gBAAgB,EAOjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAwCxD,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,GAAG,MAAM,CAAC;CAC1B;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI1D;AAoBD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB,GAAG,cAAc,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,CAwGlI;AAID,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAU5E;AAqjCD,iBAAS,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAe3C;AA2HD,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAO9C;AAoED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,EAAE,OAAO,GAAE;IAAE,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GAAG,MAAM,CAOnN;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAqBnI;AAED,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC"}
|
package/dist/client-codegen.js
CHANGED
|
@@ -7,6 +7,7 @@ import { parse } from '@vesk/compiler/src/parser';
|
|
|
7
7
|
import { generateIR } from '@vesk/compiler/src/ir-generator';
|
|
8
8
|
import { transformTopLevelForActions } from '@vesk/compiler/src/actions';
|
|
9
9
|
import { extractRuntimeNames } from '@vesk/compiler/src/server-utils';
|
|
10
|
+
import { importBindingPairs } from '@vesk/compiler/src/module-imports';
|
|
10
11
|
import { stripTrackGeneric } from '@vesk/compiler/src/scan';
|
|
11
12
|
import { inlineMdImportsFrom } from '@vesk/compiler/src/md-inline';
|
|
12
13
|
import { stripTsTypes, hasTsSyntax } from '@vesk/compiler/src/strip-ts';
|
|
@@ -1532,7 +1533,16 @@ function emitClientFromIR(ir, options) {
|
|
|
1532
1533
|
runtimeNames.push(name);
|
|
1533
1534
|
}
|
|
1534
1535
|
}
|
|
1535
|
-
|
|
1536
|
+
// A name the file already binds via its own imports (e.g. a local module that
|
|
1537
|
+
// exports its own `effect`) shadows the runtime binding — never inject a
|
|
1538
|
+
// duplicate `import { x } from '@vesk/runtime'`. Mirrors SSR, so the two agree.
|
|
1539
|
+
const boundLocally = new Set();
|
|
1540
|
+
for (const imp of ir.imports) {
|
|
1541
|
+
for (const pair of importBindingPairs(imp))
|
|
1542
|
+
boundLocally.add(pair.local);
|
|
1543
|
+
}
|
|
1544
|
+
const shadowedRuntimeNames = runtimeNames.filter(n => !boundLocally.has(n));
|
|
1545
|
+
const runtimeImport = `import { ${shadowedRuntimeNames.length > 0 ? shadowedRuntimeNames.join(', ') : 'destroy_block'} } from '@vesk/runtime';`;
|
|
1536
1546
|
const moduleCode = `
|
|
1537
1547
|
${runtimeImport}
|
|
1538
1548
|
${importLines}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ir-generator.d.ts","sourceRoot":"","sources":["../src/ir-generator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,MAAM,EAoBP,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"ir-generator.d.ts","sourceRoot":"","sources":["../src/ir-generator.ts"],"names":[],"mappings":"AACA,OAAO,EACL,MAAM,EAoBP,MAAM,uBAAuB,CAAC;AAgJ/B,wBAAgB,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,GAAG,CAAC;IAAC,cAAc,CAAC,EAAE,GAAG,CAAC;IAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC,GAAG,SAAS,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCnL;AAuxBD,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAiO3D"}
|
package/dist/ir-generator.js
CHANGED
|
@@ -4,6 +4,7 @@ import { createBaseParser } from '@vesk/compiler/src/parser';
|
|
|
4
4
|
import { skipWhitespace, findBalancedEnd, splitTopLevel, startsWithIdentifier, stripDeclKeyword, isWhitespaceChar, collapseNewlineWhitespace } from '@vesk/compiler/src/scan';
|
|
5
5
|
import { stripCodeTypes } from '@vesk/compiler/src/strip-ts';
|
|
6
6
|
import { stripTypeImport } from '@vesk/compiler/src/vsk-imports';
|
|
7
|
+
import { importBindingPairs } from '@vesk/compiler/src/module-imports';
|
|
7
8
|
import { collectCalledIdentifiers, extractImportNames, importModuleTarget } from '@vesk/compiler/src/tokens';
|
|
8
9
|
let __vskAnnotations = [];
|
|
9
10
|
function parseExprNode(text) {
|
|
@@ -89,11 +90,11 @@ function componentUsesFetch(nodes) {
|
|
|
89
90
|
return true;
|
|
90
91
|
}
|
|
91
92
|
else if (node instanceof RuntimeStatement) {
|
|
92
|
-
if (node.raw.includes('useFetch('))
|
|
93
|
+
if (node.raw.includes('useFetch(') || node.raw.includes('useFetch.'))
|
|
93
94
|
return true;
|
|
94
95
|
}
|
|
95
96
|
else if (node instanceof DynamicBinding) {
|
|
96
|
-
if (node.expression.raw.includes('useFetch('))
|
|
97
|
+
if (node.expression.raw.includes('useFetch(') || node.expression.raw.includes('useFetch.'))
|
|
97
98
|
return true;
|
|
98
99
|
}
|
|
99
100
|
else if (node instanceof MapRegion) {
|
|
@@ -467,6 +468,32 @@ function processJSXChildren(source, children) {
|
|
|
467
468
|
result.push(...processJSXChildren(source, [c]));
|
|
468
469
|
i++;
|
|
469
470
|
}
|
|
471
|
+
else if (child.type === 'ForOfStatement') {
|
|
472
|
+
let alternate = [];
|
|
473
|
+
let consumed = 1;
|
|
474
|
+
const emptyText = children[i + 1];
|
|
475
|
+
const emptyContainer = children[i + 2];
|
|
476
|
+
if (emptyText && emptyText.type === 'JSXText' &&
|
|
477
|
+
['#empty', 'empty'].includes(emptyText.value.trim()) &&
|
|
478
|
+
emptyContainer && emptyContainer.type === 'JSXExpressionContainer' &&
|
|
479
|
+
emptyContainer.expression.type !== 'JSXEmptyExpression') {
|
|
480
|
+
alternate = exprToIR(source, emptyContainer.expression);
|
|
481
|
+
consumed = 3;
|
|
482
|
+
}
|
|
483
|
+
result.push(...processForStatement(source, child, alternate));
|
|
484
|
+
i += consumed;
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
else if (child.type === 'IfStatement' || child.type === 'ForStatement' ||
|
|
488
|
+
child.type === 'ForInStatement' ||
|
|
489
|
+
child.type === 'WhileStatement' || child.type === 'DoWhileStatement' ||
|
|
490
|
+
child.type === 'SwitchStatement' || child.type === 'TryStatement' ||
|
|
491
|
+
child.type === 'VariableDeclaration' || child.type === 'ExpressionStatement' ||
|
|
492
|
+
child.type === 'ReturnStatement' || child.type === 'WithStatement' ||
|
|
493
|
+
child.type === 'LabeledStatement') {
|
|
494
|
+
result.push(...processStatementModeBody(source, [child]));
|
|
495
|
+
i++;
|
|
496
|
+
}
|
|
470
497
|
else {
|
|
471
498
|
i++;
|
|
472
499
|
}
|
|
@@ -509,6 +536,30 @@ function exprToIR(source, expr) {
|
|
|
509
536
|
}
|
|
510
537
|
return [new DynamicBinding(toExpression(source, expr))];
|
|
511
538
|
}
|
|
539
|
+
/**
|
|
540
|
+
* True when an `ExpressionStatement` expression is a pure value that should
|
|
541
|
+
* render as output (a bare reference, member access, literal, template,
|
|
542
|
+
* conditional, etc.) rather than a side-effecting statement (call, assignment,
|
|
543
|
+
* update, `new`, `await`, `yield`, tagged template, `delete`/`void`). Side
|
|
544
|
+
* effects stay as runtime statements; pure values become dynamic bindings.
|
|
545
|
+
*/
|
|
546
|
+
function isRenderableExpression(expr) {
|
|
547
|
+
const t = expr.type;
|
|
548
|
+
if (t === 'CallExpression' || t === 'NewExpression' ||
|
|
549
|
+
t === 'AssignmentExpression' || t === 'UpdateExpression' ||
|
|
550
|
+
t === 'AwaitExpression' || t === 'YieldExpression' ||
|
|
551
|
+
t === 'TaggedTemplateExpression' || t === 'ImportExpression' ||
|
|
552
|
+
t === 'MetaProperty') {
|
|
553
|
+
return false;
|
|
554
|
+
}
|
|
555
|
+
if (t === 'UnaryExpression') {
|
|
556
|
+
return expr.operator !== 'delete' && expr.operator !== 'void';
|
|
557
|
+
}
|
|
558
|
+
if (t === 'SequenceExpression') {
|
|
559
|
+
return isRenderableExpression(expr.expressions[expr.expressions.length - 1]);
|
|
560
|
+
}
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
512
563
|
function processJSXCallbackBody(source, body) {
|
|
513
564
|
if (body.type === 'JSXElement')
|
|
514
565
|
return processJSXElement(source, body);
|
|
@@ -606,12 +657,17 @@ function buildGuardChain(source, guardClauses, mainReturn) {
|
|
|
606
657
|
const guard = guardClauses[i];
|
|
607
658
|
const condExpr = toExpression(source, guard.test);
|
|
608
659
|
const consequent = [];
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
660
|
+
const guardReturn = getReturnArgument(guard.consequent);
|
|
661
|
+
if (guardReturn) {
|
|
662
|
+
if (guardReturn.type === 'JSXElement') {
|
|
663
|
+
consequent.push(...processJSXElement(source, guardReturn));
|
|
664
|
+
}
|
|
665
|
+
else if (guardReturn.type === 'JSXFragment') {
|
|
666
|
+
for (const c of guardReturn.children)
|
|
667
|
+
consequent.push(...processJSXChildren(source, [c]));
|
|
612
668
|
}
|
|
613
669
|
else {
|
|
614
|
-
consequent.push(new DynamicBinding(toExpression(source,
|
|
670
|
+
consequent.push(new DynamicBinding(toExpression(source, guardReturn)));
|
|
615
671
|
}
|
|
616
672
|
}
|
|
617
673
|
currentAlternate = [new OpaqueDynamicRegion(condExpr, consequent, currentAlternate)];
|
|
@@ -655,7 +711,24 @@ function hasJSXInSubtree(node) {
|
|
|
655
711
|
return false;
|
|
656
712
|
}
|
|
657
713
|
function isGuardClause(node) {
|
|
658
|
-
return node.type === 'IfStatement' &&
|
|
714
|
+
return (node.type === 'IfStatement' &&
|
|
715
|
+
!node.alternate &&
|
|
716
|
+
getReturnArgument(node.consequent) !== null &&
|
|
717
|
+
hasJSXInSubtree(node.consequent));
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* Returns the `return` argument of a statement that represents an early
|
|
721
|
+
* return — either a bare `ReturnStatement` or a `BlockStatement` wrapping a
|
|
722
|
+
* single `ReturnStatement`. Returns `null` when the statement is not such a
|
|
723
|
+
* return (including `return null` / `return;`, whose argument is absent).
|
|
724
|
+
*/
|
|
725
|
+
function getReturnArgument(node) {
|
|
726
|
+
if (node.type === 'ReturnStatement')
|
|
727
|
+
return node.argument ?? null;
|
|
728
|
+
if (node.type === 'BlockStatement' && node.body.length === 1 && node.body[0].type === 'ReturnStatement') {
|
|
729
|
+
return node.body[0].argument ?? null;
|
|
730
|
+
}
|
|
731
|
+
return null;
|
|
659
732
|
}
|
|
660
733
|
function isStatementMode(bodyStmts) {
|
|
661
734
|
if (bodyStmts.some((s) => s.type === 'JSXElement' || s.type === 'JSXExpressionContainer' || s.type === 'JSXFragment'))
|
|
@@ -842,6 +915,16 @@ function processStatementModeBody(source, bodyStmts) {
|
|
|
842
915
|
else if (stmt.type === 'ForStatement') {
|
|
843
916
|
nodes.push(...processForStatement(source, stmt));
|
|
844
917
|
}
|
|
918
|
+
else if (stmt.type === 'ExpressionStatement') {
|
|
919
|
+
if (isRenderableExpression(stmt.expression)) {
|
|
920
|
+
nodes.push(...exprToIR(source, stmt.expression));
|
|
921
|
+
}
|
|
922
|
+
else {
|
|
923
|
+
const raw = getSource(source, stmt);
|
|
924
|
+
if (raw)
|
|
925
|
+
nodes.push(new RuntimeStatement(raw, stmt, source));
|
|
926
|
+
}
|
|
927
|
+
}
|
|
845
928
|
else if (stmt.type === 'ClassDeclaration') {
|
|
846
929
|
throw VeskError.classDecl();
|
|
847
930
|
}
|
|
@@ -1161,7 +1244,15 @@ export function generateIR(ast, source) {
|
|
|
1161
1244
|
for (const n of extractImportNames(imp))
|
|
1162
1245
|
existing.add(n);
|
|
1163
1246
|
}
|
|
1164
|
-
|
|
1247
|
+
// A name already bound by the file's own imports (any target — including a
|
|
1248
|
+
// local module with the same export) wins; never auto-import a duplicate
|
|
1249
|
+
// binding. Mirrors client shadowing so SSR and client agree.
|
|
1250
|
+
const boundLocally = new Set();
|
|
1251
|
+
for (const imp of imports) {
|
|
1252
|
+
for (const pair of importBindingPairs(imp))
|
|
1253
|
+
boundLocally.add(pair.local);
|
|
1254
|
+
}
|
|
1255
|
+
const missing = [...usedFunctions].filter(f => !existing.has(f) && !boundLocally.has(f));
|
|
1165
1256
|
if (missing.length > 0) {
|
|
1166
1257
|
imports.push(`import { ${missing.join(', ')} } from '@vesk/runtime';`);
|
|
1167
1258
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AST-driven extraction of the value bindings introduced by one import
|
|
3
|
+
* statement (`import { a as b } from 'm'` → `[{ local: 'b', imported: 'a' }]`;
|
|
4
|
+
* `import X from 'm'` → `[{ local: 'X', imported: 'default' }]`;
|
|
5
|
+
* `import * as X from 'm'` → `[{ local: 'X', imported: '*' }]`). Type-only
|
|
6
|
+
* specifiers are skipped. Side-effect imports return `[]`.
|
|
7
|
+
*/
|
|
8
|
+
export declare function importBindingPairs(imp: string): Array<{
|
|
9
|
+
local: string;
|
|
10
|
+
imported: string;
|
|
11
|
+
}>;
|
|
12
|
+
/** Local binding names imported from non-runtime, non-`.vsk` modules. */
|
|
13
|
+
export declare function localValueImportNames(importStrs: string[]): string[];
|
|
14
|
+
/** True when an import line should be SSR-loaded (non-runtime, non-empty, non-`.vsk`). */
|
|
15
|
+
export declare function isLocalValueImport(imp: string): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Loads every local value import and merges its exports into `__vesk` so SSR
|
|
18
|
+
* component bodies can reference them. Pure side-effect imports (`import './x'`)
|
|
19
|
+
* are also resolved and executed so their module-level setup runs client AND
|
|
20
|
+
* server. Resolution is relative to `sourcePath` (the importing `.vsk` file).
|
|
21
|
+
*
|
|
22
|
+
* Best-effort: unresolvable/unloadable modules warn and are skipped, matching
|
|
23
|
+
* how unresolvable `.vsk` imports are handled. Unsupported ESM constructs
|
|
24
|
+
* (import.meta/top-level await) THROW a specific error — loading them would
|
|
25
|
+
* silently yield `undefined` at render.
|
|
26
|
+
*/
|
|
27
|
+
export declare function applyLocalModuleImports(__vesk: Record<string, unknown>, importStrs: string[], sourcePath: string | undefined): void;
|
|
28
|
+
/**
|
|
29
|
+
* Loads (and caches) a module's export object. Cache entries track both the
|
|
30
|
+
* module's own mtime and the mtimes of everything it transitively resolved,
|
|
31
|
+
* so a change to any dependency invalidates every module that pulls it in.
|
|
32
|
+
* Builtin markers load through Node and are cached separately (never stale).
|
|
33
|
+
*/
|
|
34
|
+
export declare function loadSsrModule(absPath: string): Record<string, unknown> | null;
|
|
35
|
+
/**
|
|
36
|
+
* Resolves a specifier to an absolute file path (or a `BUILTIN_PREFIX` marker
|
|
37
|
+
* for Node builtins). Relative/absolute localities use extension probing;
|
|
38
|
+
* bare specifiers (`npm-package`, `pkg/subpath`, `node:fs`, `fs`) prefer
|
|
39
|
+
* Node's own resolver — which understands `exports` maps, conditions, scoped
|
|
40
|
+
* packages and builtins — and fall back to a `node_modules` walk-up.
|
|
41
|
+
*
|
|
42
|
+
* Every resolved file path is normalized through `realpathSync` so two
|
|
43
|
+
* specifiers pointing at the same physical file (e.g. pnpm/yarn symlinked
|
|
44
|
+
* `node_modules`) share one cache entry and one module instance.
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveSsrModule(specifier: string, fromDir: string): string | null;
|
|
47
|
+
/** Rewrites an ESM program body (imports/exports removed) into CJS statements. */
|
|
48
|
+
export declare function esmToCjs(body: Array<{
|
|
49
|
+
type: string;
|
|
50
|
+
} & Record<string, unknown>>): string;
|
|
51
|
+
//# sourceMappingURL=module-imports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-imports.d.ts","sourceRoot":"","sources":["../src/module-imports.ts"],"names":[],"mappings":"AAmGA;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgC1F;AAED,yEAAyE;AACzE,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAQpE;AAED,0FAA0F;AAC1F,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAIvD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,UAAU,EAAE,MAAM,EAAE,EACpB,UAAU,EAAE,MAAM,GAAG,SAAS,GAC7B,IAAI,CAuBN;AAiBD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAqD7E;AAqJD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAyBlF;AAoJD,kFAAkF;AAClF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAiGxF"}
|