Search code examples
javascriptxmlhttprequestes6-proxy

How to fix `TypeError: Illegal Invocation` on an XMLHttpRequest wrapped in an ES6 Proxy


I'm writing a proxy for XMLHttpRequests, to force them to return a specific status code. I'm able to run functions on proxy, but setting fails with a TypeError: Illegal Invocation. In the example below, this happens on the line oReq.responseType = "json";. It works if that line is removed, but I need to be able to set the the XHR's properties.

XMLHttpRequest = new Proxy(XMLHttpRequest, {
  construct:function(t,a){
    const req = new t();
    return new Proxy(req, {
      get:function(o,p){
        if(p=='status')return 9001
        return typeof o[p] == 'function'?o[p].bind(o):o[p]
      },
      set: function(target, prop, value, receiver) {
        Reflect.set(target, prop, value, receiver)
        return true;
      },
    })
  }
})

var oReq = new XMLHttpRequest();

oReq.addEventListener("load", transferComplete);
oReq.addEventListener("error", transferComplete);

oReq.open("GET", "https://blossom-emery.glitch.me/yo.json");
oReq.responseType = "json"; // TypeError: Illegal Invocation
oReq.send()

console.log(oReq)

function transferComplete(evt) {
  console.log(evt);
  console.log(oReq.status,oReq.response);
}


Solution

  • For native methods like those on XMLHttpRequest, you can't use the proxy as the receiver, so you'd have to use Reflect.set(target, prop, value, target) (or omit the receiver argument). You could also simply use target[prop] = value here. Likewise with Reflect.get, which you've already opted to use target[prop] instead.