-
Notifications
You must be signed in to change notification settings - Fork 32
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
@W-17070457 Allow multi conditional !import.meta.env.SSR statements #171
@W-17070457 Allow multi conditional !import.meta.env.SSR statements #171
Conversation
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.
Initial round of feedback. Looking good overall!
lib/util/ssr.js
Outdated
@@ -6,13 +6,45 @@ | |||
*/ | |||
'use strict'; | |||
|
|||
let ssrEscapeFound = false; |
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.
Having this let
outside of isSSREscape
makes it a global. This is a code smell to me – I'd recommend moving both ssrEscapeFound
and checkConditionalStatements
into isSSREscape
instead.
lib/util/ssr.js
Outdated
); | ||
if (node.type === 'IfStatement' || node.type === 'ConditionalExpression') { | ||
ssrEscapeFound = false; | ||
if (checkConditionalStatements(node.test) || isWindowOrDocumentCheck(node.test)) { |
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.
Since typeof window !== 'undefined'
is basically the same as !import.meta.env.SSR
, I think we should handle the recursive case here too:
if (randomOtherCheck && typeof window !== 'undefined') {
lib/util/ssr.js
Outdated
// Recursive Case: If the node is a logical expression, check its left and right parts. | ||
if (node.type === 'LogicalExpression' || node.type === 'BinaryExpression') { | ||
checkConditionalStatements(node.left); | ||
checkConditionalStatements(node.right); |
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.
Rather than checking the ssrEscapeFound
global, you could have checkConditionalStatements
return a boolean, and then do a |=
here.
lib/util/ssr.js
Outdated
checkConditionalStatements(node.right); | ||
} | ||
|
||
// Base Case: If the node is an Identifier or MemberExpression, don't need to continue. |
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.
Why?
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.
If the node is an Identifier
or MemberExpression
, then there is no way it can be !import.meta.env.SSR
. This is a base case to break out of the recursion. Since it's not the base case we care about (UnaryExpression
), there is nothing more to check.
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 would be a helpful comment! 🙂
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.
Actually, this if
seems redundant to me since we fall through to return false
on line 47 anyway. I think we can remove it entirely.
@@ -351,7 +401,6 @@ testRule('no-unsupported-ssr-properties', { | |||
{ | |||
code: ` | |||
import { LightningElement } from 'lwc'; | |||
|
|||
export default class Foo extends LightningElement { | |||
connectedCallback() { | |||
this.childNodes.item(0).textContent = 'foo'; |
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.
Having some invalid cases tested here would be helpful to check that the PR is working as expected. For example:
if (a && b && c && d) {
this.template.querySelector('span');
}
BTW one slightly broken thing I noticed is that eslint-plugin-lwc/lib/util/ssr.js Lines 54 to 62 in c5d0cbb
This means that it treats |
Co-authored-by: Nolan Lawson <[email protected]>
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.
LGTM overall, some minor suggestions for cleanup.
{ | ||
code: ` | ||
import { LightningElement } from 'lwc'; | ||
|
||
export default class Foo extends LightningElement { | ||
connectedCallback() { | ||
return isCSR ? this.template.querySelector('button') : null; | ||
} | ||
} | ||
`, | ||
}, |
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 doesn't look correct at all. This test is only passing because it's using this.template.querySelector
rather than this.querySelector
. We should open a separate issue to handle this.template.querySelector
the same as this.querySelector
.
{ | |
code: ` | |
import { LightningElement } from 'lwc'; | |
export default class Foo extends LightningElement { | |
connectedCallback() { | |
return isCSR ? this.template.querySelector('button') : null; | |
} | |
} | |
`, | |
}, | |
{ | |
code: ` | |
import { LightningElement } from 'lwc'; | |
export default class Foo extends LightningElement { | |
connectedCallback() { | |
return isCSR ? this.template.querySelector('button') : null; | |
} | |
} | |
`, | |
}, |
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.
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.
I've updated the test to be this:
import { LightningElement } from 'lwc';
export default class Foo extends LightningElement {
connectedCallback() {
return !import.meta.env.SSR ? this.querySelector('button') : null;
}
}
Seems to pass!
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.
Not sure an issue was opened but we have plans to migrate all isCSR
into !import.meta.env.SSR
because they were not getting detected by the linter.
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.
LGTM! Minor nitpicks, but
lib/util/ssr.js
Outdated
// Recursive Case: If the node is a logical expression, check its left and right parts. | ||
if (node.type === 'LogicalExpression' && node.operator === '&&') { | ||
const rightNodeConditional = checkConditionalStatements(node.right); | ||
return !!rightNodeConditional || checkConditionalStatements(node.left); |
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.
If we want to be consistent about returning booleans (!!
) then we'll also need to fix isMetaEnvCheck
since it can return undefined if it returns node.type
.
Or we can just remove the !!
because it's probably not important to return a boolean versus truthy/falsy. 🙂
Co-authored-by: Nolan Lawson <[email protected]>
Co-authored-by: Nolan Lawson <[email protected]>
@W-17070457 Allow multi conditional !import.meta.env.SSR statements
@lwc/lwc/ssr/no-unsupported-properties
did not recognize when there is a multi conditional check with!import.meta.env.SSR
.Example: These is the scenario we are trying to fix: