How to check if the properties of the window object are native?

8

I'm using shim that modifies several of the properties in the browsers window object.

At this point I need to validate if one of the specific properties is native or a shim. Because shim can modify the native property.

For example:

(function () {
  var native = window.alert;
  window.alert = function (): {
    /* faz alguma coisa */
    console.log(arguments);
    return native.apply(this, arguments);
  };
})();

In the example we can see that it does not change the functionality of alert by applying the original to the end, however this alert is no longer the original in another code snippet I would like to know if this method is the original or a modified.

% w / w was used only as an example of the problem.

Without modifying the "shim" that no longer exposes the alert native, how to access the alert native to compare with the modified and know that the function in alert is not native?     

asked by anonymous 06.03.2014 / 15:50

4 answers

6

A native function will return function () { [native code] } when converted to string.

var nativa = typeof funcao === 'function ' && funcao.toString().indexOf('[native code]') !== -1

On the other hand this does not work if the Function.prototype.toString function has been modified.

You can access native javascript functions by using another window (an iframe or a popup) and then compare them:

function retrieveNative(native) {
  var iframe = document.createElement('iframe');
  document.head.appendChild(iframe);
  var retrieved = iframe.contentWindow[native];
  document.head.removeChild(iframe);
  return retrieved;
}
var alertNativo = retrieveNative('alert');

Note: The correct one is to put in body iframe , but if it has not been loaded yet, it will generate an exception, placing in head will not load iframe however it will provide access to window that is the goal in this case.

Credits to @bfavaretto for changes in comments.

    
06.03.2014 / 16:10
7

I do not know how this would be compatible with all browsers, but if you convert the function to string, you will see the source code in the case of non-native functions, and a string containing [native code] in native. For example, in the case of your native variable (tested on the Chrome console):

native.toString(); // function alert() { [native code] } 

Based on this, you can create a function to check this:

function nativa(fn) {
    return typeof fn == 'function' && fn.toString().indexOf('[native code]') > -1;
}
    
06.03.2014 / 16:07
4

To restore a native function, we can use delete . Example:

delete window.alert;

So by applying this to a function that deletes and restores the initial value, we can check if the function is native without the iframe hack:

function isNative(object, name) {
    var aux = object[name]; //salva o valor
    delete object[name]; //apaga a função
    var result = object[name] == aux; //se continuar a mesma é porque é nativa
    object[name] = aux; //restaura a anterior, caso não seja a nativa
    return result;
}

Test:

console.log(window.alert, isNative(window, 'alert'));
window.alert = function() { }
console.log(window.alert, isNative(window, 'alert'));
delete window.alert;
console.log(window.alert, isNative(window, 'alert'));

Output:

  

True

     

False

     

True

Jsfiddle

Note: This technique does not work in some browsers if the function has been defined with the Object.defineProperty " and the writable : false parameter. See the test fiddle . In Chrome there were no problems, but in Firefox the function returned true when it should be false .

Note 2: also does not work if the function definition is done directly in the global scope, for example:

function alert() { ... }
    
06.03.2014 / 16:28
1

One possibility is to "back up" the window before running your shim. After that you can compare the values of the functions with the old value of the backup to see if there was a change.

//Coloque esse código em uma tag <script> anterior à tag <script> com o shim.
var window_backup = {}
for(var k in window){
    window_backup[k] = window[k];
}

function is_native(key){
   return window[key] === window_backup[key];
}

The main advantage of this approach is that you do not rely on implementation details as the result of the toString function, and you do not have to tinker with the window object after running shim.

    
06.03.2014 / 22:35