lwc icon indicating copy to clipboard operation
lwc copied to clipboard

event.composedPath() throws

Open bmblb opened this issue 4 years ago • 18 comments

Description

Trying to read composedPath on event throws exception

Steps to Reproduce

  1. create LWC app like in this playground: https://developer.salesforce.com/docs/component-library/tools/playground/9Xurl1YY9/1/edit
  2. click on Click me div

Expected Results

div
(9) ["DIV", "DIV", undefined, "C-APP", "MAIN", "BODY", "HTML", undefined, undefined]
root
(9) ["DIV", "DIV", undefined, "C-APP", "MAIN", "BODY", "HTML", undefined, undefined]
document
(9) ["DIV", "DIV", undefined, "C-APP", "MAIN", "BODY", "HTML", undefined, undefined]

Actual Results

div
TypeError: Illegal invocation
    at Object.composedPathValue (aura_proddebug.js:473)
    at Object.SecureFunction (aura_proddebug.js:18838)
    at Proxy.eval (active_element_test.js:61)
    at HTMLDivElement.handleEvent (aura_proddebug.js:16832)
    at HTMLDivElement.fnOrObj.$$lwcEventWrapper$$ (aura_proddebug.js:2471)
root
TypeError: Illegal invocation
    at Object.composedPathValue (aura_proddebug.js:473)
    at Object.SecureFunction (aura_proddebug.js:18838)
    at Object.eval (active_element_test.js:52)
    at DocumentFragment.handleEvent (aura_proddebug.js:16832)
    at shadowRootWrappedListener (aura_proddebug.js:567)
    at aura_proddebug.js:650
    at Array.forEach (<anonymous>)
    at invokeListenersByPlacement (aura_proddebug.js:647)
    at HTMLElement.domListener (aura_proddebug.js:657)
document
TypeError: Illegal invocation
    at Object.composedPathValue (aura_proddebug.js:473)
    at Object.SecureFunction (aura_proddebug.js:18838)
    at Object.eval (active_element_test.js:43)
    at HTMLDocument.handleEvent (aura_proddebug.js:16832)
    at HTMLDocument.fnOrObj.$$lwcEventWrapper$$ (aura_proddebug.js:2471)

Browsers Affected

Tested in Chrome

Version

  • "lwc-engine": "1.1.13-224.4"

Additional context/Screenshots I found a PR which add event.path property: https://github.com/salesforce/lwc/pull/859 event.path works like composedPath is supposed to, but since it is not in the spec I am not sure if it is safe to use it. I assume it can be removed without a notice? event.composedPath is part of spec though and it would be great to use it, if it wouldn't throw.

bmblb avatar May 15 '20 13:05 bmblb

This is related to locker service, not LWC. As you can see in the playground, LWC works fine, but when inside locker in platform (and we can see some SecureFunction in the error stack), locker prevents access to such feature afaik. /cc @seksenov @manuel-jasso

caridy avatar May 15 '20 17:05 caridy

Can I use event.path though? I can see it was deliberately added as part of mentioned PR. Do you intend to support it in future?

bmblb avatar May 15 '20 23:05 bmblb

No, event.path is non-standard. Yes, there are plans to support composedPath, @seksenov owns that timeline :)

caridy avatar May 16 '20 02:05 caridy

Apologies for thread necromancy but do you have any news on the composedPath()?

I am trying to use https://visjs.org/ Timeline which internally uses https://github.com/naver/hammer.js (for easy use of touch gestures etc across multiple browsers). They have support for shadow DOM but (as far as I can tell) it sometimes dies on Lightning Locker. It's really weird, simple clicks on the timeline or mousewheel (triggers zoom in-out on the timeline) work fine but panning / dragging sideways doesn't call right handlers.

They have piece of code going like that

if (srcEvent.composedPath) {
    srcEventTarget = srcEvent.composedPath()[0];
} else if (srcEvent.path) {
    srcEventTarget = srcEvent.path[0];
} else {
    srcEventTarget = srcEvent.target;
}

In LWC input.srcEvent.composedPath exists but attempts to call it end up with SecureFunction's "Illegal Invocation" exception. As a temp hack I can experiment with commenting it out and using path. Any idea what do you mean by it being non-standard? https://caniuse.com/?search=event%20path looks pretty good?

tomekduda avatar Jun 13 '21 23:06 tomekduda

@tomekduda I can't find any mention of event.path on MDN, but based on this SO answer and this quick test I wrote, it seems like it's supported in Chrome but not Firefox or Safari, and it doesn't seem to be on the standards track.

