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;
}
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.
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").
You can use Function. Caller to get the calling function.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With