Skip to content

Commit

Permalink
fix: sensitive elements
Browse files Browse the repository at this point in the history
  • Loading branch information
aidenybai committed Sep 15, 2023
1 parent 4d6d7ff commit 147a161
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 14 deletions.
6 changes: 3 additions & 3 deletions packages/cli/src/utils/modify-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,11 @@ export async function modifyConfigFile(detectedBuildTool: BuildTool) {

const confirmation = await abortIfCancelled(
clack.confirm({
message: 'Do these changes to your config file cause errors?',
initialValue: false,
message: 'Does the config file look good?',
initialValue: true,
}),
);
if (confirmation) {
if (!confirmation) {
await fs.promises.writeFile(filePath, oldCode, {
encoding: 'utf-8',
flag: 'w',
Expand Down
24 changes: 21 additions & 3 deletions packages/compiler/react/jsx-element-visitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,23 @@ export const jsxElementVisitor = (options: Options = {}, isReact = true) => {
);
}

if (t.isBlockStatement(expression.body)) {
const expressionPath = resolvePath(jsxElementPath.get('children'));
const returnStatementPath = resolvePath(
expressionPath.find((path) => path.isReturnStatement())!,
) as NodePath<t.ReturnStatement>;
const argument = returnStatementPath.node.argument;

if (!t.isJSXElement(argument) && !t.isJSXFragment(argument)) {
return;
}
} else if (
!t.isJSXElement(expression.body) &&
!t.isJSXFragment(expression.body)
) {
return;
}

const jsxElementParent = jsxElementPath.parent;

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

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

// We do a similar extraction process as in the call expression visitor
const originalComponent = t.variableDeclaration('const', [
Expand All @@ -249,9 +267,9 @@ export const jsxElementVisitor = (options: Options = {}, isReact = true) => {
ids.map((id) => t.objectProperty(id, id, false, true)),
),
],
t.isBlockStatement(expression.body)
? expression.body
: t.blockStatement([t.returnStatement(expression.body)]),
t.isBlockStatement(body)
? body
: t.blockStatement([t.returnStatement(body)]),
),
),
]);
Expand Down
40 changes: 32 additions & 8 deletions packages/compiler/react/transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
isStatic,
isJSXFragment,
hasStyledAttributes,
isSensitiveElement,
} from './utils';
import { optimize } from './optimize';
import { evaluate } from './evaluator';
Expand Down Expand Up @@ -1012,10 +1013,19 @@ export const transformJSX = (
* <div><For each={[1, 2, 3]}>{i => <div>{i}</div>}</For></div>
* ```
*/
const expressionPath = resolvePath(
jsxPath.get(`children.${i}.expression`),
);
const hasSensitive =
expressionPath.parentPath?.isJSXExpressionContainer() &&
t.isJSXElement(expressionPath.parentPath.parent) &&
isSensitiveElement(expressionPath.parentPath.parent);

if (
t.isCallExpression(expression) &&
t.isMemberExpression(expression.callee) &&
t.isIdentifier(expression.callee.property, { name: 'map' })
t.isIdentifier(expression.callee.property, { name: 'map' }) &&
!hasSensitive
) {
const For = imports.addNamed('For');
const jsxFor = t.jsxIdentifier(For.name);
Expand All @@ -1037,7 +1047,6 @@ export const transformJSX = (
continue;
}

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

if (
expressionPath.find(
(path) => path.isJSXElement() || path.isJSXFragment(),
)
) {
let foundJsxInExpression = false;
expressionPath.traverse({
JSXElement(path) {
foundJsxInExpression = true;
path.stop();
},
JSXFragment(path) {
foundJsxInExpression = true;
path.stop();
},
});
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (foundJsxInExpression) {
const id = createPortal(() => {
if (hasSensitive) {
return jsxPath.replaceWith(
isRoot
? t.expressionStatement(id!)
: t.jsxExpressionContainer(id!),
);
}
jsx.children[i] = t.jsxExpressionContainer(id!);
}, [expression, t.booleanLiteral(unstable)]);
}, [hasSensitive ? jsx : expression, t.booleanLiteral(unstable)]);

continue;
}
Expand Down
10 changes: 10 additions & 0 deletions packages/compiler/react/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ export const getValidSpecifiers = (
return validSpecifiers;
};

export const isSensitiveElement = (jsx: t.JSXElement) => {
// elements that break when the children are not in a specific format
const sensitiveElements = ['select'];

return (
t.isJSXIdentifier(jsx.openingElement.name) &&
sensitiveElements.includes(jsx.openingElement.name.name)
);
};

export const hasStyledAttributes = (attribute: t.JSXAttribute) => {
return attribute.name.name === 'tw' || attribute.name.name === 'css';
};
Expand Down

2 comments on commit 147a161

@vercel
Copy link

@vercel vercel bot commented on 147a161 Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

million-kitchen-sink – ./packages/kitchen-sink

million-kitchen-sink-git-main-millionjs.vercel.app
million-kitchen-sink.vercel.app
million-kitchen-sink-millionjs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 147a161 Sep 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

sink – ./packages/kitchen-sink

sink-git-main-millionjs.vercel.app
sink-millionjs.vercel.app
million-kitchen-sink-atit.vercel.app
sink.million.dev

Please sign in to comment.