x-function
Version:
Extension of Function Class in JsDK
164 lines (138 loc) • 5.48 kB
JavaScript
((metaClass,_F)=>{
metaClass.delegate=function(ctx){
var that=this;
return function(){
with (ctx){
eval(that.body())
}
}
};
metaClass.arrowBody=function(){
const matches = this.toString().match(/^(?:\s*\(?(?:\s*\w*\s*,?\s*)*\)?\s*?=>\s*){?([\s\S]*)}?$/);
if (!matches) {
return null;
}
const firstPass = matches[1];
// Needed because the RegExp doesn't handle the last '}'.
const secondPass =
(firstPass.match(/{/g) || []).length === (firstPass.match(/}/g) || []).length - 1 ?
firstPass.slice(0, firstPass.lastIndexOf('}')) :
firstPass
return secondPass;
};
metaClass.classicBody=function(){
return this.toString().match(/function[^{]+\{([\s\S]*)\}$/)[1];
}
metaClass.body=function(){
if(this.toString().replace(/\s+/g, '').indexOf(')=>')>=1){
return this.arrowBody();
}else{
return this.classicBody();
}
}
metaClass.bodyWihoutChildrenfunctions=function(){
var reducer=this.toString().reduceWhiteSpace();
// console.log(reducer)
this.childrenfunctionsNames().map(function(e,i){
var posFName=reducer.indexOf('function '+e)+('function '+e).length;
var from=reducer.indexOf('function '+e);
var indexFeteh=reducer.indexOf('{',posFName);
var indexCloser=appContext.utils.closeddiama(indexFeteh,reducer,1);
//var openerArgs=reducer.indexOf('(',posFName);
// var closerArgs=appContext.utils.closeddiama(openerArgs,reducer,1);
// console.log(indexFeteh);
//console.log(indexCloser);
reducer=reducer.replaceAll(reducer.substr(from,indexCloser-from+1),'')
return {from:reducer.indexOf('function '+e),to:indexCloser}
//return {name:e,body:reducer.substring(indexFeteh+1,indexCloser),args:reducer.substring(openerArgs+1,closerArgs)}
});
return reducer;
};
/**
* @depends on appContext rabeeJS
* @returns {metaClass@call;childrenfunctionsNames@call;map}
*/
metaClass.childrenfunctionsBodies=function(){
var reducer=this.toString().reduceWhiteSpace();
// console.log(reducer)
return this.childrenfunctionsNames().map(function(e,i){
var posFName=reducer.indexOf('function '+e)+('function '+e).length;
var indexFeteh=reducer.indexOf('{',posFName);
var indexCloser=appContext.utils.closeddiama(indexFeteh,reducer,1);
var openerArgs=reducer.indexOf('(',posFName);
var closerArgs=appContext.utils.closeddiama(openerArgs,reducer,1);
// console.log(indexFeteh);
//console.log(indexCloser);
return {name:e,body:reducer.substring(indexFeteh+1,indexCloser),args:reducer.substring(openerArgs+1,closerArgs)}
});
};
metaClass.childrenfunctionsNames = function(nested) {
function tokenize(code) {
var code = code.split(/\\./).join(''),
regex = /\bfunction\b|\(|\)|\{|\}|\/\*|\*\/|\/\/|"|'|\n|\s+/mg,
tokens = [],
pos = 0;
for (var matches; matches = regex.exec(code); pos = regex.lastIndex) {
var match = matches[0],
matchStart = regex.lastIndex - match.length;
if (pos < matchStart)
tokens.push(code.substring(pos, matchStart));
tokens.push(match);
}
if (pos < code.length)
tokens.push(code.substring(pos));
return tokens;
}
var separators = {
'/*': '*/',
'//': '\n',
'"': '"',
'\'': '\''
};
function extractInnerFunctionNames(func, nested) {
var names = [],
tokens = tokenize(func.toString()),
level = 0;
for (var i = 0; i < tokens.length; ++i) {
var token = tokens[i];
switch (token) {
case '{':
++level;
break;
case '}':
--level;
break;
case '/*':
case '//':
case '"':
case '\'':
var sep = separators[token];
while (++i < tokens.length && tokens[i] !== sep)
;
break;
case 'function':
if (level === 1 || (nested && level)) {
while (++i < tokens.length) {
token = tokens[i];
if (token === '(')
break;
if (/^\s+$/.test(token))
continue;
if (token === '/*' || token === '//') {
var sep = separators[token];
while (++i < tokens.length && tokens[i] !== sep)
;
continue;
}
names.push(token);
break;
}
}
break;
}
}
return names;
};
return extractInnerFunctionNames(this,nested);
};
})(Function.prototype,Function)