How does one override a method in order to intercept any call to this method?

73 Views Asked by At

In this widget there is a function isPermitted(). How would I intercept it and overwrite it.

I use the following to intercept other functions isPermittedDomain etc, but unable to overwrite the isPermitted function. Any suggestions?

this is the function I'm trying to intercept and overwrite:

n.prototype.isPermitted = function (t) {var n = !this.direct || 'OW2017' !== e.AppSettings.omo_username;
return !n && t && this.onFail(new e.ErrorMessage({ error: 'FEED_NOT_PERMITTED' })), n;
};

My code:

function intercept(obj, prop, callback) {
  var oldVal = null;
  Object.defineProperty(
    obj, prop, {
      get: function() {
        return oldVal;
      },
      set: function(newVal) {
        callback.call(this, newVal);
        oldVal = newVal;
      },
      enumerable: true,
      configurable: true
    });
};

intercept(Opta, 'Subscriptions', function(Subscriptions) {
  Subscriptions.isPermittedDomain = function() {
    return true;
  };
  intercept(Subscriptions, 'feeds', function(feeds) {
    const t = Opta.Trans.loadTerms({
      term_set_id: Opta.Trans.mapSportIdToTerms(1)
    });
    Opta.when(t).done(startReact);
  });
});
1

There are 1 best solutions below

0
On BEST ANSWER

How about an approach which straightforwardly provides interception handling by wrapping the intercepting handler around the original (prototypal) isPermitted method. And for convenience reasons (code-reuse of the wrapping pattern) one would make use of an immediately invoked arrow function expression.

// n.prototype.isPermitted = function (t) {
//   var n = !this.direct || ('OW2017' !== e.AppSettings.omo_username);
// 
//   return !n && t && this.onFail(new e.ErrorMessage({
//     error: 'FEED_NOT_PERMITTED'
//   })), n;
// };

// test code based on the OP's provide exampe.

class N {
  direct = true;

  isPermitted(t) {
    // const n = !this.direct || 'OW2017' !== e.AppSettings.omo_username;
    const n = !this.direct;

    // return !n && t && this.onFail(new e.ErrorMessage({
    //   error: 'FEED_NOT_PERMITTED'
    // })), n;
    if (!n && t) {
      this.onFail(new Error('FEED_NOT_PERMITTED'));
    }
    return n;
  }

  onFail(error) {
    console.log({ "error.message": error.message });
  }
}

function handleIsPermittedInterception(proceed, args, target) {
  /**
   *  - implement all functionality which is specific to the
   *    interception of the original `isPermitted` method.
   *
   *    - one does get passed in ...
   *
   *      - the original `isPermitted` method as `proceed`.
   *      - the method's arguments as a real arrray as `args`.
   *      - the method's `this` context as `target`.
   */
  console.log('+++ interception handling :: begin +++');
  console.log({ args, target, proceed });

  // the intercepted sole `t` parameter.
  const [ t ] = args;

  // implement e.g. handling upon `t`'s value.
  console.log({ t });

  // invocation of the original method within its correct context.
  const intermediateResult = proceed.apply(target, args);

  // implement e.g. handling upon the `intermediateResult`'s value.
  console.log({ intermediateResult });
  
  console.log('--- interception handling :: end ---\n\n\n');

  return intermediateResult // or any implementation specific value.
}

N.prototype.isPermitted = ((proceed, interceptor) => {

  // - wrap the handling of the interception
  //   around the original `isPermitted` method.
  return function (...args) {

    // - forwarding call wich passes all necessary
    //   values to the provided intercetion handler.
    return interceptor(proceed, args, this);
  };
})(N.prototype.isPermitted, handleIsPermittedInterception);

const n = new N;
console.log('n.isPermitted(true) ...', n.isPermitted(true));
.as-console-wrapper { min-height: 100%!important; top: 0; }