@barefootjs/jsx 0.23.0 → 0.25.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/analyzer.d.ts.map +1 -1
- package/dist/errors.d.ts +2 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/format-date-lowering.d.ts +6 -3
- package/dist/format-date-lowering.d.ts.map +1 -1
- package/dist/index.js +696 -108
- package/dist/ir-to-client-js/emit-reactive.d.ts.map +1 -1
- package/dist/jsx-to-ir.d.ts.map +1 -1
- package/dist/to-locale-date-lowering.d.ts +62 -23
- package/dist/to-locale-date-lowering.d.ts.map +1 -1
- package/dist/types.d.ts +47 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/format-date-lowering.test.ts +22 -6
- package/src/__tests__/reactive-factory-cross-file.test.ts +845 -0
- package/src/__tests__/reactive-factory-inlining.test.ts +527 -1
- package/src/__tests__/reactive-factory-rename-fidelity.test.ts +318 -0
- package/src/__tests__/to-locale-date-lowering.test.ts +203 -2
- package/src/analyzer.ts +730 -131
- package/src/errors.ts +10 -0
- package/src/format-date-lowering.ts +9 -5
- package/src/ir-to-client-js/emit-reactive.ts +14 -4
- package/src/jsx-to-ir.ts +15 -4
- package/src/to-locale-date-lowering.ts +437 -49
- package/src/types.ts +49 -3
package/src/errors.ts
CHANGED
|
@@ -89,6 +89,8 @@ export const ErrorCodes = {
|
|
|
89
89
|
UNRECOGNIZED_REACTIVE_FACTORY: 'BF110',
|
|
90
90
|
REACTIVE_FACTORY_RENAME_UNSUPPORTED: 'BF111',
|
|
91
91
|
REACTIVE_FACTORY_MODULE_CAPTURE: 'BF112',
|
|
92
|
+
REACTIVE_FACTORY_IMPORT_COLLISION: 'BF113',
|
|
93
|
+
REACTIVE_FACTORY_PARAM_SHADOWED: 'BF114',
|
|
92
94
|
} as const
|
|
93
95
|
|
|
94
96
|
export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]
|
|
@@ -178,6 +180,14 @@ const errorMessages: Record<ErrorCode, string> = {
|
|
|
178
180
|
'body cannot be inlined into the component file. Move those helpers into the ' +
|
|
179
181
|
'component file, pass them to the factory as parameters, or define the factory ' +
|
|
180
182
|
'in the component file.',
|
|
183
|
+
|
|
184
|
+
[ErrorCodes.REACTIVE_FACTORY_IMPORT_COLLISION]:
|
|
185
|
+
'Inlining an imported reactive factory requires re-importing one of its helper ' +
|
|
186
|
+
'imports into this file, but that name is already bound here to something else. ' +
|
|
187
|
+
"Rename the conflicting binding in this file, or alias the import in the factory's own file.",
|
|
188
|
+
|
|
189
|
+
[ErrorCodes.REACTIVE_FACTORY_PARAM_SHADOWED]:
|
|
190
|
+
'Reactive factory parameter is shadowed by a nested declaration inside the factory body, so argument substitution at the inline site would be ambiguous. Rename the inner binding so it does not collide with the parameter.',
|
|
181
191
|
}
|
|
182
192
|
|
|
183
193
|
// =============================================================================
|
|
@@ -21,11 +21,15 @@ import type { LoweringNode, LoweringPlugin } from './lowering-registry.ts'
|
|
|
21
21
|
import { formatDateLocalNames } from './adapters/env-signal.ts'
|
|
22
22
|
|
|
23
23
|
const UTC_LITERAL: ParsedExpr = { kind: 'literal', value: 'UTC', literalType: 'string' }
|
|
24
|
+
const EMPTY_NAMES: ParsedExpr = { kind: 'array-literal', elements: [], raw: '[]' } as ParsedExpr
|
|
24
25
|
|
|
25
26
|
/**
|
|
26
|
-
* Recognise `formatDate(date, pattern[, timeZone])` against the
|
|
27
|
-
* local import bindings, or decline (null): a non-identifier
|
|
28
|
-
* not bound to the `@barefootjs/client` import, or an arity
|
|
27
|
+
* Recognise `formatDate(date, pattern[, timeZone[, names]])` against the
|
|
28
|
+
* component's local import bindings, or decline (null): a non-identifier
|
|
29
|
+
* callee, a name not bound to the `@barefootjs/client` import, or an arity
|
|
30
|
+
* outside 2–4. The canonical helper arity is 4 (#2334): omitted `timeZone` /
|
|
31
|
+
* `names` normalize to the `'UTC'` literal and the empty table the client
|
|
32
|
+
* function defaults to, so backend helpers stay fixed-arity.
|
|
29
33
|
*/
|
|
30
34
|
export function matchFormatDateCall(
|
|
31
35
|
callee: ParsedExpr,
|
|
@@ -33,11 +37,11 @@ export function matchFormatDateCall(
|
|
|
33
37
|
locals: ReadonlySet<string>,
|
|
34
38
|
): LoweringNode | null {
|
|
35
39
|
if (callee.kind !== 'identifier' || !locals.has(callee.name)) return null
|
|
36
|
-
if (args.length < 2 || args.length >
|
|
40
|
+
if (args.length < 2 || args.length > 4) return null
|
|
37
41
|
return {
|
|
38
42
|
kind: 'helper-call',
|
|
39
43
|
helper: 'format_date',
|
|
40
|
-
args: [args[0], args[1], args[2] ?? UTC_LITERAL],
|
|
44
|
+
args: [args[0], args[1], args[2] ?? UTC_LITERAL, args[3] ?? EMPTY_NAMES],
|
|
41
45
|
}
|
|
42
46
|
}
|
|
43
47
|
|
|
@@ -11,7 +11,7 @@ import type { ClientJsContext } from './types.ts'
|
|
|
11
11
|
import { toHtmlAttrName, varSlotId, PROPS_PARAM } from './utils.ts'
|
|
12
12
|
import { createTemplateAwareStringProtector } from './html-template.ts'
|
|
13
13
|
import { datePlugin, DATE_METHODS } from '../date-lowering.ts'
|
|
14
|
-
import { toLocaleDatePlugin } from '../to-locale-date-lowering.ts'
|
|
14
|
+
import { toLocaleDatePlugin, foldedArgToClientJs } from '../to-locale-date-lowering.ts'
|
|
15
15
|
import { tsNodeToParsedExpr } from '../expression-parser.ts'
|
|
16
16
|
import type { LoweringMatcher } from '../lowering-registry.ts'
|
|
17
17
|
|
|
@@ -181,8 +181,17 @@ function lowerToLocaleCallsInReactiveExpr(expr: string, matcher: LoweringMatcher
|
|
|
181
181
|
call.arguments.map((a) => tsNodeToParsedExpr(a)),
|
|
182
182
|
)
|
|
183
183
|
if (!node || node.kind !== 'helper-call' || node.helper !== 'format_date') continue
|
|
184
|
-
const [, patternArg, tzArg] = node.args
|
|
185
|
-
if (patternArg
|
|
184
|
+
const [, patternArg, tzArg, namesArg] = node.args
|
|
185
|
+
if (!patternArg || tzArg?.kind !== 'literal') continue
|
|
186
|
+
const localeText = call.arguments[0].getText(sourceFile)
|
|
187
|
+
const patternJs = foldedArgToClientJs(patternArg, localeText)
|
|
188
|
+
if (patternJs === null) continue
|
|
189
|
+
// The names table (#2334) — omitted when empty, same as the static path.
|
|
190
|
+
let namesJs: string | null = null
|
|
191
|
+
if (namesArg && !(namesArg.kind === 'array-literal' && namesArg.elements.length === 0)) {
|
|
192
|
+
namesJs = foldedArgToClientJs(namesArg, localeText)
|
|
193
|
+
if (namesJs === null) continue
|
|
194
|
+
}
|
|
186
195
|
const receiverText = propAccess.expression.getText(sourceFile)
|
|
187
196
|
const matchText = call.getText(sourceFile)
|
|
188
197
|
// The call text contains string literals (placeholders in the protected
|
|
@@ -191,7 +200,8 @@ function lowerToLocaleCallsInReactiveExpr(expr: string, matcher: LoweringMatcher
|
|
|
191
200
|
result = replaceProtectedCall(
|
|
192
201
|
result,
|
|
193
202
|
matchText,
|
|
194
|
-
() =>
|
|
203
|
+
() =>
|
|
204
|
+
`formatDate(${receiverText}, ${patternJs}, ${JSON.stringify(tzArg.value)}${namesJs !== null ? `, ${namesJs}` : ''})`,
|
|
195
205
|
)
|
|
196
206
|
}
|
|
197
207
|
return restore(result)
|
package/src/jsx-to-ir.ts
CHANGED
|
@@ -49,7 +49,7 @@ import { resolveFreeRefs, isNameBound as isNameBoundInEnv, type BindingEnvironme
|
|
|
49
49
|
import { computeFileScope } from './ir-to-client-js/component-scope.ts'
|
|
50
50
|
import { createTemplateAwareStringProtector } from './ir-to-client-js/html-template.ts'
|
|
51
51
|
import { datePlugin, DATE_METHODS } from './date-lowering.ts'
|
|
52
|
-
import { toLocaleDatePlugin } from './to-locale-date-lowering.ts'
|
|
52
|
+
import { toLocaleDatePlugin, foldedArgToClientJs } from './to-locale-date-lowering.ts'
|
|
53
53
|
import type { LoweringMatcher } from './lowering-registry.ts'
|
|
54
54
|
import { extractFreeIdentifiersFromNode, initializerShapeContainsJsx } from './analyzer.ts'
|
|
55
55
|
import { iterateJsTokens, replaceInExprContexts } from './scanner/js-scanner.ts'
|
|
@@ -462,8 +462,18 @@ function lowerToLocaleDateCalls(text: string, expr: ts.Node, ctx: TransformConte
|
|
|
462
462
|
call.arguments.map((a) => tsNodeToParsedExpr(a)),
|
|
463
463
|
)
|
|
464
464
|
if (!node || node.kind !== 'helper-call' || node.helper !== 'format_date') continue
|
|
465
|
-
const [, patternArg, tzArg] = node.args
|
|
466
|
-
if (patternArg
|
|
465
|
+
const [, patternArg, tzArg, namesArg] = node.args
|
|
466
|
+
if (!patternArg || tzArg?.kind !== 'literal') continue
|
|
467
|
+
const localeText = ctx.getJS(call.arguments[0])
|
|
468
|
+
const patternJs = foldedArgToClientJs(patternArg, localeText)
|
|
469
|
+
if (patternJs === null) continue
|
|
470
|
+
// The names table (#2334) — omitted from the client call when empty
|
|
471
|
+
// (the client function defaults to []).
|
|
472
|
+
let namesJs: string | null = null
|
|
473
|
+
if (namesArg && !(namesArg.kind === 'array-literal' && namesArg.elements.length === 0)) {
|
|
474
|
+
namesJs = foldedArgToClientJs(namesArg, localeText)
|
|
475
|
+
if (namesJs === null) continue
|
|
476
|
+
}
|
|
467
477
|
const receiverText = ctx.getJS(propAccess.expression)
|
|
468
478
|
const matchText = ctx.getJS(call)
|
|
469
479
|
// Unlike `lowerDateCalls`' zero-arg needle, this call text CONTAINS
|
|
@@ -473,7 +483,8 @@ function lowerToLocaleDateCalls(text: string, expr: ts.Node, ctx: TransformConte
|
|
|
473
483
|
result = replaceProtectedCall(
|
|
474
484
|
result,
|
|
475
485
|
matchText,
|
|
476
|
-
() =>
|
|
486
|
+
() =>
|
|
487
|
+
`formatDate(${receiverText}, ${patternJs}, ${JSON.stringify(tzArg.value)}${namesJs !== null ? `, ${namesJs}` : ''})`,
|
|
477
488
|
)
|
|
478
489
|
}
|
|
479
490
|
return restore(result)
|