6

I'm working on an app which uses events. The modules of the app execute in separate containers and I thought about using Proxy to tame the events that are fired. However, I cannot seem to be able to make dispatchEvent accept an event that has been proxied.

The following fails:

let event = new CustomEvent('my event');
let eventProxy = new Proxy(event, {});
let eventTarget = document.createElement('div');

try {
    eventTarget.dispatchEvent(eventProxy); // VM134:4 Uncaught TypeError: Failed to execute 'dispatchEvent' on 'EventTarget': parameter 1 is not of type 'Event'
} catch(error) {
    console.log(error.message);
}

Anyone has any ideas how dispatchEvent can be made to accept proxies?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user253530
  • 2,583
  • 13
  • 44
  • 61
  • What do you mean by "*tame the events that are fired*"? – Bergi Sep 06 '18 at 21:03
  • restrict/filter property values depending of the container in which the event is being caught. – user253530 Sep 06 '18 at 21:23
  • `new Proxy(event, {})` does not create a fully transparent replacement object. You need a lot more to handle that unfortunately. – loganfsmyth Sep 06 '18 at 23:08
  • @loganfsmyth what more? – hldev Apr 02 '22 at 21:42
  • @hldev In the generic case, you need a everything that crosses a proxy boundary to be wrapped, so you should _never_ return any object from a proxy handler unless it is also wrapped in a Proxy. This is generally referred to as a "membrane": https://tvcutsem.github.io/js-membranes https://stackoverflow.com/questions/43177855/how-to-create-a-deep-proxy-aka-proxy-membrane – loganfsmyth Apr 04 '22 at 16:29
  • @loganfsmyth this membrane won't make `dispatchEvent()` accept proxied object – hldev Apr 04 '22 at 17:00
  • @hldev If you have a membrane then _every_ access should go through the membrane, so it would be the membrane's job to unwrap the proxy and pass the underlying event object as the argument for `dispatchEvent` since `dispatchEvent` is also something from outside the membrane. It's very complicated, which is why I'd generally say using a Proxy as a generic "programmable object" is a mistake. – loganfsmyth Apr 04 '22 at 17:18

1 Answers1

0

Could be an old question, but It may help someone, because I didn't find similar Q&As about this.

As pointed in the comments:

Proxy will not create a fully transparent replacement object.

You can also log out eventProxy and see that most of the properties are unaccusable.

My suggestion is wrapping your Event with an object that has a function that returns the event. (for multiple events, you can even use that object for a gateway to all events).

Then, dispatch the event that returns by calling that function.

Now, when you proxy the new object, you can override the get in the handler to log the call.

let event = new CustomEvent('my event');
let eventWrapper = { getEvent: ()=> event };
let handler = {
get: function(target, thisArg, argumentsList) {
    console.log('Logged!');
    return Reflect.get(...arguments)
  }
}
let eventProxy = new Proxy(eventWrapper, handler);
let eventTarget = document.createElement('div');

try {
    eventTarget.dispatchEvent(eventProxy.getEvent());
    console.log("Done!")
} catch(error) {
    console.log(error.message);
}
SomoKRoceS
  • 2,934
  • 2
  • 19
  • 30