Skip to content

Commit 0fa4f3c

Browse files
committed
Fix hierarchical params regressions and restore derive callbacks
1 parent a5ad113 commit 0fa4f3c

14 files changed

+55
-33
lines changed

packages/deno-web-test/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ async function copy(src: string, dest: string): Promise<void> {
8181
} else if (stat.isDirectory) {
8282
await copyDir(src, dest);
8383
} else {
84+
await Deno.mkdir(path.dirname(dest), { recursive: true });
8485
await Deno.copyFile(src, dest);
8586
}
8687
}

packages/ts-transformers/src/transformers/builtins/derive.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -204,16 +204,6 @@ function createDeriveArgs(
204204
}
205205
}
206206

207-
if (properties.length === 1 && fallbackEntries.length === 0) {
208-
const first = captureTree.values().next();
209-
if (!first.done) {
210-
const node = first.value;
211-
if (node.expression && node.properties.size === 0) {
212-
return [node.expression];
213-
}
214-
}
215-
}
216-
217207
return [
218208
factory.createObjectLiteralExpression(properties, properties.length > 1),
219209
];

packages/ts-transformers/src/utils/identifiers.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,20 @@ export interface UniqueIdentifierOptions extends SanitizeIdentifierOptions {
1313

1414
export function isSafeIdentifierText(name: string): boolean {
1515
if (name.length === 0) return false;
16-
const first = name.codePointAt(0)!;
17-
if (!ts.isIdentifierStart(first, ts.ScriptTarget.ESNext)) {
16+
const codePoints = Array.from(name);
17+
const first = codePoints[0]?.codePointAt(0);
18+
if (
19+
first === undefined ||
20+
!ts.isIdentifierStart(first, ts.ScriptTarget.ESNext)
21+
) {
1822
return false;
1923
}
20-
for (let i = 1; i < name.length; i++) {
21-
const code = name.codePointAt(i)!;
22-
if (!ts.isIdentifierPart(code, ts.ScriptTarget.ESNext)) {
24+
for (const codePoint of codePoints.slice(1)) {
25+
const code = codePoint.codePointAt(0);
26+
if (
27+
code === undefined ||
28+
!ts.isIdentifierPart(code, ts.ScriptTarget.ESNext)
29+
) {
2330
return false;
2431
}
2532
}
@@ -53,7 +60,11 @@ export function sanitizeIdentifierCandidate(
5360
return DEFAULT_FALLBACK;
5461
}
5562

56-
if (!ts.isIdentifierStart(text.charCodeAt(0), ts.ScriptTarget.ESNext)) {
63+
const first = text.codePointAt(0);
64+
if (
65+
first === undefined ||
66+
!ts.isIdentifierStart(first, ts.ScriptTarget.ESNext)
67+
) {
5768
text = `${DEFAULT_FALLBACK}${text}`;
5869
}
5970

@@ -79,7 +90,11 @@ export function sanitizeIdentifierCandidate(
7990

8091
const ensureIdentifierStart = (text: string): string => {
8192
if (text.length === 0) return fallback;
82-
if (ts.isIdentifierStart(text.charCodeAt(0), ts.ScriptTarget.ESNext)) {
93+
const first = text.codePointAt(0);
94+
if (
95+
first !== undefined &&
96+
ts.isIdentifierStart(first, ts.ScriptTarget.ESNext)
97+
) {
8398
return text;
8499
}
85100
return `${fallback}${text}`;

packages/ts-transformers/test/fixtures/ast-transform/builder-conditional.expected.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export default recipe({
2121
return {
2222
[NAME]: state.label,
2323
[UI]: (<section>
24-
{__ctHelpers.ifElse(__ctHelpers.derive(state, ({ state }) => state && state.count > 0), <p>Positive</p>, <p>Non-positive</p>)}
24+
{__ctHelpers.ifElse(__ctHelpers.derive(state, (state) => state && state.count > 0), <p>Positive</p>, <p>Non-positive</p>)}
2525
</section>),
2626
};
2727
});

packages/ts-transformers/test/fixtures/closures/map-computed-alias-side-effect.expected.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,13 @@ export default recipe({
4242
}
4343
},
4444
required: ["element", "params"]
45-
} as const satisfies __ctHelpers.JSONSchema, ({ element: { [nextKey()]: amount }, params: {} }) => (<span>{amount}</span>)), {})}
45+
} as const satisfies __ctHelpers.JSONSchema, ({ element, params: {} }) => {
46+
const __ct_amount_key = nextKey();
47+
return (<span>{__ctHelpers.derive({
48+
element,
49+
__ct_amount_key
50+
}, ({ element: element, __ct_amount_key: __ct_amount_key }) => element[__ct_amount_key])}</span>);
51+
}), {})}
4652
</div>),
4753
};
4854
});

