-
Notifications
You must be signed in to change notification settings - Fork 396
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(engine-dom): remove ARIA reflection global polyfill (BREAKING CHANGE) #3666
Conversation
Note I considered an alternative implementation where, instead of using an |
|
||
describe('disable aria reflection polyfill', () => { | ||
testWithFeatureFlagEnabled('DISABLE_ARIA_REFLECTION_POLYFILL'); | ||
}); |
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 is no longer any difference in server mode with this flag on or off, so this test isn't needed anymore.
// | ||
// Also note that we apply this to BaseBridgeElement.prototype to avoid excessively redefining property | ||
// accessors inside the HTMLBridgeElementFactory. | ||
applyAriaReflection(BaseBridgeElement.prototype); |
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.
Applying ARIA reflection to the base bridge element and lightning element unilaterally has a few benefits:
- No confusion about server vs client – same logic for both
- The global polyfill is simpler – it affects one line of code basically (whether we apply the polyfill to
Element.prototype
or not) - It's easier to detect violations – we can just detect
Element.prototype.aria*
directly with no need to filter out Lightning/BridgeElements.
// polyfill is not applied | ||
if (window.lwcRuntimeFlags.ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL) { | ||
usePropertyAccessValues.push(true); | ||
} |
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 test was busted before, but we didn't notice because we weren't testing with global ARIA reflection disabled in native shadow mode.
- run_karma: | ||
disable_synthetic: true | ||
disable_aria_reflection_polyfill: true | ||
enable_aria_reflection_global_polyfill: true |
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 feel we may as well test with synthetic shadow on vs off, especially since this flag will be set to true in LEX.
This comment was marked as outdated.
This comment was marked as outdated.
…ault-aria-reflection-off
…f' into nolan/default-aria-reflection-off
As it turns out, JSDOM does not support ARIA string reflection (jsdom/jsdom#3323), so the following does not work: <div role="button" aria-label="foo"></div> element.role // undefined
element.ariaLabel // undefined (This matches Firefox's current behavior, but not Chrome's/Safari's.) Unfortunately this is working in LWC Jest tests today, because we are applying this polyfill to the global In addition, we are currently not warning on string reflection ( |
I opened a PR on JSDOM for this (jsdom/jsdom#3586), but in the interests of expediency, we may want to temporarily add the minimal string reflection polyfill to |
This comment was marked as outdated.
This comment was marked as outdated.
Argument against fixing this in |
Per discussion in DevSync, removed the polyfill entirely and moved it to lwc-platform: 4cafff8 ^ The |
/nucleus test |
/nucleus test |
Realized I could simplify things even further by just removing the When we release v4.0, we can just mark the existing package as deprecated. |
After discussion in PR review:
This makes |
/nucleus test |
packages/@lwc/engine-core/src/libs/aria-reflection/aria-reflection.ts
Outdated
Show resolved
Hide resolved
packages/@lwc/engine-core/src/patches/detect-non-standard-aria.ts
Outdated
Show resolved
Hide resolved
@@ -45,7 +43,8 @@ function findVM(elm: Element): VM | undefined { | |||
// Else it might be a light DOM component. Walk up the tree trying to find the owner | |||
let parentElement: Element | null = elm; | |||
while (!isNull((parentElement = parentElement.parentElement))) { | |||
if (isLightningElement(parentElement)) { | |||
if (parentElement instanceof BaseBridgeElement) { |
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 elm instanceof LightningElement
check isn't required here because findVM
only deals with DOM elements?
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.
Correct. LightningElement
is an internal thing that you can't see from the outside by traversing the DOM.
@@ -56,32 +55,30 @@ function findVM(elm: Element): VM | undefined { | |||
} | |||
|
|||
function checkAndReportViolation(elm: Element, prop: string, isSetter: boolean, setValue: any) { | |||
if (!isLightningElement(elm)) { |
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.
How come we no longer require this 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.
I actually couldn't remember, so I wrote a test to confirm the behavior: 892212b
I checked, and the reason this works i because we are overriding the Element.prototype
accessors in detect-non-standard-aria
after the accessors were applied to LightningElement.prototype
and BaseBridgeElement.prototype
. So when you call the accessors directly on the component (internally with this.aria*
or externally with elm.aria*
), it never goes through the accessors in this file.
This is kind of confusing, so I added a comment to explain: 8ab13fa
/nucleus test |
@@ -1,20 +1,85 @@ | |||
/* | |||
* Copyright (c) 2018, salesforce.com, inc. | |||
* Copyright (c) 2023, salesforce.com, inc. |
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.
Just curious whether you're updating these manually?
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.
Manually, yes. We should really go through and just run a script or something.
Details
Fixes #2733
The
@lwc/aria-reflection
polyfill still exists, but we don't use it in the LWC engine. It's just there for backwards-compat in LEX, similar to@lwc/synthetic-shadow
.Old description
This disables the global ARIA reflection polyfill by default. It can still be enabled with the flag
ENABLE_ARIA_REFLECTION_GLOBAL_POLYFILL
.The idea is that we can set this to
true
inlwc-platform
for as long as we need the backwards-compat support. Unfortunately we don't have a good idea of how to fix this with API versioning, because (since it's a global polyfill), it's currently being used both by LWC components and Aura components in LEX.On the bright side, we can at least remove it from the core LWC npm package, which means that non-LEX environments will not get the global polyfill.
Does this pull request introduce a breaking change?
Note: this change only applies to non-Lightning Experience use cases such as Jest tests and off-core scenarios. It also only applies to non-
LightningElement
HTML elements.Removal of non-standard ARIA APIs
The following non-standard ARIA APIs are now deprecated:
ariaActiveDescendant
ariaControls
ariaDescribedBy
ariaDetails
ariaErrorMessage
ariaFlowTo
ariaLabelledBy
ariaOwns
… when used on a non-
LightningElement
HTML element. E.g.:For a
LightningElement
, you can continue to usethis.ariaActiveDescendant
andelement.ariaActiveDescendant
as before.For arbitrary HTML elements, however, instead of using these non-standard APIs, please use the appropriate
setAttribute
/getAttribute
APIs instead:aria-activedescendant
aria-controls
aria-describedby
aria-details
aria-errormessage
aria-flowto
aria-labelledby
aria-owns
E.g.:
Removal of standard ARIA reflection global polyfill
Some browsers and environments, notably Firefox and JSDOM, do not yet support ARIA reflection for properties such as
role
andariaLabel
. For maximum compatibility, please use the attribute format instead:element.role
->element.getAttribute('role')
element.ariaLabel
->element.getAttribute('aria-label')
If you are using the latest version of
@lwc/jest-*
, a polyfill for JSDOM is already included.Deprecation of
@lwc/aria-reflection
packageIf you were using this package for whatever reason, it is now deprecated. You should probably not be using it, unless you absolutely need it for backwards compatibility and don't want to update code that's relying on it.
Does this pull request introduce an observable change?
See above.
GUS work item
W-10820032