@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.
Files changed (53) hide show
  1. package/dist/adapter/analysis/component-tree.d.ts +30 -0
  2. package/dist/adapter/analysis/component-tree.d.ts.map +1 -0
  3. package/dist/adapter/emit-context.d.ts +96 -0
  4. package/dist/adapter/emit-context.d.ts.map +1 -0
  5. package/dist/adapter/expr/array-method.d.ts +85 -0
  6. package/dist/adapter/expr/array-method.d.ts.map +1 -0
  7. package/dist/adapter/expr/emitters.d.ts +78 -0
  8. package/dist/adapter/expr/emitters.d.ts.map +1 -0
  9. package/dist/adapter/expr/operand.d.ts +34 -0
  10. package/dist/adapter/expr/operand.d.ts.map +1 -0
  11. package/dist/adapter/index.js +1482 -1339
  12. package/dist/adapter/lib/constants.d.ts +27 -0
  13. package/dist/adapter/lib/constants.d.ts.map +1 -0
  14. package/dist/adapter/lib/ir-scope.d.ts +33 -0
  15. package/dist/adapter/lib/ir-scope.d.ts.map +1 -0
  16. package/dist/adapter/lib/perl-naming.d.ts +29 -0
  17. package/dist/adapter/lib/perl-naming.d.ts.map +1 -0
  18. package/dist/adapter/lib/types.d.ts +28 -0
  19. package/dist/adapter/lib/types.d.ts.map +1 -0
  20. package/dist/adapter/memo/seed.d.ts +34 -0
  21. package/dist/adapter/memo/seed.d.ts.map +1 -0
  22. package/dist/adapter/mojo-adapter.d.ts +46 -104
  23. package/dist/adapter/mojo-adapter.d.ts.map +1 -1
  24. package/dist/adapter/props/prop-classes.d.ts +48 -0
  25. package/dist/adapter/props/prop-classes.d.ts.map +1 -0
  26. package/dist/adapter/spread/spread-codegen.d.ts +64 -0
  27. package/dist/adapter/spread/spread-codegen.d.ts.map +1 -0
  28. package/dist/adapter/value/parsed-literal.d.ts +26 -0
  29. package/dist/adapter/value/parsed-literal.d.ts.map +1 -0
  30. package/dist/build.js +1482 -1339
  31. package/dist/index.js +1482 -1339
  32. package/dist/test-render.d.ts.map +1 -1
  33. package/lib/BarefootJS/Backend/Mojo.pm +1 -1
  34. package/lib/Mojolicious/Plugin/BarefootJS/DevReload.pm +1 -1
  35. package/lib/Mojolicious/Plugin/BarefootJS.pm +1 -1
  36. package/package.json +3 -3
  37. package/src/__tests__/mojo-adapter.test.ts +286 -69
  38. package/src/__tests__/query-href.test.ts +94 -0
  39. package/src/adapter/analysis/component-tree.ts +128 -0
  40. package/src/adapter/emit-context.ts +107 -0
  41. package/src/adapter/expr/array-method.ts +429 -0
  42. package/src/adapter/expr/emitters.ts +639 -0
  43. package/src/adapter/expr/operand.ts +55 -0
  44. package/src/adapter/lib/constants.ts +39 -0
  45. package/src/adapter/lib/ir-scope.ts +57 -0
  46. package/src/adapter/lib/perl-naming.ts +36 -0
  47. package/src/adapter/lib/types.ts +31 -0
  48. package/src/adapter/memo/seed.ts +73 -0
  49. package/src/adapter/mojo-adapter.ts +248 -1485
  50. package/src/adapter/props/prop-classes.ts +87 -0
  51. package/src/adapter/spread/spread-codegen.ts +181 -0
  52. package/src/adapter/value/parsed-literal.ts +34 -0
  53. 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":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EACL,KAAK,iBAAiB,EAEtB,KAAK,WAAW,EAChB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC1B,KAAK,SAAS,EACd,KAAK,YAAY,EAMlB,MAAM,iBAAiB,CAAA;AAExB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AA+CzD,qBAAa,iBAAkB,YAAW,iBAAiB;IAEvD,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAI5B,OAAO,CAAC,QAAQ,CAAC,YAAY;IAK7B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAXjC,YACmB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAIhC,YAAY,GAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAqB,EAKlD,aAAa,CAAC,GAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,aAAA,EACzE;IAEJ,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/B;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,EAAE,WAAW,EAAE,WAAW,GAAG,MAAM,CAKjF;IAED,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAYxG;IAED,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAE1F;IAED,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAMpF;IAED,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAS/E;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAmB/F;IAED,OAAO,CAAC,EAAE,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAM5G;IAED,cAAc,CACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,EAC7C,SAAS,EAAE,UAAU,EAAE,EACvB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAgCR;IAED,YAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAQ5E;IAED,WAAW,CACT,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAAE,EAClB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAMR;IAED,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAExF;IAED,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,CAEtF;IAED,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,CAE9C;IAED,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAKpF;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG1B;IAED,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;IAED,aAAa,CAAC,WAAW,EAAE,qBAAqB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAM1G;CACF;AAED;;;;;;;;;;GAUG;AACH,qBAAa,mBAAoB,YAAW,iBAAiB;IAC/C,OAAO,CAAC,QAAQ,CAAC,GAAG;IAAhC,YAA6B,GAAG,EAAE,eAAe,EAAI;IAErD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAe/B;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,EAAE,WAAW,EAAE,WAAW,GAAG,MAAM,CAKjF;IAED,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAkBxG;IAED,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAE1F;IAED,IAAI,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CA4CpF;IAED,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAK/E;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAqB/F;IAED,OAAO,CAAC,EAAE,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAM5G;IAED,cAAc,CACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,EAC7C,QAAQ,EAAE,UAAU,EAAE,EACtB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAqER;IAED,OAAO,CAAC,eAAe;IAiDvB,YAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAO5E;IAED,WAAW,CACT,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,UAAU,EAAE,EAClB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAER;IAED,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAExF;IAED,WAAW,CACT,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,UAAU,EACrB,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAC9B,MAAM,CAER;IAED,eAAe,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CA6B9E;IAED,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAOpF;IAED,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAK1B;IAED,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAOjD;IAED,aAAa,CAAC,WAAW,EAAE,qBAAqB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,MAAM,GAAG,MAAM,CAO1G;CACF"}
@@ -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"}