lwc icon indicating copy to clipboard operation
lwc copied to clipboard

(engine-restrictions) Lift restrictions on addEventListener's options param for host element

Open ravijayaramappa opened this issue 4 years ago • 16 comments

Description

Adding an event listener on the custom element with a third options argument logs an error.

This restriction should be on the component instance and not on the host element. From the outside world, a DOM element should behave per spec when addEventListener is invoked with the options param, regardless of whether the element is a standard html element or a native custom element or an LWC host element.

Steps to Reproduce

https://playground.lwcjs.org/projects/d1fzv_d_h/3/edit

import { LightningElement, track } from 'lwc';

export default class App extends LightningElement {
    renderedCallback() {
        this.addEventListener('foo', () => {}, { passive: true });
    }
}

Reference: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

ravijayaramappa avatar Apr 13 '20 20:04 ravijayaramappa

FYI, this is probably just moving the following block:

https://github.com/salesforce/lwc/blob/9e19ce545011760e7a736e214ac3eab6948f0d60/packages/%40lwc/engine/src/framework/restrictions.ts#L338-L370

to

https://github.com/salesforce/lwc/blob/9e19ce545011760e7a736e214ac3eab6948f0d60/packages/%40lwc/engine/src/framework/restrictions.ts#L405

caridy avatar Apr 13 '20 21:04 caridy

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

git2gus[bot] avatar Apr 14 '20 15:04 git2gus[bot]

I'd have to dig in a little more but giving users the ability to subscribe to the capture phase of focusin might require us to refactor our delegatesFocus implementation. It might be fine as long as we always run first, not sure...

ekashida avatar Apr 14 '20 19:04 ekashida

Looks like we only restrict this for the host element: https://playground.lwcjs.org/projects/LY4Z_tvOv/1/edit

ekashida avatar Jul 06 '20 06:07 ekashida

When introducing support for options, we'll also need to update the existing logic to prevent multiple listeners for the same event since we currently only consider the identity of the listener function.

Some points to consider when determining whether a listener is "identical":

  1. Only the configuration parameters of the option object is considered and the values are read once when binding (it doesn't matter if the values change over time). This means that passing in true and { capture: true } are equivalent.

  2. IE11 doesn't support option objects, it just cares whether the third argument is truthy or not. We'd need to detect browser behavior to support this since different option objects should be considered equivalent.

ekashida avatar Mar 28 '21 05:03 ekashida

Hello, there. I'm also seeing this behavior in our project. I am using LWCs as web components in my app and would like to use the third optional parameter when binding event listeners to them. When running in development mode the LWC runtime throws an error for each usage. @pmdartus

bk-dev avatar Apr 20 '21 15:04 bk-dev

Updated repro using StackBlitz for posterity

FWIW it seems to log an error, not throw an error.

Screen Shot 2023-04-07 at 9 00 25 AM

nolanlawson avatar Apr 07 '23 16:04 nolanlawson

I just ran into this issue when trying to use LWC in Storybook 7, which requires lit-html/lit v2. It doesn't seem to be an issue with lit-html v1, though it still logs the error (but doesn't throw it). Have there been any updates since 2021?

fafnirical avatar Apr 10 '23 17:04 fafnirical

@fafnirical Is the issue just that it's logging an error? Or is there an actual functional difference?

nolanlawson avatar Apr 10 '23 17:04 nolanlawson

@fafnirical Is the issue just that it's logging an error? Or is there an actual functional difference?

@nolanlawson There's an actual functional difference. In addition to the logged error (LWC error]: The `addEventListener` method in `LightningElement` does not support any options.) I see when rendered by both lit-html v1 and v2, lit-html v2 causes LWC to throw the following error in Storybook:

vendors~main.iframe.bundle.js:1475 Uncaught (in promise) TypeError: Invalid second argument for Element.addEventListener() in [object HTMLElement] for event "changesegment". Expected an EventListener but received [object Object].
    at HTMLBridgeElement.addCustomElementEventListener (vendors~main.iframe.bundle.js:1475:13)
    at HTMLBridgeElement.patchedAddEventListener$1 [as addEventListener] (vendors~main.iframe.bundle.js:4318:42)
    at HTMLBridgeElement.value [as addEventListener] (engine-dom.js:1422:41)
    at L._$AI (vendors~main.iframe.bundle.js:72132:84)
    at S.v (vendors~main.iframe.bundle.js:71920:112)
    at M.g (vendors~main.iframe.bundle.js:71991:13)
    at M._$AI (vendors~main.iframe.bundle.js:71964:191)
    at c.setValue (vendors~main.iframe.bundle.js:71166:122)
    at _callee$ (vendors~main.iframe.bundle.js:71624:65)
    at tryCatch (vendors~main.iframe.bundle.js:71540:1357)

The source of the error is https://github.com/salesforce/lwc/blob/v2.43.0/packages/@lwc/synthetic-shadow/src/faux-shadow/events.ts#L210-L214

And the code for the story:

/// myLwcComponent.stories.ts
import { html } from 'lit-html';

const handleEvent = (e: CustomEvent) => console.log(e);

export const example = () => html`<my-lwc-component @changesegment=${handleEvent}></my-lwc-component>`;

fafnirical avatar Apr 10 '23 18:04 fafnirical

I see, so this is a synthetic shadow issue. Synthetic shadow is deprecated, and we had not planned to make any changes to it. But I can understand if you cannot remove synthetic shadow from your storybook testing.

nolanlawson avatar Apr 10 '23 19:04 nolanlawson

Ah, I also just noticed that this error is only thrown in non-prod mode. Maybe we should tie this into #3245 then.

https://github.com/salesforce/lwc/blob/3770a62e261db4cafa6b82bfa10de21068e1395d/packages/%40lwc/synthetic-shadow/src/faux-shadow/events.ts#L208-L216

nolanlawson avatar Apr 10 '23 19:04 nolanlawson

@fafnirical Actually, I don't understand how you're hitting this error. Your error message is:

Invalid second argument for Element.addEventListener() in [object HTMLElement] for event 
"changesegment". Expected an EventListener but received [object Object].

How is the second argument to addEventListener an object and not a function? Per MDN, the second argument should always be a function.

nolanlawson avatar Apr 10 '23 19:04 nolanlawson

Nevermind, I get it. The second argument can be an object with a handleEvent method. Looks like that is exactly what Lit is using.

nolanlawson avatar Apr 10 '23 19:04 nolanlawson

This issue only logs a warning, it doesn't throw an error. Adding to our trust backlog.

jmsjtu avatar May 07 '24 16:05 jmsjtu

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

git2gus[bot] avatar May 07 '24 16:05 git2gus[bot]