-
Notifications
You must be signed in to change notification settings - Fork 398
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(ssr-compiler): validate api decorator usage #5071
base: master
Are you sure you want to change the base?
Conversation
const field = state.publicFields.get(node.key.name); | ||
|
||
if (field) { | ||
if ( | ||
(is.methodDefinition(field, { kind: (k) => k === 'get' || k === 'set' }) && | ||
node.kind === 'get') || | ||
node.kind === 'set' | ||
) { | ||
throw generateError( | ||
DecoratorErrors.SINGLE_DECORATOR_ON_SETTER_GETTER_PAIR, | ||
node.key.name | ||
); | ||
} else { | ||
throw generateError(DecoratorErrors.DUPLICATE_API_PROPERTY, node.key.name); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clean this up & move to its own function
…alidate-api-decorator
…alidate-api-decorator
…alidate-api-decorator
…alidate-api-decorator
I'm a bit unsure about the scope of this PR, so I'm opening it up for review. The main remaining TODO is to replicate the valid tests, but on second thought that might already be covered by the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The approach taken here is to mirror behavior and tests from babel-plugin-component
. I focused on the api decorator errors and didn't introduce location info to keep the PR short.
|
||
/** | ||
* This set is for attributes that have a camel cased property name | ||
* For example, div.tabIndex. | ||
* We do not want users to define `@api` properties with these names | ||
* Because the template will never call them. It'll always call the camel | ||
* cased version. | ||
*/ | ||
export const AMBIGUOUS_PROP_SET = /*@__PURE__@*/ new Map([ | ||
['bgcolor', 'bgColor'], | ||
['accesskey', 'accessKey'], | ||
['contenteditable', 'contentEditable'], | ||
['tabindex', 'tabIndex'], | ||
['maxlength', 'maxLength'], | ||
['maxvalue', 'maxValue'], | ||
]); | ||
|
||
/** | ||
* This set is for attributes that can never be defined | ||
* by users on their components. | ||
* We throw for these. | ||
*/ | ||
export const DISALLOWED_PROP_SET = /*@__PURE__@*/ new Set(['is', 'class', 'slot', 'style']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe @lwc/errors
would be a better place for this. Not sure.
function validateName(definition: ApiDefinition) { | ||
if (definition.computed) { | ||
throw generateError(DecoratorErrors.PROPERTY_CANNOT_BE_COMPUTED); | ||
} | ||
|
||
const propertyName = definition.key.name; | ||
|
||
switch (true) { | ||
case propertyName === 'part': | ||
throw generateError(DecoratorErrors.PROPERTY_NAME_PART_IS_RESERVED, propertyName); | ||
case propertyName.startsWith('on'): | ||
throw generateError(DecoratorErrors.PROPERTY_NAME_CANNOT_START_WITH_ON, propertyName); | ||
case propertyName.startsWith('data') && propertyName.length > 4: | ||
throw generateError(DecoratorErrors.PROPERTY_NAME_CANNOT_START_WITH_DATA, propertyName); | ||
case DISALLOWED_PROP_SET.has(propertyName): | ||
throw generateError(DecoratorErrors.PROPERTY_NAME_IS_RESERVED, propertyName); | ||
case AMBIGUOUS_PROP_SET.has(propertyName): | ||
throw generateError( | ||
DecoratorErrors.PROPERTY_NAME_IS_AMBIGUOUS, | ||
propertyName, | ||
AMBIGUOUS_PROP_SET.get(propertyName)! | ||
); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This whole file mirrors the structure and logic from babel-plugin-component
:
function validatePropertyName(property: NodePath<types.ClassMethod>, state: LwcBabelPluginPass) { | |
if (property.node.computed) { | |
throw generateError( | |
property, | |
{ | |
errorInfo: DecoratorErrors.PROPERTY_CANNOT_BE_COMPUTED, | |
}, | |
state | |
); | |
} |
…alidate-api-decorator
…alidate-api-decorator
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved back to draft as I learned some stuff in #5114 that will make this better 😅
class CompilationError extends Error { | ||
constructor( | ||
message: string, | ||
public code: number | ||
) { | ||
super(message); | ||
this.name = 'CompilationError'; | ||
this.code = code; | ||
} | ||
} | ||
|
||
export function generateError<const T extends LWCErrorInfo>( | ||
error: T, | ||
...args: ExtractArguments<T['message']> | ||
): Error { | ||
return new Error(generateErrorMessage(error, args)); | ||
): CompilationError { | ||
return new CompilationError(generateErrorMessage(error, args), error.code); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use CompilerError
from @lwc/errors
instead.
…alidate-api-decorator
Details
I'm a bit short on time today to finish polishing this up, so I'm sending this as a draft.
Follow up to #5062
Partially addresses #5032
This PR aims to replicate the api decorator validation done in
babel-plugin-component
and also related tests.Some of the validation done in
babel-plugin-component
seems to be done after everything is collected, while here it's currently all done during traversal. Maybe that's just for better error reporting, which I think can be considered in a separate issue, but need to make sure this is not introducing undesirable behavior here.TODOS:
generateCompilerError
from@lwc/errors
@lwc/shared
or@lwc/errors
Does this pull request introduce a breaking change?
Does this pull request introduce an observable change?
GUS work item