1

I know how to intercept a native function in JavaScript. For example, I use the code below to intercept document.createElement:

var origParseFloat = document.createElement;
document.createElement = function(str) {
     alert("Called");
     return origParseFloat(str);
}

My question here is that how can I intercept methods of an object. I mean what if I want to intercept toDataURL() which is a method for CanvasElement.The code above does not work in this case. so now the main question is how can I intercept toDataURL() in a case such as below:

canvas = document.createElement('canvas');
var tdu = canvas.toDataURL();
0

1 Answer 1

5

You need to monkey patch the method on the prototype it appears in, in your case HTMLCanvasElement.prototype.toDataURL.

var origToDataURL = HTMLCanvasElement.prototype.toDataURL;
HTMLCanvasElement.prototype.toDataURL = function() {
  var r = origToDataURL.apply(this, arguments);
  console.log('toDataURL:', r);
  return r;
};


var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillRect(25, 25, 50, 50);
canvas.toDataURL();
<canvas id="canvas" width="100" height="100"></canvas>

Alternately, if you know the canvas element is created with document.createElement, I suppose you could define a new method on that instance, but this method is less-reliable as elements created with HTML would be missed, and the object structure is technically different.

You can also do something similar for getter functions.

// Function to find the prototype chain object that has a property.
function findPrototypeProperty(obj, prop) {
    while (!obj.hasOwnProperty(prop)) {
        obj = Object.getPrototypeOf(obj);
    }
    return obj;
}

var property = 'sampleRate';
var proto = findPrototypeProperty(AudioContext.prototype, property);

var desc = Object.getOwnPropertyDescriptor(proto, property);
var getter = desc.get;
desc.get = function() {
    var r = getter.apply(this, arguments);
    console.log(property, r);
    return r;
};
Object.defineProperty(proto, property, desc);


var audioCtx = new AudioContext();
void(audioCtx.sampleRate);

2
  • Really appreciate your answer, Could you please also help with the property? I mean what if I want to find out if a property is accessed. For example: baseAudioContext.sampleRate
    – Bathooman
    Commented Mar 20, 2018 at 8:39
  • 1
    @Bathooman I've added a sample on hijacking the sampleRate getter. Commented Mar 20, 2018 at 20:47

Not the answer you're looking for? Browse other questions tagged or ask your own question.