The issue you're running into with composedPath being blocked by Locker sounds like the same issue as the original poster.

nolanlawson avatar Jun 21 '21 18:06 nolanlawson

that's correct, web components first iteration had 2 APIs that are now deprecated, path and composePath accessor, which became a method in the next iteration. The code above is trying to guess the best possible target, trying with composedPath first, the first element there is usually the original target in open shadows. The second branch is similar, but since that's not accessible in locker (doesn't support legacy path), then it is going to go with the target, and the target is probably not what you want for some cases since it was already retargeted.

As for the invalid invocation exception, that sounds more like a bug.

caridy avatar Jun 21 '21 20:06 caridy

Are there any news on the matter? Recently we noticed that every mouse event that we listen and try to read composedPath from - throws Illegal invocation error. Has smth changed recently with Locker Service that composedPath became inaccessible?

Can we use event.path?

bmblb avatar Mar 31 '22 09:03 bmblb

My events started to work when I ditched Lightning Locker and switched the org over to Lightning Web Security. But it's "all or nothing" global switch, it's not like Locker where you (in aura at least) choose API version and it turns it on/off.

tomekduda avatar Mar 31 '22 10:03 tomekduda

...switched the org over to Lightning Web Security.

That's the way to go here, we will probably not be opening up any new DOM API in legacy locker at this point.

caridy avatar Mar 31 '22 16:03 caridy

@tomekduda unfortunately I cannot switch to Lightning Web Security just yet because library I'm working on does not yet support it. So I just started using a try-catch for event.composedPath falling back to event.path. I suppose path should work for Locker Service and composedPath should be working when we eventually switch to LWS.

bmblb avatar Apr 17 '22 17:04 bmblb

@bmblb

@tomekduda unfortunately I cannot switch to Lightning Web Security just yet because library I'm working on does not yet support it.

I want to learn more. If it works in legacy locker, it will work in LWS for sure. cc @manuel-jasso

So I just started using a try-catch for event.composedPath falling back to event.path. I suppose path should work for Locker Service and composedPath should be working when we eventually switch to LWS.

event.path is not standard, and will be missing in some browsers, e.g.: Safari and FF.

caridy avatar Apr 19 '22 02:04 caridy

@caridy I've just checked firefox, event.path works. Don't know about safari though

bmblb avatar Apr 19 '22 12:04 bmblb

Object.getOwnPropertyDescriptor(Event.prototype, 'path')

Chrome has a descriptor there, Safari-15.4 and FF-98 doesn't.

caridy avatar Apr 19 '22 17:04 caridy

This exception is thrown by the patchedComposedPathValue method while reading the target property of the event.

Here is a snippet from aura_proddebug.js:

function patchedComposedPathValue() {
    const originalTarget = eventTargetGetter.call(this); // <--<< throws "Illegal Invocation" error

    //...
}

The this reference here is a "fake" event object, not an instance of the Event class. It does however have own target property, which can be read via this.target and it returns a Proxy wrapped SecureElement.

I got this error in LWC, not using any third-party code. Is this expected behaviour?

amurashincertinia avatar Apr 19 '22 21:04 amurashincertinia

@caridy

...switched the org over to Lightning Web Security.

That's the way to go here, we will probably not be opening up any new DOM API in legacy locker at this point.

Myself and @amurashinffdc are using the library that @bmblb is mentioning in this git issue. This, unfortunately, is not a feasible outcome for us.

We have a number of other LWS cases open which are not related to this library which are blocking us from recommending that our customers enable Lightning Web Security at this time.

Further, as an ISV, we cannot guarantee that our customers will enable LWS. We have heard from multiple customers that they will NOT be able to upgrade to LWS because of incompatibility with other existing functionality from other packages that we do not own. We cannot force them to upgrade.

Unfortunately, the upgrade path to LWS has not been as simple or transparent as advertised. For that reason desperately need support for this API within Locker Service

pallencertinia avatar Apr 21 '22 17:04 pallencertinia

cc @manuel-jasso @seksenov can you track this somewhere else? this is definitely not LWC related, but Locker.

@pallenffdc you should engage in a conversation with locker PM @seksenov to see what they can do. Keep in mind that enabling this in current locker might NOT be possible for other reasons that I don't know ATM.

caridy avatar Apr 22 '22 04:04 caridy

Thanks @caridy, I've reached out to @seksenov directly.

amurashincertinia avatar Apr 22 '22 08:04 amurashincertinia

Thanks @caridy and @amurashinffdc, I will sync with @seksenov for tracking this.

manuel-jasso avatar Apr 22 '22 20:04 manuel-jasso