@barefootjs/jsx 0.33.6 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/parsed-expr-emitter.d.ts +17 -0
- package/dist/adapters/parsed-expr-emitter.d.ts.map +1 -1
- package/dist/expression-parser.d.ts +17 -4
- package/dist/expression-parser.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +101 -67
- package/dist/lowering-registry.d.ts +12 -0
- package/dist/lowering-registry.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/lowering-value-position.test.ts +232 -0
- package/src/adapters/parsed-expr-emitter.ts +43 -0
- package/src/expression-parser.ts +63 -29
- package/src/index.ts +2 -1
- package/src/lowering-registry.ts +21 -0
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
* be added in one place.
|
|
34
34
|
*/
|
|
35
35
|
import type { ParsedExpr, FlatDepth, TemplatePart, ObjectLiteralProperty } from '../expression-parser.ts';
|
|
36
|
+
import type { LoweringMatcher, LoweringNode } from '../lowering-registry.ts';
|
|
36
37
|
export type HigherOrderMethod = 'filter' | 'every' | 'some' | 'find' | 'findIndex' | 'findLast' | 'findLastIndex';
|
|
37
38
|
/**
|
|
38
39
|
* Non-higher-order array methods (#1443). One discriminator for the
|
|
@@ -59,6 +60,21 @@ export type ArrayMethod = 'join' | 'includes' | 'indexOf' | 'lastIndexOf' | 'at'
|
|
|
59
60
|
*/
|
|
60
61
|
export type SortMethod = 'sort' | 'toSorted';
|
|
61
62
|
export type LiteralType = 'string' | 'number' | 'boolean' | 'null';
|
|
63
|
+
/**
|
|
64
|
+
* An adapter's registered-lowering seam for the shared `call` dispatch
|
|
65
|
+
* (#2843). `matchers` are the same `ctx.state.loweringMatchers`-style list
|
|
66
|
+
* every adapter already binds at init; `render` maps one matched neutral
|
|
67
|
+
* node to this adapter's own template syntax (its body is typically what
|
|
68
|
+
* used to live inline in the adapter's `call()` method before this seam
|
|
69
|
+
* existed — see `renderLoweringNode` in the Go adapter's `url-builder.ts`
|
|
70
|
+
* for the shape). Returning null for a `kind`/`helper` this adapter has no
|
|
71
|
+
* mapping for lets the caller fall through to the ordinary `call()`
|
|
72
|
+
* dispatch, same as an unmatched call.
|
|
73
|
+
*/
|
|
74
|
+
export interface LoweringEmitter {
|
|
75
|
+
readonly matchers: readonly LoweringMatcher[];
|
|
76
|
+
render(node: LoweringNode, emit: (e: ParsedExpr) => string): string | null;
|
|
77
|
+
}
|
|
62
78
|
/**
|
|
63
79
|
* Adapter-side ParsedExpr lowering surface. One method per
|
|
64
80
|
* `ParsedExpr.kind`. The shared `emitParsedExpr` runner dispatches
|
|
@@ -73,6 +89,7 @@ export interface ParsedExprEmitter {
|
|
|
73
89
|
identifier(name: string): string;
|
|
74
90
|
literal(value: string | number | boolean | null, literalType: LiteralType): string;
|
|
75
91
|
call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string;
|
|
92
|
+
lowering?: LoweringEmitter;
|
|
76
93
|
member(object: ParsedExpr, property: string, computed: boolean, optional: boolean, emit: (e: ParsedExpr) => string): string;
|
|
77
94
|
indexAccess(object: ParsedExpr, index: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
78
95
|
binary(op: string, left: ParsedExpr, right: ParsedExpr, emit: (e: ParsedExpr) => string): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parsed-expr-emitter.d.ts","sourceRoot":"","sources":["../../src/adapters/parsed-expr-emitter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"parsed-expr-emitter.d.ts","sourceRoot":"","sources":["../../src/adapters/parsed-expr-emitter.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* and conversion to backend template syntax.
|
|
7
7
|
*/
|
|
8
8
|
import ts from 'typescript';
|
|
9
|
+
import { type LoweringMatcher } from './lowering-registry.ts';
|
|
9
10
|
export type ParsedExpr = {
|
|
10
11
|
kind: 'identifier';
|
|
11
12
|
name: string;
|
|
@@ -380,17 +381,29 @@ export declare function sortComparatorFromArrow(arrow: ParsedExpr): SortComparat
|
|
|
380
381
|
* reaches the page. See {@link isSupportedValue} for the sibling VALUE-
|
|
381
382
|
* position entry point, and `checkSupport`'s `pos` parameter for why the two
|
|
382
383
|
* never converge partway through a tree.
|
|
383
|
-
|
|
384
|
-
|
|
384
|
+
*
|
|
385
|
+
* `opts.loweringMatchers` (#2843), when given, lets a call recognised by a
|
|
386
|
+
* registered lowering plugin (`queryHref`, or any userland plugin) admit
|
|
387
|
+
* its params regardless of nesting position — a ternary branch, a
|
|
388
|
+
* template-literal interpolation, a binary operand, … — matching the
|
|
389
|
+
* top-level attribute path, which already consulted the same registry
|
|
390
|
+
* before this gate ever ran. Omit it (every existing caller does) for
|
|
391
|
+
* byte-identical prior behaviour.
|
|
392
|
+
*/
|
|
393
|
+
export declare function isSupported(expr: ParsedExpr, opts?: {
|
|
394
|
+
loweringMatchers?: readonly LoweringMatcher[];
|
|
395
|
+
}): SupportResult;
|
|
385
396
|
/**
|
|
386
397
|
* Check if a parsed expression is supported at a VALUE position — a
|
|
387
398
|
* signal/memo initializer (`computeSsrSeedPlan`'s classify step: an
|
|
388
399
|
* assignment, never a render). The one behavioural difference from
|
|
389
400
|
* {@link isSupported}: an `object-literal` anywhere in the tree is admitted
|
|
390
401
|
* when every property value is itself supported, instead of being refused
|
|
391
|
-
* outright.
|
|
402
|
+
* outright. See {@link isSupported}'s doc for `opts.loweringMatchers`.
|
|
392
403
|
*/
|
|
393
|
-
export declare function isSupportedValue(expr: ParsedExpr
|
|
404
|
+
export declare function isSupportedValue(expr: ParsedExpr, opts?: {
|
|
405
|
+
loweringMatchers?: readonly LoweringMatcher[];
|
|
406
|
+
}): SupportResult;
|
|
394
407
|
/**
|
|
395
408
|
* Check if expression contains any higher-order callback method call
|
|
396
409
|
* (`.filter`/`.sort`/`.reduce`/… with an arrow argument — see
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expression-parser.d.ts","sourceRoot":"","sources":["../src/expression-parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"expression-parser.d.ts","sourceRoot":"","sources":["../src/expression-parser.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -24,14 +24,14 @@ export { JsxAdapter } from './adapters/jsx-adapter.ts';
|
|
|
24
24
|
export type { JsxAdapterConfig } from './adapters/jsx-adapter.ts';
|
|
25
25
|
export { rewriteImportsForTemplate, rewriteDynamicImportsInSource } from './adapters/template-imports.ts';
|
|
26
26
|
export { emitParsedExpr, groupBinaryOperand, groupObjectLiteralSegments, isStringTypedOperand, isStringConcatBinary } from './adapters/parsed-expr-emitter.ts';
|
|
27
|
-
export type { ParsedExprEmitter, HigherOrderMethod, ArrayMethod, SortMethod, LiteralType } from './adapters/parsed-expr-emitter.ts';
|
|
27
|
+
export type { ParsedExprEmitter, LoweringEmitter, HigherOrderMethod, ArrayMethod, SortMethod, LiteralType } from './adapters/parsed-expr-emitter.ts';
|
|
28
28
|
export { collectLoopBoundNames } from './adapters/loop-bound-names.ts';
|
|
29
29
|
export { derivesScopeFromSlot } from './adapters/child-scope.ts';
|
|
30
30
|
export { evaluateStaticLiteral, isFullyStaticLiteral, resolveStaticLoopSource } from './static-literal.ts';
|
|
31
31
|
export { importsSearchParams, searchParamsLocalNames, envSignalLocalNames, envSignalReaderFor, ENV_SIGNAL_READERS, queryHrefLocalNames, formatDateLocalNames, matchSearchParamsMethodCall } from './adapters/env-signal.ts';
|
|
32
32
|
export type { EnvSignalReader } from './adapters/env-signal.ts';
|
|
33
33
|
export { matchQueryHrefCall, queryHrefArgs, type QueryHrefCall, type QueryHrefTriple } from './query-href-lowering.ts';
|
|
34
|
-
export { registerLoweringPlugin, getLoweringPlugins, prepareLoweringMatchers, matchLoweringCall, isValidHelperId, __resetLoweringPluginsForTest, type LoweringPlugin, type LoweringNode, type LoweringTriple, type LoweringMatcher, } from './lowering-registry.ts';
|
|
34
|
+
export { registerLoweringPlugin, getLoweringPlugins, prepareLoweringMatchers, matchLoweringCall, isValidHelperId, loweringNodeChildren, __resetLoweringPluginsForTest, type LoweringPlugin, type LoweringNode, type LoweringTriple, type LoweringMatcher, } from './lowering-registry.ts';
|
|
35
35
|
export { queryHrefPlugin, registerBuiltinLoweringPlugins, BUILTIN_LOWERING_PLUGINS, } from './builtin-lowering-plugins.ts';
|
|
36
36
|
export { emitIRNode } from './adapters/ir-node-emitter.ts';
|
|
37
37
|
export type { IRNodeEmitter, EmitIRNode } from './adapters/ir-node-emitter.ts';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AACzD,YAAY,EAAE,aAAa,EAAE,cAAc,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAGzG,OAAO,EAAE,kBAAkB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAA;AAG/E,OAAO,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACjG,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAMnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAA;AAG1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,YAAY,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAGlE,YAAY,EACV,WAAW,EACX,MAAM,EACN,SAAS,EACT,MAAM,EACN,YAAY,EACZ,aAAa,EACb,MAAM,EACN,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,cAAc,EACd,WAAW,EACX,UAAU,EACV,MAAM,EACN,aAAa,EACb,UAAU,EACV,OAAO,EACP,UAAU,EACV,SAAS,EACT,WAAW,EACX,cAAc,EACd,WAAW,EACX,oBAAoB,EACpB,YAAY,EACZ,UAAU,EACV,eAAe,EACf,cAAc,EACd,MAAM,EACN,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,cAAc,EACd,cAAc,EACd,aAAa,EACb,eAAe,EACf,UAAU,EACV,aAAa,EACb,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,UAAU,GACX,MAAM,YAAY,CAAA;AAGnB,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,sBAAsB,IAAI,sBAAsB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACzR,OAAO,EAAE,sBAAsB,EAAE,KAAK,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAGvF,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AACxC,OAAO,EAAE,uBAAuB,EAAE,MAAM,0CAA0C,CAAA;AAGlF,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAG3H,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAGrD,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACrE,YAAY,EACV,eAAe,EACf,aAAa,EACb,sBAAsB,EACtB,gBAAgB,EAChB,qBAAqB,EACrB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA;AACtD,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACjE,OAAO,EAAE,yBAAyB,EAAE,6BAA6B,EAAE,MAAM,gCAAgC,CAAA;AACzG,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AAC9J,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -184,6 +184,56 @@ import ts10 from "typescript";
|
|
|
184
184
|
|
|
185
185
|
// src/expression-parser.ts
|
|
186
186
|
import ts2 from "typescript";
|
|
187
|
+
|
|
188
|
+
// src/lowering-registry.ts
|
|
189
|
+
var plugins = [];
|
|
190
|
+
function registerLoweringPlugin(plugin) {
|
|
191
|
+
const existing = plugins.findIndex((p) => p.name === plugin.name);
|
|
192
|
+
if (existing >= 0)
|
|
193
|
+
plugins[existing] = plugin;
|
|
194
|
+
else
|
|
195
|
+
plugins.push(plugin);
|
|
196
|
+
}
|
|
197
|
+
function getLoweringPlugins() {
|
|
198
|
+
return [...plugins];
|
|
199
|
+
}
|
|
200
|
+
function prepareLoweringMatchers(metadata) {
|
|
201
|
+
const matchers = [];
|
|
202
|
+
for (const plugin of plugins) {
|
|
203
|
+
const matcher = plugin.prepare(metadata);
|
|
204
|
+
if (matcher)
|
|
205
|
+
matchers.push(matcher);
|
|
206
|
+
}
|
|
207
|
+
return matchers;
|
|
208
|
+
}
|
|
209
|
+
function matchLoweringCall(callee, args, metadata) {
|
|
210
|
+
for (const matcher of prepareLoweringMatchers(metadata)) {
|
|
211
|
+
const node = matcher(callee, args);
|
|
212
|
+
if (node)
|
|
213
|
+
return node;
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
function loweringNodeChildren(node) {
|
|
218
|
+
if (node.kind === "helper-call")
|
|
219
|
+
return [...node.args];
|
|
220
|
+
const children = [node.base];
|
|
221
|
+
for (const t of node.triples) {
|
|
222
|
+
if (t.guard)
|
|
223
|
+
children.push(t.guard);
|
|
224
|
+
children.push(t.value);
|
|
225
|
+
}
|
|
226
|
+
return children;
|
|
227
|
+
}
|
|
228
|
+
function isValidHelperId(helper) {
|
|
229
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(helper);
|
|
230
|
+
}
|
|
231
|
+
function __resetLoweringPluginsForTest(next = []) {
|
|
232
|
+
plugins.length = 0;
|
|
233
|
+
plugins.push(...next);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/expression-parser.ts
|
|
187
237
|
var PARSED_EXPR_KINDS = [
|
|
188
238
|
"identifier",
|
|
189
239
|
"literal",
|
|
@@ -526,7 +576,7 @@ function convertNode(node, raw) {
|
|
|
526
576
|
}
|
|
527
577
|
if (n === undefined || Number.isNaN(n)) {
|
|
528
578
|
const parsedDepth = convertNode(depthNode, raw);
|
|
529
|
-
if (checkSupport(parsedDepth, "rendered").supported) {
|
|
579
|
+
if (checkSupport(parsedDepth, "rendered", []).supported) {
|
|
530
580
|
depthExpr = parsedDepth;
|
|
531
581
|
flatDepth = 1;
|
|
532
582
|
} else {
|
|
@@ -1304,13 +1354,13 @@ function getUnaryOperatorString(op) {
|
|
|
1304
1354
|
return "unknown";
|
|
1305
1355
|
}
|
|
1306
1356
|
}
|
|
1307
|
-
function isSupported(expr) {
|
|
1308
|
-
return checkSupport(expr, "rendered");
|
|
1357
|
+
function isSupported(expr, opts) {
|
|
1358
|
+
return checkSupport(expr, "rendered", opts?.loweringMatchers ?? []);
|
|
1309
1359
|
}
|
|
1310
|
-
function isSupportedValue(expr) {
|
|
1311
|
-
return checkSupport(expr, "value");
|
|
1360
|
+
function isSupportedValue(expr, opts) {
|
|
1361
|
+
return checkSupport(expr, "value", opts?.loweringMatchers ?? []);
|
|
1312
1362
|
}
|
|
1313
|
-
function checkSupport(expr, pos) {
|
|
1363
|
+
function checkSupport(expr, pos, matchers) {
|
|
1314
1364
|
switch (expr.kind) {
|
|
1315
1365
|
case "unsupported":
|
|
1316
1366
|
return { supported: false, reason: expr.reason };
|
|
@@ -1319,7 +1369,7 @@ function checkSupport(expr, pos) {
|
|
|
1319
1369
|
return { supported: false, reason: "Unsupported syntax: ObjectLiteralExpression" };
|
|
1320
1370
|
}
|
|
1321
1371
|
for (const prop of expr.properties) {
|
|
1322
|
-
const propSupport = checkSupport(prop.kind === "spread" ? prop.expr : prop.value, pos);
|
|
1372
|
+
const propSupport = checkSupport(prop.kind === "spread" ? prop.expr : prop.value, pos, matchers);
|
|
1323
1373
|
if (!propSupport.supported)
|
|
1324
1374
|
return propSupport;
|
|
1325
1375
|
}
|
|
@@ -1334,7 +1384,7 @@ function checkSupport(expr, pos) {
|
|
|
1334
1384
|
return { supported: false, reason: "Standalone arrow functions / regex literals are not supported" };
|
|
1335
1385
|
case "array-literal": {
|
|
1336
1386
|
for (const el of expr.elements) {
|
|
1337
|
-
const elSupport = checkSupport(el, pos);
|
|
1387
|
+
const elSupport = checkSupport(el, pos, matchers);
|
|
1338
1388
|
if (!elSupport.supported)
|
|
1339
1389
|
return elSupport;
|
|
1340
1390
|
}
|
|
@@ -1347,28 +1397,39 @@ function checkSupport(expr, pos) {
|
|
|
1347
1397
|
reason: `String.prototype.${expr.method} supports only a string pattern + string replacement (the regex form is deferred); use a string pattern or wrap the expression in /* @client */`
|
|
1348
1398
|
};
|
|
1349
1399
|
}
|
|
1350
|
-
const objSupport = checkSupport(expr.object, pos);
|
|
1400
|
+
const objSupport = checkSupport(expr.object, pos, matchers);
|
|
1351
1401
|
if (!objSupport.supported)
|
|
1352
1402
|
return objSupport;
|
|
1353
1403
|
for (const arg of expr.args) {
|
|
1354
|
-
const argSupport = checkSupport(arg, pos);
|
|
1404
|
+
const argSupport = checkSupport(arg, pos, matchers);
|
|
1355
1405
|
if (!argSupport.supported)
|
|
1356
1406
|
return argSupport;
|
|
1357
1407
|
}
|
|
1358
1408
|
if (expr.method === "flat" && expr.depthExpr) {
|
|
1359
|
-
const depthSupport = checkSupport(expr.depthExpr, pos);
|
|
1409
|
+
const depthSupport = checkSupport(expr.depthExpr, pos, matchers);
|
|
1360
1410
|
if (!depthSupport.supported)
|
|
1361
1411
|
return depthSupport;
|
|
1362
1412
|
}
|
|
1363
1413
|
return { supported: true, level: "L2" };
|
|
1364
1414
|
}
|
|
1365
1415
|
case "call": {
|
|
1416
|
+
for (const matcher of matchers) {
|
|
1417
|
+
const node = matcher(expr.callee, expr.args);
|
|
1418
|
+
if (!node)
|
|
1419
|
+
continue;
|
|
1420
|
+
for (const child of loweringNodeChildren(node)) {
|
|
1421
|
+
const childSupport = checkSupport(child, pos, matchers);
|
|
1422
|
+
if (!childSupport.supported)
|
|
1423
|
+
return childSupport;
|
|
1424
|
+
}
|
|
1425
|
+
return { supported: true, level: "L2" };
|
|
1426
|
+
}
|
|
1366
1427
|
const cb = asCallbackMethodCall(expr);
|
|
1367
1428
|
if (cb) {
|
|
1368
|
-
const objSupport = checkSupport(cb.object, pos);
|
|
1429
|
+
const objSupport = checkSupport(cb.object, pos, matchers);
|
|
1369
1430
|
if (!objSupport.supported)
|
|
1370
1431
|
return objSupport;
|
|
1371
|
-
const bodySupport = checkSupport(cb.arrow.body, pos);
|
|
1432
|
+
const bodySupport = checkSupport(cb.arrow.body, pos, matchers);
|
|
1372
1433
|
if (!bodySupport.supported) {
|
|
1373
1434
|
return {
|
|
1374
1435
|
supported: false,
|
|
@@ -1377,13 +1438,13 @@ function checkSupport(expr, pos) {
|
|
|
1377
1438
|
};
|
|
1378
1439
|
}
|
|
1379
1440
|
for (const rest of cb.args) {
|
|
1380
|
-
const restSupport = checkSupport(rest, pos);
|
|
1441
|
+
const restSupport = checkSupport(rest, pos, matchers);
|
|
1381
1442
|
if (!restSupport.supported)
|
|
1382
1443
|
return restSupport;
|
|
1383
1444
|
}
|
|
1384
1445
|
return { supported: true, level: "L5" };
|
|
1385
1446
|
}
|
|
1386
|
-
const calleeSupport = checkSupport(expr.callee, pos);
|
|
1447
|
+
const calleeSupport = checkSupport(expr.callee, pos, matchers);
|
|
1387
1448
|
if (!calleeSupport.supported) {
|
|
1388
1449
|
return calleeSupport;
|
|
1389
1450
|
}
|
|
@@ -1402,7 +1463,7 @@ function checkSupport(expr, pos) {
|
|
|
1402
1463
|
return { supported: true, level: "L1" };
|
|
1403
1464
|
}
|
|
1404
1465
|
for (const arg of expr.args) {
|
|
1405
|
-
const argSupport = checkSupport(arg, pos);
|
|
1466
|
+
const argSupport = checkSupport(arg, pos, matchers);
|
|
1406
1467
|
if (!argSupport.supported) {
|
|
1407
1468
|
return argSupport;
|
|
1408
1469
|
}
|
|
@@ -1410,7 +1471,7 @@ function checkSupport(expr, pos) {
|
|
|
1410
1471
|
return { supported: true, level: "L2" };
|
|
1411
1472
|
}
|
|
1412
1473
|
case "member": {
|
|
1413
|
-
const objSupport = checkSupport(expr.object, pos);
|
|
1474
|
+
const objSupport = checkSupport(expr.object, pos, matchers);
|
|
1414
1475
|
if (!objSupport.supported) {
|
|
1415
1476
|
return objSupport;
|
|
1416
1477
|
}
|
|
@@ -1420,19 +1481,19 @@ function checkSupport(expr, pos) {
|
|
|
1420
1481
|
return { supported: true, level: "L2" };
|
|
1421
1482
|
}
|
|
1422
1483
|
case "index-access": {
|
|
1423
|
-
const objSupport = checkSupport(expr.object, pos);
|
|
1484
|
+
const objSupport = checkSupport(expr.object, pos, matchers);
|
|
1424
1485
|
if (!objSupport.supported)
|
|
1425
1486
|
return objSupport;
|
|
1426
|
-
const indexSupport = checkSupport(expr.index, pos);
|
|
1487
|
+
const indexSupport = checkSupport(expr.index, pos, matchers);
|
|
1427
1488
|
if (!indexSupport.supported)
|
|
1428
1489
|
return indexSupport;
|
|
1429
1490
|
return { supported: true, level: "L2" };
|
|
1430
1491
|
}
|
|
1431
1492
|
case "binary": {
|
|
1432
|
-
const leftSupport = checkSupport(expr.left, pos);
|
|
1493
|
+
const leftSupport = checkSupport(expr.left, pos, matchers);
|
|
1433
1494
|
if (!leftSupport.supported)
|
|
1434
1495
|
return leftSupport;
|
|
1435
|
-
const rightSupport = checkSupport(expr.right, pos);
|
|
1496
|
+
const rightSupport = checkSupport(expr.right, pos, matchers);
|
|
1436
1497
|
if (!rightSupport.supported)
|
|
1437
1498
|
return rightSupport;
|
|
1438
1499
|
if (["===", "==", "!==", "!=", ">", "<", ">=", "<="].includes(expr.op)) {
|
|
@@ -1444,7 +1505,7 @@ function checkSupport(expr, pos) {
|
|
|
1444
1505
|
return { supported: false, reason: `Unknown operator: ${expr.op}` };
|
|
1445
1506
|
}
|
|
1446
1507
|
case "unary": {
|
|
1447
|
-
const argSupport = checkSupport(expr.argument, pos);
|
|
1508
|
+
const argSupport = checkSupport(expr.argument, pos, matchers);
|
|
1448
1509
|
if (!argSupport.supported)
|
|
1449
1510
|
return argSupport;
|
|
1450
1511
|
if (expr.op === "!") {
|
|
@@ -1456,25 +1517,25 @@ function checkSupport(expr, pos) {
|
|
|
1456
1517
|
return { supported: false, reason: `Unsupported unary operator: ${expr.op}` };
|
|
1457
1518
|
}
|
|
1458
1519
|
case "logical": {
|
|
1459
|
-
const leftSupport = checkSupport(expr.left, pos);
|
|
1520
|
+
const leftSupport = checkSupport(expr.left, pos, matchers);
|
|
1460
1521
|
if (!leftSupport.supported)
|
|
1461
1522
|
return leftSupport;
|
|
1462
1523
|
if (expr.op === "??" && expr.right.kind === "object-literal" && expr.right.properties.length === 0) {
|
|
1463
1524
|
return { supported: true, level: "L4" };
|
|
1464
1525
|
}
|
|
1465
|
-
const rightSupport = checkSupport(expr.right, pos);
|
|
1526
|
+
const rightSupport = checkSupport(expr.right, pos, matchers);
|
|
1466
1527
|
if (!rightSupport.supported)
|
|
1467
1528
|
return rightSupport;
|
|
1468
1529
|
return { supported: true, level: "L4" };
|
|
1469
1530
|
}
|
|
1470
1531
|
case "conditional": {
|
|
1471
|
-
const testSupport = checkSupport(expr.test, pos);
|
|
1532
|
+
const testSupport = checkSupport(expr.test, pos, matchers);
|
|
1472
1533
|
if (!testSupport.supported)
|
|
1473
1534
|
return testSupport;
|
|
1474
|
-
const consSupport = checkSupport(expr.consequent, pos);
|
|
1535
|
+
const consSupport = checkSupport(expr.consequent, pos, matchers);
|
|
1475
1536
|
if (!consSupport.supported)
|
|
1476
1537
|
return consSupport;
|
|
1477
|
-
const altSupport = checkSupport(expr.alternate, pos);
|
|
1538
|
+
const altSupport = checkSupport(expr.alternate, pos, matchers);
|
|
1478
1539
|
if (!altSupport.supported)
|
|
1479
1540
|
return altSupport;
|
|
1480
1541
|
return { supported: true, level: "L4" };
|
|
@@ -1482,7 +1543,7 @@ function checkSupport(expr, pos) {
|
|
|
1482
1543
|
case "template-literal": {
|
|
1483
1544
|
for (const part of expr.parts) {
|
|
1484
1545
|
if (part.type === "expression") {
|
|
1485
|
-
const partSupport = checkSupport(part.expr, pos);
|
|
1546
|
+
const partSupport = checkSupport(part.expr, pos, matchers);
|
|
1486
1547
|
if (!partSupport.supported)
|
|
1487
1548
|
return partSupport;
|
|
1488
1549
|
}
|
|
@@ -17001,45 +17062,6 @@ function collectComponentNames(node) {
|
|
|
17001
17062
|
|
|
17002
17063
|
// src/relocate.ts
|
|
17003
17064
|
import ts18 from "typescript";
|
|
17004
|
-
|
|
17005
|
-
// src/lowering-registry.ts
|
|
17006
|
-
var plugins = [];
|
|
17007
|
-
function registerLoweringPlugin(plugin) {
|
|
17008
|
-
const existing = plugins.findIndex((p) => p.name === plugin.name);
|
|
17009
|
-
if (existing >= 0)
|
|
17010
|
-
plugins[existing] = plugin;
|
|
17011
|
-
else
|
|
17012
|
-
plugins.push(plugin);
|
|
17013
|
-
}
|
|
17014
|
-
function getLoweringPlugins() {
|
|
17015
|
-
return [...plugins];
|
|
17016
|
-
}
|
|
17017
|
-
function prepareLoweringMatchers(metadata) {
|
|
17018
|
-
const matchers = [];
|
|
17019
|
-
for (const plugin of plugins) {
|
|
17020
|
-
const matcher = plugin.prepare(metadata);
|
|
17021
|
-
if (matcher)
|
|
17022
|
-
matchers.push(matcher);
|
|
17023
|
-
}
|
|
17024
|
-
return matchers;
|
|
17025
|
-
}
|
|
17026
|
-
function matchLoweringCall(callee, args, metadata) {
|
|
17027
|
-
for (const matcher of prepareLoweringMatchers(metadata)) {
|
|
17028
|
-
const node = matcher(callee, args);
|
|
17029
|
-
if (node)
|
|
17030
|
-
return node;
|
|
17031
|
-
}
|
|
17032
|
-
return null;
|
|
17033
|
-
}
|
|
17034
|
-
function isValidHelperId(helper) {
|
|
17035
|
-
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(helper);
|
|
17036
|
-
}
|
|
17037
|
-
function __resetLoweringPluginsForTest(next = []) {
|
|
17038
|
-
plugins.length = 0;
|
|
17039
|
-
plugins.push(...next);
|
|
17040
|
-
}
|
|
17041
|
-
|
|
17042
|
-
// src/relocate.ts
|
|
17043
17065
|
function classify(name, env) {
|
|
17044
17066
|
return env.bindings.get(name) ?? "global";
|
|
17045
17067
|
}
|
|
@@ -26414,6 +26436,17 @@ function emitParsedExpr(expr, emitter) {
|
|
|
26414
26436
|
case "literal":
|
|
26415
26437
|
return emitter.literal(expr.value, expr.literalType);
|
|
26416
26438
|
case "call": {
|
|
26439
|
+
if (emitter.lowering) {
|
|
26440
|
+
for (const matcher of emitter.lowering.matchers) {
|
|
26441
|
+
const node = matcher(expr.callee, expr.args);
|
|
26442
|
+
if (!node)
|
|
26443
|
+
continue;
|
|
26444
|
+
const rendered = emitter.lowering.render(node, emit);
|
|
26445
|
+
if (rendered !== null)
|
|
26446
|
+
return rendered;
|
|
26447
|
+
break;
|
|
26448
|
+
}
|
|
26449
|
+
}
|
|
26417
26450
|
const cb = asCallbackMethodCall(expr);
|
|
26418
26451
|
if (cb)
|
|
26419
26452
|
return emitter.callbackMethod(cb.method, cb.object, cb.arrow, cb.args, emit);
|
|
@@ -29741,6 +29774,7 @@ export {
|
|
|
29741
29774
|
matchQueryHrefCall,
|
|
29742
29775
|
matchLoweringCall,
|
|
29743
29776
|
makeIdCallRegex,
|
|
29777
|
+
loweringNodeChildren,
|
|
29744
29778
|
lookupStaticRecordLiteral,
|
|
29745
29779
|
listComponentFunctions as listExportedComponents,
|
|
29746
29780
|
listComponentFunctions,
|
|
@@ -112,6 +112,18 @@ export declare function prepareLoweringMatchers(metadata: IRMetadata): LoweringM
|
|
|
112
112
|
* call sites.
|
|
113
113
|
*/
|
|
114
114
|
export declare function matchLoweringCall(callee: ParsedExpr, args: readonly ParsedExpr[], metadata: IRMetadata): LoweringNode | null;
|
|
115
|
+
/**
|
|
116
|
+
* The child expressions a plugin took responsibility for inside a matched
|
|
117
|
+
* call (#2843) — the base + every triple's value/guard for a `guard-list`,
|
|
118
|
+
* or the args for a `helper-call`. Shared by the support gate
|
|
119
|
+
* (`checkSupport`'s `call` arm in `expression-parser.ts`, which recurses
|
|
120
|
+
* into these instead of refusing the call's raw argument shapes — a
|
|
121
|
+
* `guard-list`'s params object literal, for instance, would otherwise be
|
|
122
|
+
* refused before any adapter ever sees the recognised node) and any future
|
|
123
|
+
* walker that needs the same "what did this plugin actually consume"
|
|
124
|
+
* answer, so the two can't drift on what counts as consumed.
|
|
125
|
+
*/
|
|
126
|
+
export declare function loweringNodeChildren(node: LoweringNode): ParsedExpr[];
|
|
115
127
|
/**
|
|
116
128
|
* Whether a `LoweringNode.helper` id is safe to splice directly into an
|
|
117
129
|
* adapter's runtime-helper naming convention (`bf_${helper}` in Go,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lowering-registry.d.ts","sourceRoot":"","sources":["../src/lowering-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,UAAU,CAAA;CAClB;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY;AACtB;;;;;;;;;GASG;AACD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,cAAc,EAAE,CAAA;CAAE;AACrF;;;;GAIG;GACD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,UAAU,EAAE,CAAA;CAAE,CAAA;AAExE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,CAC5B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,SAAS,UAAU,EAAE,KACxB,YAAY,GAAG,IAAI,CAAA;AAExB;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,QAAQ,EAAE,UAAU,GAAG,eAAe,GAAG,IAAI,CAAA;CACtD;AAID;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAInE;AAED;8CAC8C;AAC9C,wBAAgB,kBAAkB,IAAI,SAAS,cAAc,EAAE,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,UAAU,GAAG,eAAe,EAAE,CAO/E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,SAAS,UAAU,EAAE,EAC3B,QAAQ,EAAE,UAAU,GACnB,YAAY,GAAG,IAAI,CAMrB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,GAAE,SAAS,cAAc,EAAO,GAAG,IAAI,CAGxF"}
|
|
1
|
+
{"version":3,"file":"lowering-registry.d.ts","sourceRoot":"","sources":["../src/lowering-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAE5C;;;;;;;GAOG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACxB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,UAAU,CAAA;CAClB;AAED;;;;GAIG;AACH,MAAM,MAAM,YAAY;AACtB;;;;;;;;;GASG;AACD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,cAAc,EAAE,CAAA;CAAE;AACrF;;;;GAIG;GACD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,SAAS,UAAU,EAAE,CAAA;CAAE,CAAA;AAExE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,CAC5B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,SAAS,UAAU,EAAE,KACxB,YAAY,GAAG,IAAI,CAAA;AAExB;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,QAAQ,EAAE,UAAU,GAAG,eAAe,GAAG,IAAI,CAAA;CACtD;AAID;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAInE;AAED;8CAC8C;AAC9C,wBAAgB,kBAAkB,IAAI,SAAS,cAAc,EAAE,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,UAAU,GAAG,eAAe,EAAE,CAO/E;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,SAAS,UAAU,EAAE,EAC3B,QAAQ,EAAE,UAAU,GACnB,YAAY,GAAG,IAAI,CAMrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,YAAY,GAAG,UAAU,EAAE,CAQrE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,IAAI,GAAE,SAAS,cAAc,EAAO,GAAG,IAAI,CAGxF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@barefootjs/jsx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"description": "JSX compiler for BarefootJS - transforms JSX to server HTML + client JS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"directory": "packages/jsx"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@barefootjs/shared": "0.
|
|
52
|
+
"@barefootjs/shared": "0.34.0"
|
|
53
53
|
},
|
|
54
54
|
"peerDependencies": {
|
|
55
55
|
"@barefootjs/client": ">=0.2.0",
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Registered-lowering recognition at ANY value position (#2843), not only
|
|
3
|
+
* a call's own top-level entry point. Two independent seams share this
|
|
4
|
+
* shared-layer test:
|
|
5
|
+
*
|
|
6
|
+
* - the SUPPORT GATE (`isSupported`/`isSupportedValue`, `expression-parser.ts`),
|
|
7
|
+
* which must admit a matched call's own params — even an `object-literal`,
|
|
8
|
+
* normally refused at `rendered` position — wherever it's nested
|
|
9
|
+
* (a ternary branch, a template-literal interpolation, a binary operand),
|
|
10
|
+
* by re-checking the neutral node's `loweringNodeChildren` instead of the
|
|
11
|
+
* call's raw `args`;
|
|
12
|
+
* - the shared `emitParsedExpr` DISPATCHER (`parsed-expr-emitter.ts`), whose
|
|
13
|
+
* `call` case now tries an emitter's optional `lowering` seam before its
|
|
14
|
+
* ordinary `call()`/`callbackMethod` dispatch, so an adapter that adopts
|
|
15
|
+
* it renders the matched node correctly at any nesting depth too.
|
|
16
|
+
*
|
|
17
|
+
* Uses a standalone SAMPLE plugin (independent of `queryHref`) so these tests
|
|
18
|
+
* exercise the mechanism itself, mirroring `lowering-registry.test.ts`.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { describe, test, expect, afterEach } from 'bun:test'
|
|
22
|
+
import {
|
|
23
|
+
registerLoweringPlugin,
|
|
24
|
+
getLoweringPlugins,
|
|
25
|
+
prepareLoweringMatchers,
|
|
26
|
+
__resetLoweringPluginsForTest,
|
|
27
|
+
isSupported,
|
|
28
|
+
isSupportedValue,
|
|
29
|
+
emitParsedExpr,
|
|
30
|
+
type LoweringPlugin,
|
|
31
|
+
type LoweringEmitter,
|
|
32
|
+
type ParsedExprEmitter,
|
|
33
|
+
type IRMetadata,
|
|
34
|
+
type ParsedExpr,
|
|
35
|
+
} from '../index'
|
|
36
|
+
|
|
37
|
+
// A minimal sample plugin: active only when the component imports anything
|
|
38
|
+
// from `@sample/pkg`, lowering `demo(base, { … })` to a neutral `guard-list`
|
|
39
|
+
// on the `query` helper — the exact shape `queryHref` produces, so these
|
|
40
|
+
// tests exercise the same object-literal-admission path #2743/#2841 needed.
|
|
41
|
+
const samplePlugin: LoweringPlugin = {
|
|
42
|
+
name: 'sample-value-position-demo',
|
|
43
|
+
prepare(metadata) {
|
|
44
|
+
const active = metadata.imports.some(i => i.source === '@sample/pkg' && !i.isTypeOnly)
|
|
45
|
+
if (!active) return null
|
|
46
|
+
return (callee, args) => {
|
|
47
|
+
if (callee.kind !== 'identifier' || callee.name !== 'demo') return null
|
|
48
|
+
const [base, obj] = args
|
|
49
|
+
if (!base || obj?.kind !== 'object-literal') return null
|
|
50
|
+
return {
|
|
51
|
+
kind: 'guard-list',
|
|
52
|
+
helper: 'query',
|
|
53
|
+
base,
|
|
54
|
+
triples: obj.properties
|
|
55
|
+
.filter((p): p is Extract<typeof p, { kind: 'prop' }> => p.kind === 'prop')
|
|
56
|
+
.map(p => ({ guard: null, key: p.key, value: p.value })),
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function metadataImporting(source: string): IRMetadata {
|
|
63
|
+
return { imports: [{ source, isTypeOnly: false, specifiers: [] }] } as unknown as IRMetadata
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
afterEach(() => {
|
|
67
|
+
const remaining = getLoweringPlugins().filter(p => p.name !== 'sample-value-position-demo')
|
|
68
|
+
__resetLoweringPluginsForTest(remaining)
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const base = { kind: 'literal', value: '/x', literalType: 'string' } as ParsedExpr
|
|
72
|
+
const tagValue = { kind: 'literal', value: 'a', literalType: 'string' } as ParsedExpr
|
|
73
|
+
const paramsObj = {
|
|
74
|
+
kind: 'object-literal',
|
|
75
|
+
raw: '{ tag: "a" }',
|
|
76
|
+
properties: [{ kind: 'prop', key: 'tag', shorthand: false, value: tagValue }],
|
|
77
|
+
} as ParsedExpr
|
|
78
|
+
const demoCall = { kind: 'call', callee: { kind: 'identifier', name: 'demo' }, args: [base, paramsObj] } as ParsedExpr
|
|
79
|
+
|
|
80
|
+
function matchers(): ReturnType<typeof prepareLoweringMatchers> {
|
|
81
|
+
registerLoweringPlugin(samplePlugin)
|
|
82
|
+
return prepareLoweringMatchers(metadataImporting('@sample/pkg'))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
describe('isSupported / isSupportedValue with loweringMatchers (#2843)', () => {
|
|
86
|
+
test('a matched call nested in a conditional branch is admitted at rendered position', () => {
|
|
87
|
+
const ms = matchers()
|
|
88
|
+
const cond: ParsedExpr = {
|
|
89
|
+
kind: 'conditional',
|
|
90
|
+
test: { kind: 'identifier', name: 'ok' },
|
|
91
|
+
consequent: demoCall,
|
|
92
|
+
alternate: { kind: 'literal', value: '/fallback', literalType: 'string' },
|
|
93
|
+
}
|
|
94
|
+
expect(isSupported(cond, { loweringMatchers: ms }).supported).toBe(true)
|
|
95
|
+
// Without matchers, the same tree is refused (the object-literal arg).
|
|
96
|
+
expect(isSupported(cond).supported).toBe(false)
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
test('a matched call nested in a logical operand is admitted', () => {
|
|
100
|
+
const ms = matchers()
|
|
101
|
+
const logical: ParsedExpr = {
|
|
102
|
+
kind: 'logical',
|
|
103
|
+
op: '||',
|
|
104
|
+
left: demoCall,
|
|
105
|
+
right: { kind: 'literal', value: '/fallback', literalType: 'string' },
|
|
106
|
+
}
|
|
107
|
+
expect(isSupported(logical, { loweringMatchers: ms }).supported).toBe(true)
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
test('a matched call nested in a template-literal interpolation is admitted', () => {
|
|
111
|
+
const ms = matchers()
|
|
112
|
+
const tmpl: ParsedExpr = {
|
|
113
|
+
kind: 'template-literal',
|
|
114
|
+
parts: [
|
|
115
|
+
{ type: 'string', value: 'pre ' },
|
|
116
|
+
{ type: 'expression', expr: demoCall },
|
|
117
|
+
],
|
|
118
|
+
}
|
|
119
|
+
expect(isSupported(tmpl, { loweringMatchers: ms }).supported).toBe(true)
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
test('an unmatched call inside the same shapes still refuses (no regression)', () => {
|
|
123
|
+
const ms = matchers()
|
|
124
|
+
const unmatchedCall: ParsedExpr = {
|
|
125
|
+
kind: 'call',
|
|
126
|
+
callee: { kind: 'identifier', name: 'other' },
|
|
127
|
+
args: [base, paramsObj],
|
|
128
|
+
}
|
|
129
|
+
const cond: ParsedExpr = {
|
|
130
|
+
kind: 'conditional',
|
|
131
|
+
test: { kind: 'identifier', name: 'ok' },
|
|
132
|
+
consequent: unmatchedCall,
|
|
133
|
+
alternate: { kind: 'literal', value: '/fallback', literalType: 'string' },
|
|
134
|
+
}
|
|
135
|
+
expect(isSupported(cond, { loweringMatchers: ms }).supported).toBe(false)
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
test('a matched call whose own child is unsupported still refuses, loudly (sound-or-loud)', () => {
|
|
139
|
+
const ms = matchers()
|
|
140
|
+
// The value of the one triple is itself an unsupported node (a bare
|
|
141
|
+
// arrow function) — the plugin's node still carries it as a child, so
|
|
142
|
+
// it must still be checked, not silently passed through.
|
|
143
|
+
const arrow: ParsedExpr = { kind: 'arrow', params: ['x'], body: { kind: 'identifier', name: 'x' } }
|
|
144
|
+
const badParams = {
|
|
145
|
+
kind: 'object-literal',
|
|
146
|
+
raw: '{ tag: (x) => x }',
|
|
147
|
+
properties: [{ kind: 'prop', key: 'tag', shorthand: false, value: arrow }],
|
|
148
|
+
} as ParsedExpr
|
|
149
|
+
const badCall: ParsedExpr = {
|
|
150
|
+
kind: 'call',
|
|
151
|
+
callee: { kind: 'identifier', name: 'demo' },
|
|
152
|
+
args: [base, badParams],
|
|
153
|
+
}
|
|
154
|
+
expect(isSupported(badCall, { loweringMatchers: ms }).supported).toBe(false)
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
test('isSupportedValue behaves the same way as isSupported for a matched nested call', () => {
|
|
158
|
+
const ms = matchers()
|
|
159
|
+
const cond: ParsedExpr = {
|
|
160
|
+
kind: 'conditional',
|
|
161
|
+
test: { kind: 'identifier', name: 'ok' },
|
|
162
|
+
consequent: demoCall,
|
|
163
|
+
alternate: { kind: 'literal', value: '/fallback', literalType: 'string' },
|
|
164
|
+
}
|
|
165
|
+
expect(isSupportedValue(cond, { loweringMatchers: ms }).supported).toBe(true)
|
|
166
|
+
})
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
describe('emitParsedExpr dispatch with an emitter.lowering seam (#2843)', () => {
|
|
170
|
+
// A stub emitter exercising only what the `call` case needs; every other
|
|
171
|
+
// method throws so an accidental fallthrough fails loudly in the test.
|
|
172
|
+
function stubEmitter(lowering?: LoweringEmitter): ParsedExprEmitter {
|
|
173
|
+
const unimplemented = (name: string) => () => {
|
|
174
|
+
throw new Error(`unexpected emitter.${name} call in this test`)
|
|
175
|
+
}
|
|
176
|
+
return {
|
|
177
|
+
identifier: (name: string) => `ID(${name})`,
|
|
178
|
+
literal: (v) => `LIT(${JSON.stringify(v)})`,
|
|
179
|
+
call: (callee, args, emit) => `CALL(${emit(callee)}, ${args.map(emit).join(', ')})`,
|
|
180
|
+
member: unimplemented('member'),
|
|
181
|
+
indexAccess: unimplemented('indexAccess'),
|
|
182
|
+
binary: unimplemented('binary'),
|
|
183
|
+
unary: unimplemented('unary'),
|
|
184
|
+
logical: unimplemented('logical'),
|
|
185
|
+
conditional: unimplemented('conditional'),
|
|
186
|
+
templateLiteral: unimplemented('templateLiteral'),
|
|
187
|
+
callbackMethod: unimplemented('callbackMethod'),
|
|
188
|
+
arrow: unimplemented('arrow'),
|
|
189
|
+
regex: unimplemented('regex'),
|
|
190
|
+
arrayLiteral: unimplemented('arrayLiteral'),
|
|
191
|
+
objectLiteral: (_props, raw) => `OBJ(${raw})`,
|
|
192
|
+
arrayMethod: unimplemented('arrayMethod'),
|
|
193
|
+
flatMethod: unimplemented('flatMethod'),
|
|
194
|
+
unsupported: (raw) => `UNSUPPORTED(${raw})`,
|
|
195
|
+
lowering,
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
test('a matched call renders via emitter.lowering.render, not the ordinary call() dispatch', () => {
|
|
200
|
+
const ms = matchers()
|
|
201
|
+
const lowering: LoweringEmitter = {
|
|
202
|
+
matchers: ms,
|
|
203
|
+
render: (node, emit) => {
|
|
204
|
+
if (node.kind !== 'guard-list') return null
|
|
205
|
+
const parts = node.triples.map(t => `${t.key}=${emit(t.value)}`).join('&')
|
|
206
|
+
return `QUERY(${emit(node.base)}, ${parts})`
|
|
207
|
+
},
|
|
208
|
+
}
|
|
209
|
+
expect(emitParsedExpr(demoCall, stubEmitter(lowering))).toBe('QUERY(LIT("/x"), tag=LIT("a"))')
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
test('without emitter.lowering, the same call falls through to the ordinary call() dispatch', () => {
|
|
213
|
+
expect(emitParsedExpr(demoCall, stubEmitter())).toBe('CALL(ID(demo), LIT("/x"), OBJ({ tag: "a" }))')
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
test('lowering present but the node kind/helper has no mapping falls through to call()', () => {
|
|
217
|
+
const ms = matchers()
|
|
218
|
+
const lowering: LoweringEmitter = { matchers: ms, render: () => null }
|
|
219
|
+
expect(emitParsedExpr(demoCall, stubEmitter(lowering))).toBe('CALL(ID(demo), LIT("/x"), OBJ({ tag: "a" }))')
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
test('an unmatched call is unaffected by an emitter.lowering seam', () => {
|
|
223
|
+
const ms = matchers()
|
|
224
|
+
const lowering: LoweringEmitter = { matchers: ms, render: () => 'SHOULD NOT BE REACHED' }
|
|
225
|
+
const unmatchedCall: ParsedExpr = {
|
|
226
|
+
kind: 'call',
|
|
227
|
+
callee: { kind: 'identifier', name: 'other' },
|
|
228
|
+
args: [base],
|
|
229
|
+
}
|
|
230
|
+
expect(emitParsedExpr(unmatchedCall, stubEmitter(lowering))).toBe('CALL(ID(other), LIT("/x"))')
|
|
231
|
+
})
|
|
232
|
+
})
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
|
|
36
36
|
import type { ParsedExpr, FlatDepth, TemplatePart, ObjectLiteralProperty } from '../expression-parser.ts'
|
|
37
37
|
import { asCallbackMethodCall } from '../expression-parser.ts'
|
|
38
|
+
import type { LoweringMatcher, LoweringNode } from '../lowering-registry.ts'
|
|
38
39
|
|
|
39
40
|
export type HigherOrderMethod = 'filter' | 'every' | 'some' | 'find' | 'findIndex' | 'findLast' | 'findLastIndex'
|
|
40
41
|
|
|
@@ -95,6 +96,22 @@ export type SortMethod = 'sort' | 'toSorted'
|
|
|
95
96
|
|
|
96
97
|
export type LiteralType = 'string' | 'number' | 'boolean' | 'null'
|
|
97
98
|
|
|
99
|
+
/**
|
|
100
|
+
* An adapter's registered-lowering seam for the shared `call` dispatch
|
|
101
|
+
* (#2843). `matchers` are the same `ctx.state.loweringMatchers`-style list
|
|
102
|
+
* every adapter already binds at init; `render` maps one matched neutral
|
|
103
|
+
* node to this adapter's own template syntax (its body is typically what
|
|
104
|
+
* used to live inline in the adapter's `call()` method before this seam
|
|
105
|
+
* existed — see `renderLoweringNode` in the Go adapter's `url-builder.ts`
|
|
106
|
+
* for the shape). Returning null for a `kind`/`helper` this adapter has no
|
|
107
|
+
* mapping for lets the caller fall through to the ordinary `call()`
|
|
108
|
+
* dispatch, same as an unmatched call.
|
|
109
|
+
*/
|
|
110
|
+
export interface LoweringEmitter {
|
|
111
|
+
readonly matchers: readonly LoweringMatcher[]
|
|
112
|
+
render(node: LoweringNode, emit: (e: ParsedExpr) => string): string | null
|
|
113
|
+
}
|
|
114
|
+
|
|
98
115
|
/**
|
|
99
116
|
* Adapter-side ParsedExpr lowering surface. One method per
|
|
100
117
|
* `ParsedExpr.kind`. The shared `emitParsedExpr` runner dispatches
|
|
@@ -109,6 +126,17 @@ export interface ParsedExprEmitter {
|
|
|
109
126
|
identifier(name: string): string
|
|
110
127
|
literal(value: string | number | boolean | null, literalType: LiteralType): string
|
|
111
128
|
call(callee: ParsedExpr, args: ParsedExpr[], emit: (e: ParsedExpr) => string): string
|
|
129
|
+
// Optional (#2843): when present, `emitParsedExpr`'s `call` case tries
|
|
130
|
+
// every matcher FIRST — before `call()` itself, and before the
|
|
131
|
+
// higher-order `callbackMethod` recognition — so a registered lowering
|
|
132
|
+
// plugin's call is recognised no matter where in an expression tree it
|
|
133
|
+
// sits (a ternary branch, a template-literal interpolation, a binary
|
|
134
|
+
// operand, …), not only when the adapter's own top-level conversion entry
|
|
135
|
+
// point happens to consult the registry directly. Omitted entirely by an
|
|
136
|
+
// adapter that hasn't adopted the seam (e.g. Go, which still consults the
|
|
137
|
+
// registry inline in its own `call()` per #2842) — behaviour is then
|
|
138
|
+
// byte-identical to before this field existed.
|
|
139
|
+
lowering?: LoweringEmitter
|
|
112
140
|
// `optional` is true for a `?.`-written access (`user?.name`); see the
|
|
113
141
|
// `ParsedExpr` `member` variant's docstring in `expression-parser.ts`
|
|
114
142
|
// for the single-hop caveat. Every adapter's `member()` implementation
|
|
@@ -340,6 +368,21 @@ export function emitParsedExpr(expr: ParsedExpr, emitter: ParsedExprEmitter): st
|
|
|
340
368
|
case 'literal':
|
|
341
369
|
return emitter.literal(expr.value, expr.literalType)
|
|
342
370
|
case 'call': {
|
|
371
|
+
// #2843: a registered lowering plugin's call wins in EVERY value
|
|
372
|
+
// position this dispatcher reaches, not only an adapter's own
|
|
373
|
+
// top-level conversion entry point — see `LoweringEmitter`'s doc.
|
|
374
|
+
// First-match-wins; a matched node whose `render` declines (helper id
|
|
375
|
+
// this adapter has no mapping for) falls through to the ordinary
|
|
376
|
+
// dispatch below, same as an unmatched call.
|
|
377
|
+
if (emitter.lowering) {
|
|
378
|
+
for (const matcher of emitter.lowering.matchers) {
|
|
379
|
+
const node = matcher(expr.callee, expr.args)
|
|
380
|
+
if (!node) continue
|
|
381
|
+
const rendered = emitter.lowering.render(node, emit)
|
|
382
|
+
if (rendered !== null) return rendered
|
|
383
|
+
break
|
|
384
|
+
}
|
|
385
|
+
}
|
|
343
386
|
// A higher-order callback call (`arr.filter(p)` / `arr.sort(cmp)` / …)
|
|
344
387
|
// routes to the dedicated `callbackMethod` arm; any other call is generic.
|
|
345
388
|
const cb = asCallbackMethodCall(expr)
|
package/src/expression-parser.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import ts from 'typescript'
|
|
10
|
+
import { loweringNodeChildren, type LoweringMatcher } from './lowering-registry.ts'
|
|
10
11
|
|
|
11
12
|
// =============================================================================
|
|
12
13
|
// Parsed Expression Types
|
|
@@ -1049,7 +1050,7 @@ function convertNode(node: ts.Node, raw: string): ParsedExpr {
|
|
|
1049
1050
|
// surface — the depth must be *expressible*, even if not
|
|
1050
1051
|
// known until render time.
|
|
1051
1052
|
const parsedDepth = convertNode(depthNode, raw)
|
|
1052
|
-
if (checkSupport(parsedDepth, 'rendered').supported) {
|
|
1053
|
+
if (checkSupport(parsedDepth, 'rendered', []).supported) {
|
|
1053
1054
|
depthExpr = parsedDepth
|
|
1054
1055
|
flatDepth = 1 // unused placeholder — consumers must check `depthExpr` first
|
|
1055
1056
|
} else {
|
|
@@ -2419,9 +2420,20 @@ function getUnaryOperatorString(op: ts.PrefixUnaryOperator): string {
|
|
|
2419
2420
|
* reaches the page. See {@link isSupportedValue} for the sibling VALUE-
|
|
2420
2421
|
* position entry point, and `checkSupport`'s `pos` parameter for why the two
|
|
2421
2422
|
* never converge partway through a tree.
|
|
2423
|
+
*
|
|
2424
|
+
* `opts.loweringMatchers` (#2843), when given, lets a call recognised by a
|
|
2425
|
+
* registered lowering plugin (`queryHref`, or any userland plugin) admit
|
|
2426
|
+
* its params regardless of nesting position — a ternary branch, a
|
|
2427
|
+
* template-literal interpolation, a binary operand, … — matching the
|
|
2428
|
+
* top-level attribute path, which already consulted the same registry
|
|
2429
|
+
* before this gate ever ran. Omit it (every existing caller does) for
|
|
2430
|
+
* byte-identical prior behaviour.
|
|
2422
2431
|
*/
|
|
2423
|
-
export function isSupported(
|
|
2424
|
-
|
|
2432
|
+
export function isSupported(
|
|
2433
|
+
expr: ParsedExpr,
|
|
2434
|
+
opts?: { loweringMatchers?: readonly LoweringMatcher[] },
|
|
2435
|
+
): SupportResult {
|
|
2436
|
+
return checkSupport(expr, 'rendered', opts?.loweringMatchers ?? [])
|
|
2425
2437
|
}
|
|
2426
2438
|
|
|
2427
2439
|
/**
|
|
@@ -2430,10 +2442,13 @@ export function isSupported(expr: ParsedExpr): SupportResult {
|
|
|
2430
2442
|
* assignment, never a render). The one behavioural difference from
|
|
2431
2443
|
* {@link isSupported}: an `object-literal` anywhere in the tree is admitted
|
|
2432
2444
|
* when every property value is itself supported, instead of being refused
|
|
2433
|
-
* outright.
|
|
2445
|
+
* outright. See {@link isSupported}'s doc for `opts.loweringMatchers`.
|
|
2434
2446
|
*/
|
|
2435
|
-
export function isSupportedValue(
|
|
2436
|
-
|
|
2447
|
+
export function isSupportedValue(
|
|
2448
|
+
expr: ParsedExpr,
|
|
2449
|
+
opts?: { loweringMatchers?: readonly LoweringMatcher[] },
|
|
2450
|
+
): SupportResult {
|
|
2451
|
+
return checkSupport(expr, 'value', opts?.loweringMatchers ?? [])
|
|
2437
2452
|
}
|
|
2438
2453
|
|
|
2439
2454
|
/**
|
|
@@ -2453,7 +2468,7 @@ export function isSupportedValue(expr: ParsedExpr): SupportResult {
|
|
|
2453
2468
|
*/
|
|
2454
2469
|
type ExprPos = 'rendered' | 'value'
|
|
2455
2470
|
|
|
2456
|
-
function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
2471
|
+
function checkSupport(expr: ParsedExpr, pos: ExprPos, matchers: readonly LoweringMatcher[]): SupportResult {
|
|
2457
2472
|
switch (expr.kind) {
|
|
2458
2473
|
case 'unsupported':
|
|
2459
2474
|
return { supported: false, reason: expr.reason }
|
|
@@ -2471,7 +2486,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2471
2486
|
// A spread entry's SOURCE must itself be supported at `value`
|
|
2472
2487
|
// position — the same criterion as an explicit property's value,
|
|
2473
2488
|
// since the spread source is read (not rendered) at merge time.
|
|
2474
|
-
const propSupport = checkSupport(prop.kind === 'spread' ? prop.expr : prop.value, pos)
|
|
2489
|
+
const propSupport = checkSupport(prop.kind === 'spread' ? prop.expr : prop.value, pos, matchers)
|
|
2475
2490
|
if (!propSupport.supported) return propSupport
|
|
2476
2491
|
}
|
|
2477
2492
|
return { supported: true, level: 'L2' }
|
|
@@ -2498,7 +2513,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2498
2513
|
// method, not here, because we can't see which adapter is consuming
|
|
2499
2514
|
// the IR at this point.
|
|
2500
2515
|
for (const el of expr.elements) {
|
|
2501
|
-
const elSupport = checkSupport(el, pos)
|
|
2516
|
+
const elSupport = checkSupport(el, pos, matchers)
|
|
2502
2517
|
if (!elSupport.supported) return elSupport
|
|
2503
2518
|
}
|
|
2504
2519
|
return { supported: true, level: 'L2' }
|
|
@@ -2518,10 +2533,10 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2518
2533
|
}
|
|
2519
2534
|
}
|
|
2520
2535
|
// Receiver/args inherit `pos` (see `ExprPos`'s doc).
|
|
2521
|
-
const objSupport = checkSupport(expr.object, pos)
|
|
2536
|
+
const objSupport = checkSupport(expr.object, pos, matchers)
|
|
2522
2537
|
if (!objSupport.supported) return objSupport
|
|
2523
2538
|
for (const arg of expr.args) {
|
|
2524
|
-
const argSupport = checkSupport(arg, pos)
|
|
2539
|
+
const argSupport = checkSupport(arg, pos, matchers)
|
|
2525
2540
|
if (!argSupport.supported) return argSupport
|
|
2526
2541
|
}
|
|
2527
2542
|
// A dynamic `.flat(depth)` carries its depth expression outside
|
|
@@ -2532,7 +2547,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2532
2547
|
// any `array-method`/`flat` node regardless of how it was constructed
|
|
2533
2548
|
// (e.g. by a rewrite walker).
|
|
2534
2549
|
if (expr.method === 'flat' && expr.depthExpr) {
|
|
2535
|
-
const depthSupport = checkSupport(expr.depthExpr, pos)
|
|
2550
|
+
const depthSupport = checkSupport(expr.depthExpr, pos, matchers)
|
|
2536
2551
|
if (!depthSupport.supported) return depthSupport
|
|
2537
2552
|
}
|
|
2538
2553
|
return { supported: true, level: 'L2' }
|
|
@@ -2540,6 +2555,25 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2540
2555
|
|
|
2541
2556
|
|
|
2542
2557
|
case 'call': {
|
|
2558
|
+
// #2843: a call a registered lowering plugin recognises (`queryHref`,
|
|
2559
|
+
// or any userland plugin) is admitted regardless of where it sits in
|
|
2560
|
+
// the tree — the neutral node's OWN children (`loweringNodeChildren`)
|
|
2561
|
+
// are re-checked at the current `pos` instead of the call's raw
|
|
2562
|
+
// `args`, so e.g. `queryHref`'s params object literal (refused at
|
|
2563
|
+
// `rendered` position by the `object-literal` case above) doesn't
|
|
2564
|
+
// reach that refusal at all: the plugin already took responsibility
|
|
2565
|
+
// for it. Tried before `asCallbackMethodCall` and the generic per-arg
|
|
2566
|
+
// loop below, matching the precedence the top-level attribute path
|
|
2567
|
+
// already gives the registry.
|
|
2568
|
+
for (const matcher of matchers) {
|
|
2569
|
+
const node = matcher(expr.callee, expr.args)
|
|
2570
|
+
if (!node) continue
|
|
2571
|
+
for (const child of loweringNodeChildren(node)) {
|
|
2572
|
+
const childSupport = checkSupport(child, pos, matchers)
|
|
2573
|
+
if (!childSupport.supported) return childSupport
|
|
2574
|
+
}
|
|
2575
|
+
return { supported: true, level: 'L2' }
|
|
2576
|
+
}
|
|
2543
2577
|
// Higher-order callback methods (`.filter`/`.sort`/`.reduce`/… with an
|
|
2544
2578
|
// arrow argument) lower via the runtime evaluator (#2018). Supported iff
|
|
2545
2579
|
// the receiver and the callback BODY are supported. Recognised before the
|
|
@@ -2558,9 +2592,9 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2558
2592
|
// one (a signal/memo initializer) admits it.
|
|
2559
2593
|
const cb = asCallbackMethodCall(expr)
|
|
2560
2594
|
if (cb) {
|
|
2561
|
-
const objSupport = checkSupport(cb.object, pos)
|
|
2595
|
+
const objSupport = checkSupport(cb.object, pos, matchers)
|
|
2562
2596
|
if (!objSupport.supported) return objSupport
|
|
2563
|
-
const bodySupport = checkSupport(cb.arrow.body, pos)
|
|
2597
|
+
const bodySupport = checkSupport(cb.arrow.body, pos, matchers)
|
|
2564
2598
|
if (!bodySupport.supported) {
|
|
2565
2599
|
return {
|
|
2566
2600
|
supported: false,
|
|
@@ -2569,7 +2603,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2569
2603
|
}
|
|
2570
2604
|
}
|
|
2571
2605
|
for (const rest of cb.args) {
|
|
2572
|
-
const restSupport = checkSupport(rest, pos)
|
|
2606
|
+
const restSupport = checkSupport(rest, pos, matchers)
|
|
2573
2607
|
if (!restSupport.supported) return restSupport
|
|
2574
2608
|
}
|
|
2575
2609
|
return { supported: true, level: 'L5' }
|
|
@@ -2577,7 +2611,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2577
2611
|
|
|
2578
2612
|
// Check if callee is supported. Not container contents — inherits
|
|
2579
2613
|
// the CURRENT `pos` (see `ExprPos`'s doc).
|
|
2580
|
-
const calleeSupport = checkSupport(expr.callee, pos)
|
|
2614
|
+
const calleeSupport = checkSupport(expr.callee, pos, matchers)
|
|
2581
2615
|
if (!calleeSupport.supported) {
|
|
2582
2616
|
return calleeSupport
|
|
2583
2617
|
}
|
|
@@ -2610,7 +2644,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2610
2644
|
// recognised callback/array-method (that path returned above) —
|
|
2611
2645
|
// inherits the CURRENT `pos` (see `ExprPos`'s doc).
|
|
2612
2646
|
for (const arg of expr.args) {
|
|
2613
|
-
const argSupport = checkSupport(arg, pos)
|
|
2647
|
+
const argSupport = checkSupport(arg, pos, matchers)
|
|
2614
2648
|
if (!argSupport.supported) {
|
|
2615
2649
|
return argSupport
|
|
2616
2650
|
}
|
|
@@ -2620,7 +2654,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2620
2654
|
|
|
2621
2655
|
case 'member': {
|
|
2622
2656
|
// Not container contents — inherits the CURRENT `pos`.
|
|
2623
|
-
const objSupport = checkSupport(expr.object, pos)
|
|
2657
|
+
const objSupport = checkSupport(expr.object, pos, matchers)
|
|
2624
2658
|
if (!objSupport.supported) {
|
|
2625
2659
|
return objSupport
|
|
2626
2660
|
}
|
|
@@ -2636,9 +2670,9 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2636
2670
|
// expression are themselves supported (the index is typically a
|
|
2637
2671
|
// loop variable or arithmetic over one). #1897 (data-table). Neither
|
|
2638
2672
|
// is container contents — both inherit the CURRENT `pos`.
|
|
2639
|
-
const objSupport = checkSupport(expr.object, pos)
|
|
2673
|
+
const objSupport = checkSupport(expr.object, pos, matchers)
|
|
2640
2674
|
if (!objSupport.supported) return objSupport
|
|
2641
|
-
const indexSupport = checkSupport(expr.index, pos)
|
|
2675
|
+
const indexSupport = checkSupport(expr.index, pos, matchers)
|
|
2642
2676
|
if (!indexSupport.supported) return indexSupport
|
|
2643
2677
|
return { supported: true, level: 'L2' }
|
|
2644
2678
|
}
|
|
@@ -2646,9 +2680,9 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2646
2680
|
case 'binary': {
|
|
2647
2681
|
// Operands inherit the CURRENT `pos` (see `ExprPos`'s doc) — a binary
|
|
2648
2682
|
// operand isn't container contents.
|
|
2649
|
-
const leftSupport = checkSupport(expr.left, pos)
|
|
2683
|
+
const leftSupport = checkSupport(expr.left, pos, matchers)
|
|
2650
2684
|
if (!leftSupport.supported) return leftSupport
|
|
2651
|
-
const rightSupport = checkSupport(expr.right, pos)
|
|
2685
|
+
const rightSupport = checkSupport(expr.right, pos, matchers)
|
|
2652
2686
|
if (!rightSupport.supported) return rightSupport
|
|
2653
2687
|
|
|
2654
2688
|
// Comparison operators are L3
|
|
@@ -2666,7 +2700,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2666
2700
|
|
|
2667
2701
|
case 'unary': {
|
|
2668
2702
|
// Inherits the CURRENT `pos` — not container contents.
|
|
2669
|
-
const argSupport = checkSupport(expr.argument, pos)
|
|
2703
|
+
const argSupport = checkSupport(expr.argument, pos, matchers)
|
|
2670
2704
|
if (!argSupport.supported) return argSupport
|
|
2671
2705
|
|
|
2672
2706
|
// Negation is L4
|
|
@@ -2683,7 +2717,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2683
2717
|
|
|
2684
2718
|
case 'logical': {
|
|
2685
2719
|
// Operands inherit the CURRENT `pos` — not container contents.
|
|
2686
|
-
const leftSupport = checkSupport(expr.left, pos)
|
|
2720
|
+
const leftSupport = checkSupport(expr.left, pos, matchers)
|
|
2687
2721
|
if (!leftSupport.supported) return leftSupport
|
|
2688
2722
|
|
|
2689
2723
|
// `x ?? {}` — admit an EMPTY object-literal fallback as the right
|
|
@@ -2710,7 +2744,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2710
2744
|
return { supported: true, level: 'L4' }
|
|
2711
2745
|
}
|
|
2712
2746
|
|
|
2713
|
-
const rightSupport = checkSupport(expr.right, pos)
|
|
2747
|
+
const rightSupport = checkSupport(expr.right, pos, matchers)
|
|
2714
2748
|
if (!rightSupport.supported) return rightSupport
|
|
2715
2749
|
|
|
2716
2750
|
return { supported: true, level: 'L4' }
|
|
@@ -2722,11 +2756,11 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2722
2756
|
// position both branches are themselves rendered — `cond ? {a:1} :
|
|
2723
2757
|
// {b:2}` stays refused there, not admitted just for being a
|
|
2724
2758
|
// sub-expression.
|
|
2725
|
-
const testSupport = checkSupport(expr.test, pos)
|
|
2759
|
+
const testSupport = checkSupport(expr.test, pos, matchers)
|
|
2726
2760
|
if (!testSupport.supported) return testSupport
|
|
2727
|
-
const consSupport = checkSupport(expr.consequent, pos)
|
|
2761
|
+
const consSupport = checkSupport(expr.consequent, pos, matchers)
|
|
2728
2762
|
if (!consSupport.supported) return consSupport
|
|
2729
|
-
const altSupport = checkSupport(expr.alternate, pos)
|
|
2763
|
+
const altSupport = checkSupport(expr.alternate, pos, matchers)
|
|
2730
2764
|
if (!altSupport.supported) return altSupport
|
|
2731
2765
|
|
|
2732
2766
|
return { supported: true, level: 'L4' }
|
|
@@ -2738,7 +2772,7 @@ function checkSupport(expr: ParsedExpr, pos: ExprPos): SupportResult {
|
|
|
2738
2772
|
// object-literal hole has no sensible rendering either way).
|
|
2739
2773
|
for (const part of expr.parts) {
|
|
2740
2774
|
if (part.type === 'expression') {
|
|
2741
|
-
const partSupport = checkSupport(part.expr, pos)
|
|
2775
|
+
const partSupport = checkSupport(part.expr, pos, matchers)
|
|
2742
2776
|
if (!partSupport.supported) return partSupport
|
|
2743
2777
|
}
|
|
2744
2778
|
}
|
package/src/index.ts
CHANGED
|
@@ -101,7 +101,7 @@ export { JsxAdapter } from './adapters/jsx-adapter.ts'
|
|
|
101
101
|
export type { JsxAdapterConfig } from './adapters/jsx-adapter.ts'
|
|
102
102
|
export { rewriteImportsForTemplate, rewriteDynamicImportsInSource } from './adapters/template-imports.ts'
|
|
103
103
|
export { emitParsedExpr, groupBinaryOperand, groupObjectLiteralSegments, isStringTypedOperand, isStringConcatBinary } from './adapters/parsed-expr-emitter.ts'
|
|
104
|
-
export type { ParsedExprEmitter, HigherOrderMethod, ArrayMethod, SortMethod, LiteralType } from './adapters/parsed-expr-emitter.ts'
|
|
104
|
+
export type { ParsedExprEmitter, LoweringEmitter, HigherOrderMethod, ArrayMethod, SortMethod, LiteralType } from './adapters/parsed-expr-emitter.ts'
|
|
105
105
|
export { collectLoopBoundNames } from './adapters/loop-bound-names.ts'
|
|
106
106
|
export { derivesScopeFromSlot } from './adapters/child-scope.ts'
|
|
107
107
|
export { evaluateStaticLiteral, isFullyStaticLiteral, resolveStaticLoopSource } from './static-literal.ts'
|
|
@@ -114,6 +114,7 @@ export {
|
|
|
114
114
|
prepareLoweringMatchers,
|
|
115
115
|
matchLoweringCall,
|
|
116
116
|
isValidHelperId,
|
|
117
|
+
loweringNodeChildren,
|
|
117
118
|
__resetLoweringPluginsForTest,
|
|
118
119
|
type LoweringPlugin,
|
|
119
120
|
type LoweringNode,
|
package/src/lowering-registry.ts
CHANGED
|
@@ -141,6 +141,27 @@ export function matchLoweringCall(
|
|
|
141
141
|
return null
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
/**
|
|
145
|
+
* The child expressions a plugin took responsibility for inside a matched
|
|
146
|
+
* call (#2843) — the base + every triple's value/guard for a `guard-list`,
|
|
147
|
+
* or the args for a `helper-call`. Shared by the support gate
|
|
148
|
+
* (`checkSupport`'s `call` arm in `expression-parser.ts`, which recurses
|
|
149
|
+
* into these instead of refusing the call's raw argument shapes — a
|
|
150
|
+
* `guard-list`'s params object literal, for instance, would otherwise be
|
|
151
|
+
* refused before any adapter ever sees the recognised node) and any future
|
|
152
|
+
* walker that needs the same "what did this plugin actually consume"
|
|
153
|
+
* answer, so the two can't drift on what counts as consumed.
|
|
154
|
+
*/
|
|
155
|
+
export function loweringNodeChildren(node: LoweringNode): ParsedExpr[] {
|
|
156
|
+
if (node.kind === 'helper-call') return [...node.args]
|
|
157
|
+
const children: ParsedExpr[] = [node.base]
|
|
158
|
+
for (const t of node.triples) {
|
|
159
|
+
if (t.guard) children.push(t.guard)
|
|
160
|
+
children.push(t.value)
|
|
161
|
+
}
|
|
162
|
+
return children
|
|
163
|
+
}
|
|
164
|
+
|
|
144
165
|
/**
|
|
145
166
|
* Whether a `LoweringNode.helper` id is safe to splice directly into an
|
|
146
167
|
* adapter's runtime-helper naming convention (`bf_${helper}` in Go,
|