Skip to content

Commit

Permalink
feat: use code frames for errors for babel plugin (#748)
Browse files Browse the repository at this point in the history
* use code frames for errors
* constrain types
  • Loading branch information
EvanBacon authored Oct 16, 2024
1 parent 6771fb6 commit f4c6ea7
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 27 deletions.
28 changes: 22 additions & 6 deletions packages/babel-plugin/src/visitors/stylex-create-theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ export default function transformStyleXCreateTheme(
state,
);
if (!confident1) {
throw new Error(messages.NON_STATIC_VALUE);
throw callExpressionPath.buildCodeFrameError(
messages.NON_STATIC_VALUE,
SyntaxError,
);
}

const injectedKeyframes: { [animationName: string]: InjectableStyle } = {};
Expand Down Expand Up @@ -118,19 +121,26 @@ export default function transformStyleXCreateTheme(
},
);
if (!confident2) {
throw new Error(messages.NON_STATIC_VALUE);
throw callExpressionPath.buildCodeFrameError(
messages.NON_STATIC_VALUE,
SyntaxError,
);
}
if (typeof overrides !== 'object' || overrides == null) {
throw new Error(messages.NON_OBJECT_FOR_STYLEX_CALL);
throw callExpressionPath.buildCodeFrameError(
messages.NON_OBJECT_FOR_STYLEX_CALL,
SyntaxError,
);
}

