Skip to content
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

fix(ssr-compiler): define setters for reflected attributes #4611

Merged
merged 2 commits into from
Oct 7, 2024

Conversation

ekashida
Copy link
Member

@ekashida ekashida commented Oct 5, 2024

Define setters for reflected attributes. Needed to add a private #setAttribute() method that can set null without turning it into a string so that removeAttribute() works as expected.

Also for-of was also changed to for-in in renderAttrs so that we can iterate over non-string (accessor) enumerable entries.

This implementation is now more correct than engine-server as it seems the latter may not be handing setAttribute(null) correctly for standard reflected attributes:

 FAIL  |lwc-ssr-compiler| src/__tests__/fixtures.spec.ts > fixtures > attribute-null/index.js
Error: Received content for "/Users/ekashida/Repos/lwc/packages/@lwc/engine-server/src/__tests__/fixtures/attribute-null/expected.html" doesn't match expected content.

Difference:

- Expected
+ Received

- <x-test aria-description="undefined" data-bar="null" data-foo="null" data-lwc-host-mutated="aria-description aria-label data-bar data-foo">
+ <x-test aria-description="undefined" aria-label="null" data-bar="null" data-foo="null">

@ekashida ekashida requested a review from a team as a code owner October 5, 2024 17:45
packages/@lwc/ssr-runtime/src/index.ts Show resolved Hide resolved
packages/@lwc/ssr-runtime/src/index.ts Outdated Show resolved Hide resolved
packages/@lwc/ssr-runtime/src/index.ts Show resolved Hide resolved
@ekashida ekashida merged commit 29d5a74 into master Oct 7, 2024
11 checks passed
@ekashida ekashida deleted the ekashida/reflective-setters branch October 7, 2024 19:18
)
),
])
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This would benefit from a code comment showing an example output. ASTs are hard to read...

setAttribute(attrName: string, value: string | null): void {
this.__attrs[attrName] = String(value);
setAttribute(attrName: string, attrValue: unknown): void {
this.#setAttribute(attrName, String(attrValue));
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's a bit confusing to have two methods named setAttribute and #setAttribute. Maybe #setAttributeWithoutTypeCoercion or something?

}

hasAttribute(attrName: unknown): boolean {
return typeof attrName === 'string' && typeof this.__attrs[attrName] === 'string';
Copy link
Collaborator

Choose a reason for hiding this comment

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

The fact that we have to check for strings here because we don't ensure that the values in this.__attrs is only a string type is odd to me. We should probably do the validation/coercion on the way in.

Copy link
Collaborator

Choose a reason for hiding this comment

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

OK, so the reason for this is that we can't call delete because that would delete the getter/setter which is required for prop/attr reflection.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants