lwc icon indicating copy to clipboard operation
lwc copied to clipboard

Move HTML/ARIA property/attribute reflection from `ssr-compiler` to `ssr-runtime`

Open nolanlawson opened this issue 1 year ago • 4 comments

Right now the property/attribute reflection in the ssr- packages is a bit hairy. I don't think that we need to sniff at runtime which props are present in the component (title, ariaLabel, etc.) – we can just move the known lists of global HTML props / ARIA props to ssr-runtime and put them all on a shared prototype (or similar mechanism). This will simplify the SSR compiler code quite a bit.

Another small bug: calling

this.ariaLabel = undefined
this.title = undefined

(etc)

should result in the corresponding attributes being removed, same as setting null. This is just how HTML IDL attribute reflection works. Currently this is busted for ARIA properties because @lwc/aria-reflection doesn't handle undefined correctly for backwards compat.

nolanlawson avatar Oct 15 '24 19:10 nolanlawson

This issue has been linked to a new work item: W-16985169

git2gus[bot] avatar Oct 15 '24 19:10 git2gus[bot]

Interestingly, null / undefined remove ARIA attributes, but not global HTML attributes.

const div = document.createElement('div')
// <div></div>

div.ariaLabel = div.title = 'foo'
// <div aria-label="foo" title="foo"></div>

div.ariaLabel = div.title = null
// <div title="null"></div>

wjhsf avatar Oct 16 '24 15:10 wjhsf

I think it varies from attribute to attribute. E.g. setting tabIndex to undefined actually gives you tabindex="0". There are also inconsistencies between browsers:

https://github.com/salesforce/lwc/blob/6d0296bbca3073022ee23ef37c69e95aab3c36ab/packages/%40lwc/integration-karma/test/component/html-properties/index.spec.js#L133-L136

nolanlawson avatar Oct 16 '24 16:10 nolanlawson

I think it varies from attribute to attribute. E.g. setting tabIndex to undefined actually gives you tabindex="0". There are also inconsistencies between browsers:

That's variation on the value, not variation on removal.

const div = document.createElement('div')
// <div></div>

div.ariaLabel = div.title = div.spellcheck = div.tabIndex = 'foo'
// <div aria-label="foo" title="foo" spellcheck="true" tabindex="0"></div>

div.ariaLabel = div.title = div.spellcheck = div.tabIndex = null
div.hasAttribute('aria-label') // false
div.hasAttribute('title') // true
div.hasAttribute('spellcheck') // true
div.hasAttribute('tabindex') // true

wjhsf avatar Oct 16 '24 17:10 wjhsf

We had to shuffle things around quite a bit, but I think we've finally got the correct implementation.

wjhsf avatar Mar 28 '25 19:03 wjhsf