Source: polyfill/Function.js

// Licensed Materials - Property of IBM
//
// IBM Watson Analytics
//
// (C) Copyright IBM Corp. 2015
//
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.

( function( Object, Function, ObjectPolyfill )
{
"use strict";

/**
 * Polyfills for {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function Function}.
 * @class module:barejs/polyfill.Function
 */

/** @lends module:barejs/polyfill.Function# */
var proto = {};

var fnProto = Function.prototype;

/*istanbul ignore else: We test with __ES__ set to 3*/
if ( __ES__ < 5 )
{
    var slice = Array.prototype.slice;

    /**
     * Bind a function to a specific context. Allows for additional prefix arguments to be specified.
     * @param {object} _thisArg The context to bind this method to.
     * @returns {function} A function that will invoke the original function in the specified context,
     *                     optionally with additional parameters prefixed.
     */
    proto.bind = function bind( _thisArg /*, ... */ )
    {
        if ( !ObjectPolyfill.isCallable( this ) )
            throw new TypeError( "Bind must be called on a function" );

        var bound, fn = this, args = null, Anonymous = function(){};

        if ( arguments.length > 1 )
            args = slice.call( arguments, 1, arguments.length );

        // Apply almost the same trick as Object.create, so if the bound method is used as a
        // constructor, we do not change the context and the prototype chain is correct.
        // We can't use Object.create since we need the Anonymous type for the instanceof check
        // Prototype is undefined for native functions, so check it first.
        Anonymous.prototype = fn.prototype /*istanbul ignore next*/|| Object.prototype;

        // Only do parameter mangling if required. This optimization provides a significant speed boost
        if ( args && args.length )
        {
            bound = function()
            {
                var len = arguments.length;
                // Only concat the arguments if there are arguments during invocation (to avoid concat)
                // If this bound method is used as a constructor, don't change the context
                return fn.apply( this instanceof Anonymous ? this : _thisArg, len ? args.concat( slice.call( arguments, 0, len ) ) : args );
            };
        }
        else
        {
            bound = function()
            {
                // If this bound method is used as a constructor, don't change the context
                return fn.apply( this instanceof Anonymous ? this : _thisArg, arguments );
            };
        }
        bound.prototype = new Anonymous();

        // technically the bound function should have the same length as the function bound, but we can't emulate that
        return bound;
    };
}

( function()
{
    var toString = fnProto.toString;

    /*istanbul ignore next: not invoked since NodeJS has a name property on Function.prototype*/
    function name()
    {
        //jshint validthis:true
        if ( this === fnProto )
            return "";

        var match = toString.call( this ).match( /function\s*([a-zA-Z0-9_$]*)\s*\(/ );

        Object.defineProperty( this, "name", { configurable: true, value: ( match && match[1] ) || "" } );

        return this.name;
    }

    // See if the name property isn't exposed, but we can expose it (and it works)
    /*istanbul ignore next: NodeJS has a name property on functions*/
    if ( !name.name && Object.defineProperties && ( name.call( name ) === "name" ) )
        Object.defineProperty( fnProto, "name", { configurable: true, "get": name } );
}() );

ObjectPolyfill.polyfill( Function, null, proto, exports, "Function" );

// End of module
}( Object, Function, require( "./Object" ) ) );