Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

arguments.callee alternative in es6 for determining caller function [duplicate]

In framework, I'm developing, I've constructed mechanism, that allowed to define private and protected properties and methods.
The only ability, I found in ES5 specifications for doing that was using arguments.callee
like this:

descriptor.method = function () {
    if (__callerIsProptected(arguments.callee.caller.caller, cls))
        return value.apply(this, __defaults(_.values(arguments), defaults));
    throw 'Attempt to call ' + access + ' method "' + cls._name + '::' + name + '"';
};

As far as in strict mode calls to arguments.callee and arguments.caller cause throwing of exceptions are there any convenient alternatives to do that?

Update - added whole called function code

    function __descriptor(cls, type, name, descriptor, access) {
    //protected private non-function descriptor.value is replaced by get/set pair
    if (access !== 'public' && type == 'property') {
        delete descriptor.value;
        delete descriptor.writable;
        _.isFunction(descriptor.get) || (descriptor.get = function () {
            return this.__get(name);
        });
        _.isFunction(descriptor.set) || (descriptor.set = function (value) {
            return this.__set(name, value);
        });
    }
    //remove uselesses
    if (_.isFunction(descriptor.get) || _.isFunction(descriptor.set)) {
        delete descriptor.value;
        delete descriptor.writable;
        if (!_.isFunction(descriptor.get)) {
            descriptor.get = function () {
                return this.__get(name);
            };
        }
        if (!_.isFunction(descriptor.set)) {
            descriptor.set = function (value) {
                return this.__set(name, value);
            };
        }
    } else {
        delete descriptor.get;
        delete descriptor.set;
    }
    if (descriptor.get) {
        var getter = descriptor.get;
        //mutate getter and setter if given respectively to access level
        if (access === 'public') {
            descriptor.getter = function () {
                return getter.apply(this, arguments);
            };
        } else if (access === 'protected') {
            descriptor.getter = function () {
                if (__callerIsProptected(arguments.callee.caller.caller, cls))
                    return getter.apply(this, arguments);
                throw 'Attempt to get ' + access + ' property "' + cls._name + '::' + name + '"';
            };
        } else if (access === 'private') {
            descriptor.getter = function () {
                if (__callerIsPrivate(arguments.callee.caller.caller, cls))
                    return getter.apply(this, arguments);
                throw 'Attempt to get ' + access + ' property "' + cls._name + '::' + name + '"';
            };
        }
        descriptor.getter._class = cls;
    }
    if (descriptor.set) {
        var setter = descriptor.set;
        //mutate getter and setter if given respectively to access level
        if (access === 'public') {
            descriptor.setter = function () {
                return setter.apply(this, arguments);
            };
        } else if (access === 'protected') {
            descriptor.setter = function () {
                if (__callerIsProptected(arguments.callee.caller.caller, cls))
                    return setter.apply(this, arguments);
                throw 'Attempt to set ' + access + ' property "' + cls._name + '::' + name + '"';
            };
        } else if (access === 'private') {
            descriptor.setter = function () {
                if (__callerIsPrivate(arguments.callee.caller.caller, cls))
                    return setter.apply(this, arguments);
                throw 'Attempt to set ' + access + ' property "' + cls._name + '::' + name + '"';
            };
        }
        descriptor.setter._class = cls;
    }
    if (descriptor.value !== undefined) {
        if (!_.isFunction(descriptor.value)) return descriptor;
        var value = descriptor.value;
        var defaults = descriptor.defaults || [];
        if (access === 'public' && type == 'method') {
            descriptor.method = function () {
                return value.apply(this, __defaults(_.values(arguments), defaults));
            };
        } else if (access === 'protected') {
            descriptor.method = function () {
                if (__callerIsProptected(arguments.callee.caller.caller, cls))
                    return value.apply(this, __defaults(_.values(arguments), defaults));
                throw 'Attempt to call ' + access + ' method "' + cls._name + '::' + name + '"';
            };
        } else if (access === 'private') {
            descriptor.method = function () {
                if (__callerIsPrivate(arguments.callee.caller.caller, cls))
                    return value.apply(this, __defaults(_.values(arguments), defaults));
                throw 'Attempt to call ' + access + ' method "' + cls._name + '::' + name + '"';
            };
        }
        descriptor.method._class = cls;
    }
    return descriptor;
}
like image 484
brutallord Avatar asked Mar 23 '14 10:03

brutallord


People also ask

What is difference between callee and caller?

A caller is a function that calls another function; a callee is a function that was called. The currently-executing function is a callee, but not a caller. For concreteness, we learn the x86-64 calling conventions for Linux.

What is arguments callee name?

callee is a property of the arguments object. It can be used to refer to the currently executing function inside the function body of that function. This is useful when the name of the function is unknown, such as within a function expression with no name (also called "anonymous functions").

Which of the following methods can be used to get the caller of a function a funk?

You can use Function. Caller to get the calling function.

How do you find out the caller function in JavaScript?

To find out the caller function, name a non-standard the function. caller property in JavaScript. The Function object is replaced by the name of the function of which you need to find out the parent function name. If the function Welcome was invoked by the top-level code, the value of Welcome.


1 Answers

Once I was developing same framework (abandoned) and the only way to figure out a caller in strict mode was to actually throw an exception and RegExp caller name from stack trace. As far as I remember it wasn't always precise. Look for example at the code of caller-id script

like image 94
ThaFog Avatar answered Oct 13 '22 15:10

ThaFog