@barefootjs/mojolicious 0.16.0 → 0.17.1
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/adapter/analysis/component-tree.d.ts +30 -0
- package/dist/adapter/analysis/component-tree.d.ts.map +1 -0
- package/dist/adapter/emit-context.d.ts +96 -0
- package/dist/adapter/emit-context.d.ts.map +1 -0
- package/dist/adapter/expr/array-method.d.ts +85 -0
- package/dist/adapter/expr/array-method.d.ts.map +1 -0
- package/dist/adapter/expr/emitters.d.ts +78 -0
- package/dist/adapter/expr/emitters.d.ts.map +1 -0
- package/dist/adapter/expr/operand.d.ts +34 -0
- package/dist/adapter/expr/operand.d.ts.map +1 -0
- package/dist/adapter/index.js +1482 -1339
- package/dist/adapter/lib/constants.d.ts +27 -0
- package/dist/adapter/lib/constants.d.ts.map +1 -0
- package/dist/adapter/lib/ir-scope.d.ts +33 -0
- package/dist/adapter/lib/ir-scope.d.ts.map +1 -0
- package/dist/adapter/lib/perl-naming.d.ts +29 -0
- package/dist/adapter/lib/perl-naming.d.ts.map +1 -0
- package/dist/adapter/lib/types.d.ts +28 -0
- package/dist/adapter/lib/types.d.ts.map +1 -0
- package/dist/adapter/memo/seed.d.ts +34 -0
- package/dist/adapter/memo/seed.d.ts.map +1 -0
- package/dist/adapter/mojo-adapter.d.ts +46 -104
- package/dist/adapter/mojo-adapter.d.ts.map +1 -1
- package/dist/adapter/props/prop-classes.d.ts +48 -0
- package/dist/adapter/props/prop-classes.d.ts.map +1 -0
- package/dist/adapter/spread/spread-codegen.d.ts +64 -0
- package/dist/adapter/spread/spread-codegen.d.ts.map +1 -0
- package/dist/adapter/value/parsed-literal.d.ts +26 -0
- package/dist/adapter/value/parsed-literal.d.ts.map +1 -0
- package/dist/build.js +1482 -1339
- package/dist/index.js +1482 -1339
- package/dist/test-render.d.ts.map +1 -1
- package/lib/BarefootJS/Backend/Mojo.pm +1 -1
- package/lib/Mojolicious/Plugin/BarefootJS/DevReload.pm +1 -1
- package/lib/Mojolicious/Plugin/BarefootJS.pm +1 -1
- package/package.json +3 -3
- package/src/__tests__/mojo-adapter.test.ts +286 -69
- package/src/__tests__/query-href.test.ts +94 -0
- package/src/adapter/analysis/component-tree.ts +128 -0
- package/src/adapter/emit-context.ts +107 -0
- package/src/adapter/expr/array-method.ts +429 -0
- package/src/adapter/expr/emitters.ts +639 -0
- package/src/adapter/expr/operand.ts +55 -0
- package/src/adapter/lib/constants.ts +39 -0
- package/src/adapter/lib/ir-scope.ts +57 -0
- package/src/adapter/lib/perl-naming.ts +36 -0
- package/src/adapter/lib/types.ts +31 -0
- package/src/adapter/memo/seed.ts +73 -0
- package/src/adapter/mojo-adapter.ts +248 -1485
- package/src/adapter/props/prop-classes.ts +87 -0
- package/src/adapter/spread/spread-codegen.ts +181 -0
- package/src/adapter/value/parsed-literal.ts +34 -0
- package/src/test-render.ts +2 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Component-tree analysis for the Mojolicious EP template adapter.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `mojo-adapter.ts` (domain-module refactor, issue #2018
|
|
5
|
+
* track D). Pure functions over the IR — they read no adapter instance
|
|
6
|
+
* state. `collectImportedLoopChildComponentErrors` returns its diagnostics
|
|
7
|
+
* instead of pushing onto the adapter's error list, so the adapter stays the
|
|
8
|
+
* sole owner of `errors`.
|
|
9
|
+
*
|
|
10
|
+
* SHARED CANDIDATE: `hasClientInteractivity` is byte-identical to the Xslate
|
|
11
|
+
* adapter's copy and adapter-agnostic; the BF103 loop-child check is the same
|
|
12
|
+
* structural walk in both, differing only in the Perl/Kolon diagnostic text —
|
|
13
|
+
* both are groundwork for a shared Perl-family codegen module (issue #2018
|
|
14
|
+
* track D).
|
|
15
|
+
*/
|
|
16
|
+
import type { ComponentIR, CompilerError } from '@barefootjs/jsx';
|
|
17
|
+
/**
|
|
18
|
+
* Whether the component needs the client runtime — it owns reactive state
|
|
19
|
+
* (signals / effects / onMount) or the analyzer flagged it as needing init.
|
|
20
|
+
*/
|
|
21
|
+
export declare function hasClientInteractivity(ir: ComponentIR): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Build a `BF103` diagnostic for every component reference inside a loop body
|
|
24
|
+
* whose name is imported from a relative-path module. Mirror of the Go
|
|
25
|
+
* adapter's check — the Mojo adapter has the same cross-template-registration
|
|
26
|
+
* constraint at request time. Returns the diagnostics so the caller pushes
|
|
27
|
+
* them onto its own error list.
|
|
28
|
+
*/
|
|
29
|
+
export declare function collectImportedLoopChildComponentErrors(ir: ComponentIR, componentName: string): CompilerError[];
|
|
30
|
+
//# sourceMappingURL=component-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-tree.d.ts","sourceRoot":"","sources":["../../../src/adapter/analysis/component-tree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,WAAW,EAUX,aAAa,EACd,MAAM,iBAAiB,CAAA;AAExB;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,EAAE,EAAE,WAAW,GAAG,OAAO,CAO/D;AAED;;;;;;GAMG;AACH,wBAAgB,uCAAuC,CACrD,EAAE,EAAE,WAAW,EACf,aAAa,EAAE,MAAM,GACpB,aAAa,EAAE,CA0EjB"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The contract the extracted expression-emitter modules depend on instead of
|
|
3
|
+
* the concrete `MojoAdapter`.
|
|
4
|
+
*
|
|
5
|
+
* The Mojo adapter's top-level expression lowering is mutually recursive with
|
|
6
|
+
* the adapter's own const/record resolution and its filter-predicate emitter,
|
|
7
|
+
* so the extracted `MojoTopLevelEmitter` still needs to call back into shared
|
|
8
|
+
* per-compile state and recursive entry points. `MojoEmitContext` is that
|
|
9
|
+
* seam: the emitter takes a `MojoEmitContext` built by the adapter's private
|
|
10
|
+
* `emitCtx` getter (the adapter does NOT `implements` this interface, so the
|
|
11
|
+
* wrapped members stay private and off its exported public type — matching the
|
|
12
|
+
* Go adapter's `emitCtx`). The emitter depends on this narrow interface rather
|
|
13
|
+
* than the full ~3k-line class, so the coupling is explicit and it's
|
|
14
|
+
* unit-testable against a stub.
|
|
15
|
+
*
|
|
16
|
+
* Keep this surface minimal: add a member only when an extracted module
|
|
17
|
+
* genuinely needs it, so the seam documents the real cross-module coupling
|
|
18
|
+
* rather than re-exposing the whole adapter.
|
|
19
|
+
*/
|
|
20
|
+
import type { ParsedExpr, CompilerError, IRMetadata } from '@barefootjs/jsx';
|
|
21
|
+
export interface MojoEmitContext {
|
|
22
|
+
/**
|
|
23
|
+
* (#1922) Local binding names the request-scoped `searchParams()` env signal
|
|
24
|
+
* is imported under. Non-empty enables the env-signal method-call lowering.
|
|
25
|
+
*/
|
|
26
|
+
readonly _searchParamsLocals: Set<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Inline a module-scope pure string-literal const by name as the resolved
|
|
29
|
+
* literal value, or null when the name is not such a const.
|
|
30
|
+
*/
|
|
31
|
+
resolveModuleStringConst(name: string): string | null;
|
|
32
|
+
/** Resolve a literal const (`const totalPages = 5`) to its Perl value, or null. */
|
|
33
|
+
resolveLiteralConst(name: string): string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Resolve a static property access on a module object-literal const
|
|
36
|
+
* (`variantClasses.ghost`) to its Perl value at compile time, or null.
|
|
37
|
+
*/
|
|
38
|
+
resolveStaticRecordLiteral(objectName: string, key: string): string | null;
|
|
39
|
+
/** Whether a getter/prop name resolves to a string-typed SSR value. */
|
|
40
|
+
_isStringValueName(name: string): boolean;
|
|
41
|
+
/** Record a BF101 unsupported-expression diagnostic. */
|
|
42
|
+
_recordExprBF101(message: string, reason?: string): void;
|
|
43
|
+
/** Lower a filter/predicate body to its Perl form, bound to `param`. */
|
|
44
|
+
_renderPerlFilterExprPublic(expr: ParsedExpr, param: string): string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The contract the extracted object-literal / conditional-spread lowering
|
|
48
|
+
* (`spread/spread-codegen.ts`) depends on. The spread lowering recurses into
|
|
49
|
+
* the core expression lowering and records its own BF101 diagnostics, so it
|
|
50
|
+
* needs the recursive entry point plus the per-compile bookkeeping the
|
|
51
|
+
* adapter owns. Declared separately from `MojoEmitContext` so each extracted
|
|
52
|
+
* module's real coupling is documented precisely.
|
|
53
|
+
*/
|
|
54
|
+
export interface MojoSpreadContext {
|
|
55
|
+
/** Component name, for diagnostic source locations. */
|
|
56
|
+
readonly componentName: string;
|
|
57
|
+
/** Per-compile diagnostic list the spread lowering appends to. */
|
|
58
|
+
readonly errors: CompilerError[];
|
|
59
|
+
/** Local-constant metadata, for resolving `Record[key]` spread values. */
|
|
60
|
+
readonly localConstants: IRMetadata['localConstants'];
|
|
61
|
+
/** Prop params, for classifying a bare-identifier index as a prop. */
|
|
62
|
+
readonly propsParams: {
|
|
63
|
+
name: string;
|
|
64
|
+
}[];
|
|
65
|
+
/**
|
|
66
|
+
* Lower a JS expression to its Perl form (the core recursive entry).
|
|
67
|
+
*
|
|
68
|
+
* When the IR already carries a structured `ParsedExpr` tree, pass it as
|
|
69
|
+
* `preParsed` so the converter threads it straight through instead of
|
|
70
|
+
* re-parsing `expr` — mirrors go-template's
|
|
71
|
+
* `convertExpressionToGo(jsExpr, out?, preParsed?)`. With `preParsed` set,
|
|
72
|
+
* `expr` is unused for parsing (the converter derives any diagnostic text
|
|
73
|
+
* from the tree), so callers may pass `''`.
|
|
74
|
+
*/
|
|
75
|
+
convertExpressionToPerl(expr: string, preParsed?: ParsedExpr): string;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The contract the extracted in-template memo / context seeding
|
|
79
|
+
* (`memo/seed.ts`) depends on. The seed lowering recurses into the core
|
|
80
|
+
* expression lowering to compute a derived signal/memo value or a context
|
|
81
|
+
* default; that recursive entry is its only adapter coupling.
|
|
82
|
+
*/
|
|
83
|
+
export interface MojoMemoContext {
|
|
84
|
+
/**
|
|
85
|
+
* Lower a JS expression to its Perl form (the core recursive entry).
|
|
86
|
+
*
|
|
87
|
+
* When the IR already carries a structured `ParsedExpr` tree, pass it as
|
|
88
|
+
* `preParsed` so the converter threads it straight through instead of
|
|
89
|
+
* re-parsing `expr` — mirrors go-template's
|
|
90
|
+
* `convertExpressionToGo(jsExpr, out?, preParsed?)`. With `preParsed` set,
|
|
91
|
+
* `expr` is unused for parsing (the converter derives any diagnostic text
|
|
92
|
+
* from the tree), so callers may pass `''`.
|
|
93
|
+
*/
|
|
94
|
+
convertExpressionToPerl(expr: string, preParsed?: ParsedExpr): string;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=emit-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emit-context.d.ts","sourceRoot":"","sources":["../../src/adapter/emit-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5E,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAEzC;;;OAGG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAErD,mFAAmF;IACnF,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAEhD;;;OAGG;IACH,0BAA0B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IAE1E,uEAAuE;IACvE,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAA;IAEzC,wDAAwD;IACxD,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAExD,wEAAwE;IACxE,2BAA2B,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;CACrE;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAE9B,kEAAkE;IAClE,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,CAAA;IAEhC,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC,gBAAgB,CAAC,CAAA;IAErD,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAExC;;;;;;;;;OASG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;CACtE;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B;;;;;;;;;OASG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;CACtE"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Array / string method lowering for the Mojolicious EP template adapter.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `mojo-adapter.ts` (domain-module refactor, issue #2018
|
|
5
|
+
* track D). Pure free functions shared by both the filter-context emitter
|
|
6
|
+
* and the top-level emitter — they take an `emit` callback for receiver /
|
|
7
|
+
* argument recursion and read no adapter instance state.
|
|
8
|
+
*/
|
|
9
|
+
import type { ParsedExpr, ArrayMethod, SortComparator, FlatDepth } from '@barefootjs/jsx';
|
|
10
|
+
/**
|
|
11
|
+
* Lower an `arr.<method>(...)` / `str.<method>(...)` value-builtin call to
|
|
12
|
+
* its Perl form. The IR lifts these into the dedicated `array-method` kind at
|
|
13
|
+
* parse time (see the `arrayMethod` emitter arms), so this is the single
|
|
14
|
+
* place every adapter-supported array/string method is mapped. An unhandled
|
|
15
|
+
* `ArrayMethod` variant throws rather than emitting a silent no-op — the
|
|
16
|
+
* drift defence we already apply to `ParsedExpr.kind` extended to its
|
|
17
|
+
* sub-discriminator.
|
|
18
|
+
*/
|
|
19
|
+
export declare function renderArrayMethod(method: ArrayMethod, object: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
20
|
+
/**
|
|
21
|
+
* Emit a `.sort(cmp)` / `.toSorted(cmp)` via the runtime evaluator (#2018):
|
|
22
|
+
* the comparator body travels as serialized-ParsedExpr JSON, evaluated per
|
|
23
|
+
* comparison against `{paramA, paramB, …captured}`. Returns null when the
|
|
24
|
+
* body can't be evaluated (e.g. a `localeCompare` comparator —
|
|
25
|
+
* `serializeParsedExpr` refuses it), so the caller falls back to the
|
|
26
|
+
* structured `bf->sort`. A `||`-chained multi-key comparator needs no
|
|
27
|
+
* special handling — JS `0 || next` is exactly the tie-break semantics.
|
|
28
|
+
*/
|
|
29
|
+
export declare function renderSortEval(recv: string, body: ParsedExpr, params: string[], emit: (e: ParsedExpr) => string): string | null;
|
|
30
|
+
/**
|
|
31
|
+
* Emit a `.reduce(fn, init)` / `.reduceRight(fn, init)` via the runtime
|
|
32
|
+
* evaluator (#2018): the reducer body travels as serialized-ParsedExpr JSON,
|
|
33
|
+
* folded over the receiver from `init` in `direction` order. Returns null when
|
|
34
|
+
* the body can't be evaluated (→ caller falls back to `bf->reduce`). A numeric
|
|
35
|
+
* seed passes through as a bare Perl number; a concat seed as a single-quoted
|
|
36
|
+
* string.
|
|
37
|
+
*/
|
|
38
|
+
export declare function renderReduceEval(recv: string, body: ParsedExpr, params: string[], init: ParsedExpr, direction: 'left' | 'right', emit: (e: ParsedExpr) => string): string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Emit a higher-order predicate call via the runtime evaluator (#2018, P2):
|
|
41
|
+
* `bf->filter_eval` / `bf->every_eval` / `bf->some_eval` / `bf->find_eval` /
|
|
42
|
+
* `bf->find_index_eval`, carrying the serialized predicate body + captured env
|
|
43
|
+
* hashref. Generalizes the inline `grep` / `bf->find` lowering to the same
|
|
44
|
+
* JS-faithful evaluator the Go adapter uses (cross-adapter isomorphism).
|
|
45
|
+
* Returns null when the predicate is outside the evaluator surface (e.g. a
|
|
46
|
+
* method-call predicate — `serializeParsedExpr` refuses it), so the caller
|
|
47
|
+
* falls back to the `grep` / `bf->find` form. `forward` (find / findIndex
|
|
48
|
+
* family only) selects the search direction — `false` = findLast /
|
|
49
|
+
* findLastIndex.
|
|
50
|
+
*/
|
|
51
|
+
export declare function renderPredicateEval(funcName: string, recv: string, predicate: ParsedExpr, param: string, emit: (e: ParsedExpr) => string, forward?: boolean): string | null;
|
|
52
|
+
/**
|
|
53
|
+
* Emit a `.flatMap(proj)` via the runtime evaluator (#2018, P3/P5): the
|
|
54
|
+
* projection `body` serializes to JSON and `bf->flat_map_eval` projects +
|
|
55
|
+
* flattens one level. The sole flatMap lowering now (the structured
|
|
56
|
+
* `bf->flat_map` / `bf->flat_map_tuple` fallback was retired with the
|
|
57
|
+
* `ParsedExpr` collapse); returns null when the projection is outside the
|
|
58
|
+
* evaluator surface, and the caller records BF101.
|
|
59
|
+
*/
|
|
60
|
+
export declare function renderFlatMapEval(recv: string, body: ParsedExpr, param: string, emit: (e: ParsedExpr) => string): string | null;
|
|
61
|
+
/**
|
|
62
|
+
* Emit a value-producing `.map(cb)` via the runtime evaluator (#2073): the
|
|
63
|
+
* projection `body` serializes to JSON and `bf->map_eval` projects each
|
|
64
|
+
* element, one result per element (no flatten — the JS `.map` contract).
|
|
65
|
+
* Composes through the array-method chain (`.map(cb).join(' ')`). Returns
|
|
66
|
+
* null when the projection is outside the evaluator surface, and the caller
|
|
67
|
+
* records BF101. The JSX-returning `.map` is an IRLoop upstream and never
|
|
68
|
+
* reaches this emit.
|
|
69
|
+
*/
|
|
70
|
+
export declare function renderMapEval(recv: string, body: ParsedExpr, param: string, emit: (e: ParsedExpr) => string): string | null;
|
|
71
|
+
/**
|
|
72
|
+
* Shared Mojo emit for `.sort(cmp)` / `.toSorted(cmp)` (#1448 Tier B).
|
|
73
|
+
* Used by both the filter-context emitter and the top-level emitter,
|
|
74
|
+
* plus the loop-hoist path in `renderLoop` — same emit shape across
|
|
75
|
+
* all three so a regression in any one path surfaces consistently.
|
|
76
|
+
*
|
|
77
|
+
* The Perl helper accepts a hash-ref opts bag whose `keys` entry is
|
|
78
|
+
* an ordered list of per-key hashes (room for a future `nulls` knob
|
|
79
|
+
* without arity churn), and returns a fresh ARRAY ref so downstream
|
|
80
|
+
* composition (`@{bf->sort(...)}` in `join(...)`, etc.) stays
|
|
81
|
+
* straightforward.
|
|
82
|
+
*/
|
|
83
|
+
export declare function renderSortMethod(recv: string, c: SortComparator): string;
|
|
84
|
+
export declare function renderFlatMethod(recv: string, depth: FlatDepth): string;
|
|
85
|
+
//# sourceMappingURL=array-method.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"array-method.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/array-method.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,cAAc,EACd,SAAS,EACV,MAAM,iBAAiB,CAAA;AAExB;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAAE,EAClB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CA6MR;AA6BD;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAOf;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,GAAG,OAAO,EAC3B,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAmBf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,UAAU,EACrB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,EAC/B,OAAO,CAAC,EAAE,OAAO,GAChB,MAAM,GAAG,IAAI,CAMf;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,GAAG,IAAI,CAKf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,cAAc,GAAG,MAAM,CAaxE;AAKD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG,MAAM,CAGvE"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ParsedExpr → Perl emitters for the Mojolicious EP template adapter.
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `mojo-adapter.ts` (domain-module refactor, issue #2018
|
|
5
|
+
* track D). Two `ParsedExprEmitter` implementations:
|
|
6
|
+
*
|
|
7
|
+
* - `MojoFilterEmitter` — filter/predicate context (loop param + local
|
|
8
|
+
* aliases + bare `$name` signal fallback); self-contained, reads no
|
|
9
|
+
* adapter state.
|
|
10
|
+
* - `MojoTopLevelEmitter` — top-level / stash context; depends on the
|
|
11
|
+
* adapter only through the narrow `MojoEmitContext` seam.
|
|
12
|
+
*/
|
|
13
|
+
import { type ParsedExprEmitter, type ArrayMethod, type LiteralType, type ParsedExpr, type ObjectLiteralProperty, type FlatDepth, type TemplatePart } from '@barefootjs/jsx';
|
|
14
|
+
import type { MojoEmitContext } from '../emit-context.ts';
|
|
15
|
+
export declare class MojoFilterEmitter implements ParsedExprEmitter {
|
|
16
|
+
private readonly param;
|
|
17
|
+
private readonly localVarMap;
|
|
18
|
+
private readonly isStringName;
|
|
19
|
+
private readonly onUnsupported?;
|
|
20
|
+
constructor(param: string, localVarMap: Map<string, string>, isStringName?: (n: string) => boolean, onUnsupported?: ((message: string, reason?: string) => void) | undefined);
|
|
21
|
+
identifier(name: string): string;
|
|
22
|
+
literal(value: string | number | boolean | null, literalType: LiteralType): string;
|
|
23
|
+
member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string;
|
|
24
|
+
indexAccess(object: ParsedExpr, index: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
25
|
+
call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
26
|
+
unary(op: string, argument: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
27
|
+
binary(op: string, left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
28
|
+
logical(op: '&&' | '||' | '??', left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
29
|
+
callbackMethod(method: string, object: ParsedExpr, arrow: Extract<ParsedExpr, {
|
|
30
|
+
kind: 'arrow';
|
|
31
|
+
}>, _restArgs: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
32
|
+
arrayLiteral(elements: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
33
|
+
arrayMethod(method: ArrayMethod, object: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
34
|
+
flatMethod(object: ParsedExpr, depth: FlatDepth, emit: (e: ParsedExpr) => string): string;
|
|
35
|
+
conditional(_test: ParsedExpr, _consequent: ParsedExpr, _alternate: ParsedExpr): string;
|
|
36
|
+
templateLiteral(_parts: TemplatePart[]): string;
|
|
37
|
+
arrow(_params: string[], _body: ParsedExpr, _emit: (e: ParsedExpr) => string): string;
|
|
38
|
+
regex(_raw: string): string;
|
|
39
|
+
unsupported(_raw: string, _reason: string): string;
|
|
40
|
+
objectLiteral(_properties: ObjectLiteralProperty[], _raw: string, _emit: (e: ParsedExpr) => string): string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Lowering for top-level expressions whose identifiers resolve against
|
|
44
|
+
* the Mojo template's stash (signals, props, locals introduced by
|
|
45
|
+
* `% my $x = ...;` lines). Differs from the filter emitter mainly in
|
|
46
|
+
* - `.length` → `scalar(@{...})` (filter contexts never see arrays
|
|
47
|
+
* in lvalue position),
|
|
48
|
+
* - `conditional` is supported (filter predicates can't return
|
|
49
|
+
* ternaries),
|
|
50
|
+
* - the `unsupported` fallback drops to the regex pipeline so legacy
|
|
51
|
+
* shapes the AST can't classify still emit something coherent.
|
|
52
|
+
*/
|
|
53
|
+
export declare class MojoTopLevelEmitter implements ParsedExprEmitter {
|
|
54
|
+
private readonly ctx;
|
|
55
|
+
constructor(ctx: MojoEmitContext);
|
|
56
|
+
identifier(name: string): string;
|
|
57
|
+
literal(value: string | number | boolean | null, literalType: LiteralType): string;
|
|
58
|
+
member(object: ParsedExpr, property: string, _computed: boolean, emit: (e: ParsedExpr) => string): string;
|
|
59
|
+
indexAccess(object: ParsedExpr, index: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
60
|
+
call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
61
|
+
unary(op: string, argument: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
62
|
+
binary(op: string, left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
63
|
+
logical(op: '&&' | '||' | '??', left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
64
|
+
callbackMethod(method: string, object: ParsedExpr, arrow: Extract<ParsedExpr, {
|
|
65
|
+
kind: 'arrow';
|
|
66
|
+
}>, restArgs: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
67
|
+
private renderPredicate;
|
|
68
|
+
arrayLiteral(elements: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
69
|
+
arrayMethod(method: ArrayMethod, object: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
70
|
+
flatMethod(object: ParsedExpr, depth: FlatDepth, emit: (e: ParsedExpr) => string): string;
|
|
71
|
+
conditional(test: ParsedExpr, consequent: ParsedExpr, alternate: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
72
|
+
templateLiteral(parts: TemplatePart[], emit: (e: ParsedExpr) => string): string;
|
|
73
|
+
arrow(_params: string[], _body: ParsedExpr, _emit: (e: ParsedExpr) => string): string;
|
|
74
|
+
regex(_raw: string): string;
|
|
75
|
+
unsupported(_raw: string, _reason: string): string;
|
|
76
|
+
objectLiteral(_properties: ObjectLiteralProperty[], _raw: string, _emit: (e: ParsedExpr) => string): string;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=emitters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitters.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/emitters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Operand-type classification + index-access lowering for the Mojolicious
|
|
3
|
+
* EP template adapter.
|
|
4
|
+
*
|
|
5
|
+
* Extracted from `mojo-adapter.ts` (domain-module refactor, issue #2018
|
|
6
|
+
* track D). Pure functions over `ParsedExpr` — they take an `isStringName`
|
|
7
|
+
* predicate (supplied by the emitter from adapter state) rather than reading
|
|
8
|
+
* adapter instance state directly.
|
|
9
|
+
*
|
|
10
|
+
* SHARED CANDIDATE: `isStringTypedOperand` is byte-identical to the Xslate
|
|
11
|
+
* adapter's copy and is adapter-agnostic — an extraction candidate for a
|
|
12
|
+
* shared Perl-family codegen module (groundwork for the future Perl evaluator
|
|
13
|
+
* integration, issue #2018 track D). `emitIndexAccessPerl` stays Mojo-specific
|
|
14
|
+
* (Perl's `->[]` vs `->{}` split has no Kolon equivalent).
|
|
15
|
+
*/
|
|
16
|
+
import type { ParsedExpr } from '@barefootjs/jsx';
|
|
17
|
+
/**
|
|
18
|
+
* Whether a comparison operand is string-typed, so JS `===`/`!==` against it
|
|
19
|
+
* must lower to Perl `eq`/`ne` instead of numeric `==`/`!=` (#1672). Covers a
|
|
20
|
+
* string literal, a string-signal getter call (`sel()`), and a string prop
|
|
21
|
+
* access (`props.x`). `isStringName` reports whether a getter/prop name is
|
|
22
|
+
* known-string. Loop-element fields (`t.id`) on untyped arrays have no known
|
|
23
|
+
* type and stay undetected — a separate, narrower gap.
|
|
24
|
+
*/
|
|
25
|
+
export declare function isStringTypedOperand(expr: ParsedExpr, isStringName: (n: string) => boolean): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Lower `arr[index]` to a Perl deref. Perl distinguishes array
|
|
28
|
+
* (`->[$i]`) from hash (`->{$k}`) access, which JS's single `[]` does
|
|
29
|
+
* not — so we pick by the index expression's type: a string-typed key
|
|
30
|
+
* derefs the hash, anything else (the common loop-index / arithmetic
|
|
31
|
+
* case, e.g. `selected()[index]`) derefs the array. #1897.
|
|
32
|
+
*/
|
|
33
|
+
export declare function emitIndexAccessPerl(object: ParsedExpr, index: ParsedExpr, emit: (e: ParsedExpr) => string, isStringName: (n: string) => boolean): string;
|
|
34
|
+
//# sourceMappingURL=operand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operand.d.ts","sourceRoot":"","sources":["../../../src/adapter/expr/operand.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAEjD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CASpG;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,UAAU,EACjB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,EAC/B,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,GACnC,MAAM,CAKR"}
|