// Check that first arg has __themeName__ set
if (
typeof variables.__themeName__ !== 'string' ||
variables.__themeName__ === ''
) {
throw new Error(
throw callExpressionPath.buildCodeFrameError(
'Can only override variables theme created with stylex.defineVars().',
SyntaxError,
);
}

Expand Down Expand Up @@ -183,10 +193,16 @@ function validateStyleXCreateTheme(
!variableDeclaratorPath.isVariableDeclarator() ||
variableDeclaratorPath.node.id.type !== 'Identifier'
) {
throw new Error(messages.UNBOUND_STYLEX_CALL_VALUE);
throw callExpressionPath.buildCodeFrameError(
messages.UNBOUND_STYLEX_CALL_VALUE,
SyntaxError,
);
}

if (callExpressionPath.node.arguments.length !== 2) {
throw new Error(messages.ILLEGAL_ARGUMENT_LENGTH);
throw callExpressionPath.buildCodeFrameError(
messages.ILLEGAL_ARGUMENT_LENGTH,
SyntaxError,
);
}
}
19 changes: 14 additions & 5 deletions packages/babel-plugin/src/visitors/stylex-create/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export default function transformStyleXCreate(
});
if (!confident) {
throw new Error(messages.NON_STATIC_VALUE);
throw path.buildCodeFrameError(messages.NON_STATIC_VALUE, SyntaxError);
}
const plainObject = value;
// eslint-disable-next-line prefer-const
Expand Down Expand Up @@ -311,20 +311,29 @@ function validateStyleXCreate(path: NodePath<t.CallExpression>) {
path.parentPath == null ||
pathUtils.isExpressionStatement(path.parentPath)
) {
throw new Error(messages.UNBOUND_STYLEX_CALL_VALUE);
throw path.buildCodeFrameError(
messages.UNBOUND_STYLEX_CALL_VALUE,
SyntaxError,
);
}
const nearestStatement = findNearestStatementAncestor(path);
if (
!pathUtils.isProgram(nearestStatement.parentPath) &&
!pathUtils.isExportNamedDeclaration(nearestStatement.parentPath)
) {
throw new Error(messages.ONLY_TOP_LEVEL);
throw path.buildCodeFrameError(messages.ONLY_TOP_LEVEL, SyntaxError);
}
if (path.node.arguments.length !== 1) {
throw new Error(messages.ILLEGAL_ARGUMENT_LENGTH);
throw path.buildCodeFrameError(
messages.ILLEGAL_ARGUMENT_LENGTH,
SyntaxError,
);
}
if (path.node.arguments[0].type !== 'ObjectExpression') {
throw new Error(messages.NON_OBJECT_FOR_STYLEX_CALL);
throw path.buildCodeFrameError(
messages.NON_OBJECT_FOR_STYLEX_CALL,
SyntaxError,
);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export function evaluateStyleXCreateArg(
NodePath<t.Identifier | t.SpreadElement | t.Pattern>,
> = fnPath.get('params');

validateDynamicStyleParams(allParams);
validateDynamicStyleParams(fnPath, allParams);

const params: Array<t.Identifier> = allParams
.filter(
Expand Down Expand Up @@ -178,7 +178,10 @@ function evaluatePartialObjectRecursively(
obj[key] = `var(${varName})`;
const node = valuePath.node;
if (!t.isExpression(node)) {
throw new Error('Expected expression as style value');
throw valuePath.buildCodeFrameError(
'Expected expression as style value',
SyntaxError,
);
}
const expression: t.Expression = node as $FlowFixMe;

Expand Down Expand Up @@ -271,9 +274,13 @@ function evaluateObjKey(
}

function validateDynamicStyleParams(
path: NodePath<t.ArrowFunctionExpression>,
params: Array<NodePath<t.Identifier | t.SpreadElement | t.Pattern>>,
) {
if (params.some((param) => !pathUtils.isIdentifier(param))) {
throw new Error(messages.ONLY_NAMED_PARAMETERS_IN_DYNAMIC_STYLE_FUNCTIONS);
throw path.buildCodeFrameError(
messages.ONLY_NAMED_PARAMETERS_IN_DYNAMIC_STYLE_FUNCTIONS,
SyntaxError,
);
}
}
25 changes: 20 additions & 5 deletions packages/babel-plugin/src/visitors/stylex-define-vars.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,16 @@ export default function transformStyleXDefineVars(
memberExpressions,
});
if (!confident) {
throw new Error(messages.NON_STATIC_VALUE);
throw callExpressionPath.buildCodeFrameError(
messages.NON_STATIC_VALUE,
SyntaxError,
);
}
if (typeof value !== 'object' || value == null) {
throw new Error(messages.NON_OBJECT_FOR_STYLEX_CALL);
throw callExpressionPath.buildCodeFrameError(
messages.NON_OBJECT_FOR_STYLEX_CALL,
SyntaxError,
);
}

const fileName = state.fileNameForHashing;
Expand Down Expand Up @@ -162,17 +168,26 @@ function validateStyleXDefineVars(
!variableDeclaratorPath.isVariableDeclarator() ||
variableDeclaratorPath.node.id.type !== 'Identifier'
) {
throw new Error(messages.UNBOUND_STYLEX_CALL_VALUE);
throw callExpressionPath.buildCodeFrameError(
messages.UNBOUND_STYLEX_CALL_VALUE,
SyntaxError,
);
}

if (
exportNamedDeclarationPath == null ||
!exportNamedDeclarationPath.isExportNamedDeclaration()
) {
throw new Error(messages.NON_EXPORT_NAMED_DECLARATION);
throw callExpressionPath.buildCodeFrameError(
messages.NON_EXPORT_NAMED_DECLARATION,
SyntaxError,
);
}

if (callExpressionPath.node.arguments.length !== 1) {
throw new Error(messages.ILLEGAL_ARGUMENT_LENGTH);
throw callExpressionPath.buildCodeFrameError(
messages.ILLEGAL_ARGUMENT_LENGTH,
SyntaxError,
);
}
}
31 changes: 23 additions & 8 deletions packages/babel-plugin/src/visitors/stylex-keyframes.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,24 @@ export default function transformStyleXKeyframes(
state.stylexImport.has(nodeInit.callee.object.name))
) {
if (nodeInit.arguments.length !== 1) {
throw new Error(messages.ILLEGAL_ARGUMENT_LENGTH);
throw path.buildCodeFrameError(
messages.ILLEGAL_ARGUMENT_LENGTH,
SyntaxError,
);
}
if (nodeInit.arguments[0].type !== 'ObjectExpression') {
throw new Error(messages.NON_OBJECT_FOR_STYLEX_KEYFRAMES_CALL);
throw path.buildCodeFrameError(
messages.NON_OBJECT_FOR_STYLEX_KEYFRAMES_CALL,
SyntaxError,
);
}

const init: ?NodePath<t.Expression> = path.get('init');
if (init == null || !pathUtils.isCallExpression(init)) {
throw new Error(messages.NON_STATIC_KEYFRAME_VALUE);
throw path.buildCodeFrameError(
messages.NON_STATIC_KEYFRAME_VALUE,
SyntaxError,
);
}
const args: $ReadOnlyArray<NodePath<>> = init.get('arguments');
const firstArg = args[0];
Expand All @@ -76,10 +85,10 @@ export default function transformStyleXKeyframes(
memberExpressions,
});
if (!confident) {
throw new Error(messages.NON_STATIC_VALUE);
throw path.buildCodeFrameError(messages.NON_STATIC_VALUE, SyntaxError);
}
const plainObject = value;
assertValidKeyframes(plainObject);
assertValidKeyframes(path, plainObject);
const [animationName, { ltr, priority, rtl }] = stylexKeyframes(
plainObject,
state.options,
Expand All @@ -93,13 +102,19 @@ export default function transformStyleXKeyframes(
}
// Validation of `stylex.keyframes` function call.
function assertValidKeyframes(obj: mixed) {
function assertValidKeyframes(
path: NodePath<t.VariableDeclarator>,
obj: mixed,
) {
if (typeof obj !== 'object' || Array.isArray(obj) || obj == null) {
throw new Error(messages.NON_OBJECT_FOR_STYLEX_KEYFRAMES_CALL);
throw path.buildCodeFrameError(
messages.NON_OBJECT_FOR_STYLEX_KEYFRAMES_CALL,
SyntaxError,
);
}
for (const [_key, value] of Object.entries(obj)) {
if (typeof value !== 'object' || Array.isArray(value)) {
throw new Error(messages.NON_OBJECT_KEYFRAME);
throw path.buildCodeFrameError(messages.NON_OBJECT_KEYFRAME, SyntaxError);
}
}
}

0 comments on commit f4c6ea7

Please sign in to comment.