Home > Net >  Can I protect custom events from "preventDefault"?
Can I protect custom events from "preventDefault"?

Time:06-01

We have a Stencil web component that renders a user dialog. It consists of an "outerComponent" and an "innerComponent". The outer one cares about dealing with the browser (props, load stuff from cookies etc.) and the inner one renders the actual HTML and lets the user operate it.

(Actually there are more components used inside, from a different project for the UI components such as checkbox, button etc. But I don't think that's relevant here.)

When a checkbox, button etc. is clicked in <inner-component> an onclick-handler within the component is called that executes some UI logic (e.g. set the "checked" property) and then emits a custom event, e.g.:

@Event() checkboxToggleModalEvent: EventEmitter<OptionType>;
...

<checkbox-comp fid="...">
  <input type="checkbox" checked={optionCheckbox.userSelection} onClick={this.handleCheckbox} />
  ...
</checkbox-comp>
...

private handleCheckbox(event: Event) {
    const checkboxElement: HTMLInputElement = event.target as HTMLInputElement;
    ...
    const selection: OptionType = { name: indexId, userSelection };

    this.checkboxToggleModalEvent.emit(selection);
}

Now, in <outer-component> this event is listened for and the handler cares for the "technical" logic:

    @Listen("checkboxToggleModalEvent")
    checkboxToggleModalEventHandler(event) {
        LogService.log.debug(event);

        ... some technical logic
    }

This works fine in most cases. Now we have an integration on one site, where the events apparently do not get emitted correctly or somehow lost in the middle. The UI logic is executed normally but the handler in outerComponent never gets called.

I was able to find the piece of code from an integrated library that causes the problem (sorry for pasting the whole function!):

// From the imported library on customer website:
function(t, exports) {
    try {
        var e = new window.CustomEvent("test");
        if (e.preventDefault(),
        !0 !== e.defaultPrevented)
            throw new Error("Could not prevent default")
    } catch (t) {
        var n = function(t, e) {
            var n, r;
            return e = e || {
                bubbles: !1,
                cancelable: !1,
                detail: void 0
            },
            n = document.createEvent("CustomEvent"),
            n.initCustomEvent(t, e.bubbles, e.cancelable, e.detail),
            r = n.preventDefault,
            n.preventDefault = function() {
                r.call(this);
                try {
                    Object.defineProperty(this, "defaultPrevented", {
                        get: function() {
                            return !0
                        }
                    })
                } catch (t) {
                    this.defaultPrevented = !0
                }
            }
            ,
            n
        };
        n.prototype = window.Event.prototype,
        window.CustomEvent = n
    }
}

If I remove this, everything works as expected.

Now, I'm wondering if we can somehow "protect" our events from being intercepted like this as the component should really work in any case (that's why we chose this technology).

But I also would be very grateful for any hints to what might actually cause the problem.

Thanks a lot!!

CodePudding user response:

  n.prototype = window.Event.prototype,
  window.CustomEvent = n

Looks like they overloaded CustomEvent and injected their own code.

This is the drawback of using 3rd party software.

In this case, only way to get around this is to get in early, and overload CustomEvent yourself.

But you then have the challenge of making their code work; because they did this overloading for a reason.

What is the 3rd party software? Publically shame them.

For those who want to try overloading, execute this early:

window.customeElements.define = () => {}

  • Related