Detect if a Function is Native Code with JavaScript

By  on  

Every once a while I'll test is a given function is native code -- it's an important part of feature testing whether a function was provided by the browser or via a third party shim which acts like the native feature.  The best way to detect this, of course, is evaluating the toString return value of the function.

The JavaScript

The code to accomplish this task is fairly basic:

function isNative(fn) {
	return (/\{\s*\[native code\]\s*\}/).test('' + fn);
}

Converting to the string representation of the function and performing a regex match on the string is how it's done.  There isn't a better way of confirming a function is native code!

Update!

Lodash creator John-David Dalton has provided a better solution:

;(function() {

  // Used to resolve the internal `[[Class]]` of values
  var toString = Object.prototype.toString;
  
  // Used to resolve the decompiled source of functions
  var fnToString = Function.prototype.toString;
  
  // Used to detect host constructors (Safari > 4; really typed array specific)
  var reHostCtor = /^\[object .+?Constructor\]$/;

  // Compile a regexp using a common native method as a template.
  // We chose `Object#toString` because there's a good chance it is not being mucked with.
  var reNative = RegExp('^' +
    // Coerce `Object#toString` to a string
    String(toString)
    // Escape any special regexp characters
    .replace(/[.*+?^${}()|[\]\/\\]/g, '\\$&')
    // Replace mentions of `toString` with `.*?` to keep the template generic.
    // Replace thing like `for ...` to support environments like Rhino which add extra info
    // such as method arity.
    .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );
  
  function isNative(value) {
    var type = typeof value;
    return type == 'function'
      // Use `Function#toString` to bypass the value's own `toString` method
      // and avoid being faked out.
      ? reNative.test(fnToString.call(value))
      // Fallback to a host object check because some environments will represent
      // things like typed arrays as DOM methods which may not conform to the
      // normal native pattern.
      : (value && type == 'object' && reHostCtor.test(toString.call(value))) || false;
  }
  
  // export however you want
  module.exports = isNative;
}());

So there you have it -- a better solution for detecting if a method is native. Of course you shouldn't use this as a form of security -- it's only to hint toward native support!

Recent Features

  • By
    Serving Fonts from CDN

    For maximum performance, we all know we must put our assets on CDN (another domain).  Along with those assets are custom web fonts.  Unfortunately custom web fonts via CDN (or any cross-domain font request) don't work in Firefox or Internet Explorer (correctly so, by spec) though...

  • By
    5 HTML5 APIs You Didn’t Know Existed

    When you say or read "HTML5", you half expect exotic dancers and unicorns to walk into the room to the tune of "I'm Sexy and I Know It."  Can you blame us though?  We watched the fundamental APIs stagnate for so long that a basic feature...

Incredible Demos

  • By
    PHP IMDB Scraper

    It's been quite a while since I've written a PHP grabber and the itch finally got to me. This time the victim is the International Movie Database, otherwise known as IMDB. IMDB has info on every movie ever made (or so it seems). Their...

  • By
    Create Classy Inputs Using MooTools’ OverText

    The MooTools More library is a goldmine. A treasure chest. Pirates booty, if you will (and, of course, I will). More is full of plugins that add a lot of class and functionality to your website with minimal effort.

Discussion

  1. Comandeer

    There is at least one method to make your own code appear as a native one ;)

    Function.prototype.call.apply(Function.prototype.bind, [function() {}]);

    Yes, it looks scary, but it works! It was used in Google Maps once upon a time and found while debugging JS in Opera by some of its devs (well, I can’t link to original article, because My Opera is gone forever…).

  2. Ok. When I should use it? If I’ve found in my code some function and dont’t know from where this function (native or 3party)? I think that in this situation I can make search by it’s name in IDE.

  3. function notNative() {
      /*{[native code]}*/
    }
    

    :P

  4. Chris Z

    As noted above, native code detection is easy to fool. Never rely on this technique for security purposes. Here’s another way it might be sidestepped:

    function notNative() {
        this.prototype.toString = function () {
            return '{[native code]}';
        }
    }

    However, I agree that there isn’t a better way. JavaScript’s permissiveness, even in Web browsers, doesn’t make true native code detection possible.

  5. @Callum Macrae

    function isNative(fn) {
    	return (/^function\s*[a-z0-9_\$]*\s*\([^)]*\)\s*\{\s*\[native code\]\s*\}/i).test('' + fn);
    }
    
  6. But for security purpose what should we do?

  7. gero3

    Wouldn’t it be better to create an iframe and get the var toString = Object.prototype.toString; from that.

  8. Stanislav

    It doesn’t work correctly if we call bind method of tested function, e.g.:

    var fn = function() {};
    isNative(fn); // false
    isNative(fn.bind()); // true
    
  9. GuTheR

    ReferenceError: module is not defined

  10. Eric P

    Here’s a minified, ready-to-use version: https://jsfiddle.net/of4c34yL/1

  11. James

    So this is working great. But is there a way to actually return a function/constructor to its native-code, original state?

    I guess what I’m asking is – if a third party script has altered that original function, and not been ‘polite’ by saving it to a variable, is the original function temporarily “lost”? Or is there a permanent “ROM” version somewhere?

    Thanks

  12. Henry

    BEHOLD!!

    Function.prototype.isNative = function(){
    return Function.prototype.toString.call(this).slice(-14, -3) === "native code";
    };
  13. xoid

    I use this :

    isNative = f => f.toString() == "function " + f.name + "() {\n    [native code]\n}";
    

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!