packages/ts-transformers/test/fixtures/closures/map-outer-element.expected.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export default recipe({
2929
element: {
3030
type: "number"
3131
},
32+
index: {
33+
type: "number"
34+
},
3235
params: {
3336
type: "object",
3437
properties: {
@@ -41,7 +44,7 @@ export default recipe({
4144
}
4245
},
4346
required: ["element", "params"]
44-
} as const satisfies __ctHelpers.JSONSchema, ({ element: __ct_element, params: { element } }) => (<span>{element}</span>)), {
47+
} as const satisfies __ctHelpers.JSONSchema, ({ element: __ct_element, index: index, params: { element } }) => (<span key={index}>{element}</span>)), {
4548
element: element
4649
})}
4750
</div>),

packages/ts-transformers/test/fixtures/closures/map-outer-element.input.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ export default recipe<State>("MapOuterElement", (state) => {
1111
return {
1212
[UI]: (
1313
<div>
14-
{state.items.map(() => (
15-
<span>{element}</span>
14+
{state.items.map((_, index) => (
15+
<span key={index}>{element}</span>
1616
))}
1717
</div>
1818
),

packages/ts-transformers/test/fixtures/jsx-expressions/map-array-length-conditional.expected.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default recipe("MapArrayLengthConditional", (_state) => {
44
const list = cell(["apple", "banana", "cherry"]);
55
return {
66
[UI]: (<div>
7-
{__ctHelpers.derive(list, ({ list }) => list.length > 0 && (<div>
7+
{__ctHelpers.derive(list, (list) => list.length > 0 && (<div>
88
{list.map((name) => (<span>{name}</span>))}
99
</div>))}
1010
</div>),

packages/ts-transformers/test/fixtures/jsx-expressions/map-single-capture.expected.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export default recipe("MapSingleCapture", (_state) => {
77
]);
88
return {
99
[UI]: (<div>
10-
{__ctHelpers.derive(people, ({ people }) => people.length > 0 && (<ul>
10+
{__ctHelpers.derive(people, (people) => people.length > 0 && (<ul>
1111
{people.map((person) => (<li key={person.id}>{person.name}</li>))}
1212
</ul>))}
1313
</div>),

packages/ts-transformers/test/fixtures/jsx-expressions/method-chains.expected.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ export default recipe({
234234
}
235235
},
236236
required: ["element", "params"]
237-
} as const satisfies __ctHelpers.JSONSchema, ({ element: name, params: {} }) => (<li>{__ctHelpers.derive(name, ({ name }) => name.trim().toLowerCase().replace(" ", "-"))}</li>)), {})}
237+
} as const satisfies __ctHelpers.JSONSchema, ({ element: name, params: {} }) => (<li>{__ctHelpers.derive(name, (name) => name.trim().toLowerCase().replace(" ", "-"))}</li>)), {})}
238238
</ul>
239239

240240
{/* Reduce with reactive accumulator */}

0 commit comments

Comments
 (0)