Skip to content

Commit 147a161

Browse files
committed
fix: sensitive elements
1 parent 4d6d7ff commit 147a161

File tree

4 files changed

+66
-14
lines changed

4 files changed

+66
-14
lines changed

packages/cli/src/utils/modify-config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,11 @@ export async function modifyConfigFile(detectedBuildTool: BuildTool) {
111111

112112
const confirmation = await abortIfCancelled(
113113
clack.confirm({
114-
message: 'Do these changes to your config file cause errors?',
115-
initialValue: false,
114+
message: 'Does the config file look good?',
115+
initialValue: true,
116116
}),
117117
);
118-
if (confirmation) {
118+
if (!confirmation) {
119119
await fs.promises.writeFile(filePath, oldCode, {
120120
encoding: 'utf-8',
121121
flag: 'w',

packages/compiler/react/jsx-element-visitor.ts

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,23 @@ export const jsxElementVisitor = (options: Options = {}, isReact = true) => {
104104
);
105105
}
106106

107+
if (t.isBlockStatement(expression.body)) {
108+
const expressionPath = resolvePath(jsxElementPath.get('children'));
109+
const returnStatementPath = resolvePath(
110+
expressionPath.find((path) => path.isReturnStatement())!,
111+
) as NodePath<t.ReturnStatement>;
112+
const argument = returnStatementPath.node.argument;
113+
114+
if (!t.isJSXElement(argument) && !t.isJSXFragment(argument)) {
115+
return;
116+
}
117+
} else if (
118+
!t.isJSXElement(expression.body) &&
119+
!t.isJSXFragment(expression.body)
120+
) {
121+
return;
122+
}
123+
107124
const jsxElementParent = jsxElementPath.parent;
108125

109126
if (t.isJSXElement(jsxElementParent)) {
@@ -238,6 +255,7 @@ export const jsxElementVisitor = (options: Options = {}, isReact = true) => {
238255
if (bailout) return jsxElementPath.stop();
239256

240257
const ids = [...idNames].map((id) => t.identifier(id));
258+
const body = t.cloneNode(expression.body);
241259

242260
// We do a similar extraction process as in the call expression visitor
243261
const originalComponent = t.variableDeclaration('const', [
@@ -249,9 +267,9 @@ export const jsxElementVisitor = (options: Options = {}, isReact = true) => {
249267
ids.map((id) => t.objectProperty(id, id, false, true)),
250268
),
251269
],
252-
t.isBlockStatement(expression.body)
253-
? expression.body
254-
: t.blockStatement([t.returnStatement(expression.body)]),
270+
t.isBlockStatement(body)
271+
? body
272+
: t.blockStatement([t.returnStatement(body)]),
255273
),
256274
),
257275
]);

packages/compiler/react/transform.ts

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
isStatic,
1515
isJSXFragment,
1616
hasStyledAttributes,
17+
isSensitiveElement,
1718
} from './utils';
1819
import { optimize } from './optimize';
1920
import { evaluate } from './evaluator';
@@ -1012,10 +1013,19 @@ export const transformJSX = (
10121013
* <div><For each={[1, 2, 3]}>{i => <div>{i}</div>}</For></div>
10131014
* ```
10141015
*/
1016+
const expressionPath = resolvePath(
1017+
jsxPath.get(`children.${i}.expression`),
1018+
);
1019+
const hasSensitive =
1020+
expressionPath.parentPath?.isJSXExpressionContainer() &&
1021+
t.isJSXElement(expressionPath.parentPath.parent) &&
1022+
isSensitiveElement(expressionPath.parentPath.parent);
1023+
10151024
if (
10161025
t.isCallExpression(expression) &&
10171026
t.isMemberExpression(expression.callee) &&
1018-
t.isIdentifier(expression.callee.property, { name: 'map' })
1027+
t.isIdentifier(expression.callee.property, { name: 'map' }) &&
1028+
!hasSensitive
10191029
) {
10201030
const For = imports.addNamed('For');
10211031
const jsxFor = t.jsxIdentifier(For.name);
@@ -1037,7 +1047,6 @@ export const transformJSX = (
10371047
continue;
10381048
}
10391049

1040-
const expressionPath = jsxPath.get(`children.${i}.expression`);
10411050
/**
10421051
* Handles JSX conditionals and shoves them into a render scope:
10431052
*
@@ -1071,14 +1080,29 @@ export const transformJSX = (
10711080
continue;
10721081
}
10731082

1074-
if (
1075-
expressionPath.find(
1076-
(path) => path.isJSXElement() || path.isJSXFragment(),
1077-
)
1078-
) {
1083+
let foundJsxInExpression = false;
1084+
expressionPath.traverse({
1085+
JSXElement(path) {
1086+
foundJsxInExpression = true;
1087+
path.stop();
1088+
},
1089+
JSXFragment(path) {
1090+
foundJsxInExpression = true;
1091+
path.stop();
1092+
},
1093+
});
1094+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
1095+
if (foundJsxInExpression) {
10791096
const id = createPortal(() => {
1097+
if (hasSensitive) {
1098+
return jsxPath.replaceWith(
1099+
isRoot
1100+
? t.expressionStatement(id!)
1101+
: t.jsxExpressionContainer(id!),
1102+
);
1103+
}
10801104
jsx.children[i] = t.jsxExpressionContainer(id!);
1081-
}, [expression, t.booleanLiteral(unstable)]);
1105+
}, [hasSensitive ? jsx : expression, t.booleanLiteral(unstable)]);
10821106

10831107
continue;
10841108
}

packages/compiler/react/utils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,16 @@ export const getValidSpecifiers = (
5858
return validSpecifiers;
5959
};
6060

61+
export const isSensitiveElement = (jsx: t.JSXElement) => {
62+
// elements that break when the children are not in a specific format
63+
const sensitiveElements = ['select'];
64+
65+
return (
66+
t.isJSXIdentifier(jsx.openingElement.name) &&
67+
sensitiveElements.includes(jsx.openingElement.name.name)
68+
);
69+
};
70+
6171
export const hasStyledAttributes = (attribute: t.JSXAttribute) => {
6272
return attribute.name.name === 'tw' || attribute.name.name === 'css';
6373
};

0 commit comments

Comments
 (0)