UNPKG

iced-js

Version:

Interface and Class ExperimenteD JavaScript

1,265 lines (1,260 loc) 35.8 kB
var iced = {}; (function(){ var classes = []; var interfaces = []; iced.class = function(def){ var cls = {}; var curr = classes.length; cls.constructor = undefined; var abscheck = {}; abscheck.constructor = undefined; var intfceCheck = {}; intfceCheck.constructor = undefined; var intfces = {public:{},private:{},protected:{}}; if(def.roles == undefined){ def.roles = []; } else if( !Array.isArray(def.roles)){ def.roles = [def.roles]; } classes.push({engine:{public:[],staticProtected:{}, abstract:{public:{},protected:{}}, roles:def.roles, virtual:[]}, class:cls}); for(var i = 0; i < def.roles.length; i++){ if(interfaces.indexOf(def.roles[i]) < 0){ throw new Exception("interace role of number "+i+" was not declared."); } var privs = ["public","protected","private"]; for(var j = 0; j < privs.length; j++){ for(var prop in def.roles[i][privs[j]]){ intfces[privs[j]][prop] = def.roles[i][privs[j]][prop]; intfceCheck[prop] = false; } } } if(def.parent != undefined){ var p = search(def.parent); if(p < 0){ throw new Error("parent class not found."); } var privs = ["public","protected","private"]; for(var i = 0; i < privs.length; i++){ for(var prop in classes[p].engine.abstract[privs[i]]){ abscheck[prop] = false; } } } if(def.public == undefined){def.public = {}; } if(def.private == undefined){def.private = {}; } if(def.protected == undefined){def.protected = {}; } var proto = {public:{},private:{},protected:{}}; var static = {public:{},private:{},protected:{}}; for(var prop in def.public){ if(abscheck[prop] != undefined){ abscheck[prop] = checkAbstract(def.public[prop], prop, "public", classes[p].engine.abstract); } if(intfceCheck[prop] != undefined){ intfceCheck[prop] = checkAbstract(def.public[prop], prop, "public", intfces); } if(def.public[prop].abstract){ classes[curr].engine.abstract.public[prop] = def.public[prop]; } if(!def.public[prop].static){ proto.public[prop] = def.public[prop]; } else{ static.public[prop] = def.public[prop]; } } for(var prop in def.protected){ if(abscheck[prop] != undefined){ abscheck[prop] = checkAbstract(def.protected[prop], prop, "protected", classes[p].engine.abstract); } if(intfceCheck[prop] != undefined){ intfceCheck[prop] = checkAbstract(def.protected[prop], prop, "protected", intfces); } if(def.protected[prop].abstract){ classes[curr].engine.abstract.protected[prop] = def.protected[prop]; } if(!def.protected[prop].static){ proto.protected[prop] = def.protected[prop]; } else{ static.protected[prop] = def.protected[prop]; } } for(var prop in def.private){ if(abscheck[prop] != undefined){ abscheck[prop] = checkAbstract(def.private[prop], prop, "private", classes[p].engine.abstract); } if(intfceCheck[prop] != undefined){ intfceCheck[prop] = checkAbstract(def.private[prop], prop, "private", intfces); } if(!def.private[prop].static){ proto.private[prop] = def.private[prop]; } else{ static.private[prop] = def.private[prop]; } } for(var prop in abscheck){ if(abscheck[prop] == false){ throw new Error("Abstract inherited member "+prop+" not correctly implemented."); } } for(var prop in intfceCheck){ if(intfceCheck[prop] == false){ throw new Error("Abstract interface roled member "+prop+" not correctly implemented."); } } var staInternal = {}; var staInternal2 = {}; (function(){ var priv = {}; var prot = {}; var virtual = {}; if(p != undefined){ for(var prop in def.parent){ if(prop != "new" && prop != "parent"){ defineInheritedPublic(prop, def.parent); } } for(var prop in classes[p].engine.protectedStatic){ if(prot[prop] == undefined && prop != "parent"){ defineInheritedProtected(prop, classes[p].engine.protectedStatic); } } defineParent("parent", def.parent); } else{ defineParent("parent", Object); } function defineParent(prop, par){ Object.defineProperty(cls, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(virtual, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(prot, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ return staInternal[prop]; }, set: function(val){ return staInternal[prop] = val; }, enumerable:true, configurable:true }); cls[prop] = par; } for(var prop in static.public){ definePublic(prop, static.public[prop]); } for(var prop in static.protected){ defineProtected(prop, static.protected[prop]); } for(var prop in static.private){ definePrivate(prop, static.private[prop]); } classes[curr].engine.protectedStatic = prot; function defineInheritedPublic(prop, par){ Object.defineProperty(staInternal, prop, { get: function(){ return par[prop]; }, set: function(val){ return par[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(cls, prop, { get: function(){ return staInternal[prop]; }, set: function(val){ return staInternal[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(prot, prop, { get: function(){ return staInternal[prop]; }, set: function(val){ return staInternal[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ return staInternal[prop]; }, set: function(val){ return staInternal[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(virtual, prop, { get: function(){ return staInternal[prop]; }, set: function(val){ return staInternal[prop] = val; }, enumerable:true, configurable:true }); } function defineInheritedProtected(prop, par){ Object.defineProperty(staInternal, prop, { get: function(){ return par[prop]; }, set: function(val){ return par[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(virtual, prop, { get: function(){ return staInternal[prop]; }, set: function(val){ return staInternal[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(prot, prop, { get: function(){ return staInternal[prop]; }, set: function(val){ return staInternal[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ return staInternal[prop]; }, set: function(val){ return staInternal[prop] = val; }, enumerable:true, configurable:true }); } function definePublic(prop, defaul){ delete staInternal[prop]; delete staInternal2[prop]; delete virtual[prop]; delete priv[prop]; delete prot[prop]; delete cls[prop]; if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){ defaul.args = []; } Object.defineProperty(cls, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); if(defaul.virtual || defaul.abstract){ Object.defineProperty(priv, prop, { get: function(){ return prot[prop]; }, set: function(val){ return prot[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(staInternal, prop, { get: function(){ return prot[prop]; }, set: function(val){ return prot[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(prot, prop, { get: function(){ if(typeof virtual[prop] == "function"){ return staInternal2[prop]; } return virtual[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ staInternal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return virtual[prop].apply(virtual, arguments); } } return virtual[prop] = val; }, enumerable:true, configurable:true }); } else{ Object.defineProperty(prot, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(virtual, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ if(typeof staInternal[prop] == "function"){ return staInternal2[prop]; } return staInternal[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ staInternal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return staInternal[prop].apply(staInternal, arguments); } } return staInternal[prop] = val; }, enumerable:true, configurable:true }); } cls[prop] = defaul.value || getDefault(defaul.type); if(p != undefined && classes[p].engine.protectedStatic[prop] != undefined){ Object.defineProperty(classes[p].engine.protectedStatic, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); } } function defineProtected(prop, defaul){ delete staInternal[prop]; delete staInternal2[prop]; delete virtual[prop]; delete priv[prop]; delete prot[prop]; if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){ defaul.args = []; } if(defaul.virtual || defaul.abstract){ Object.defineProperty(priv, prop, { get: function(){ return prot[prop]; }, set: function(val){ return prot[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(staInternal, prop, { get: function(){ return prot[prop]; }, set: function(val){ return prot[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(prot, prop, { get: function(){ if(typeof virtual[prop] == "function"){ return staInternal2[prop]; } return virtual[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ staInternal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return virtual[prop].apply(virtual, arguments); } } return virtual[prop] = val; }, enumerable:true, configurable:true }); } else{ Object.defineProperty(prot, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(virtual, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ if(typeof staInternal[prop] == "function"){ return staInternal2[prop]; } return staInternal[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ staInternal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return staInternal[prop].apply(staInternal, arguments); } } return staInternal[prop] = val; }, enumerable:true, configurable:true }); } prot[prop] = defaul.value || getDefault(defaul.type); if(p != undefined && classes[p].engine.protectedStatic[prop] != undefined){ Object.defineProperty(classes[p].engine.protectedStatic, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); } } function definePrivate(prop, defaul){ delete staInternal[prop]; delete staInternal2[prop]; delete virtual[prop]; delete priv[prop]; if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){ defaul.args = []; } Object.defineProperty(virtual, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ if(typeof staInternal[prop] == "function"){ return staInternal2[prop]; } return staInternal[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ staInternal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return staInternal[prop].apply(staInternal, arguments); } } return staInternal[prop] = val; }, enumerable:true, configurable:true }); priv[prop] = defaul.value || getDefault(defaul.type); if(p != undefined && classes[p].engine.protectedStatic[prop] != undefined){ Object.defineProperty(classes[p].engine.protectedStatic, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); } } })(); classes[curr].engine.create = function(calltype, args){ var pub = {}; var priv = {}; var prot = {}; var internal = {}; var internal2 = {}; var virtual = {}; for(var prop in static.public){ defineStaticPublic(prop, static.public[prop]); } for(var prop in static.protected){ defineStaticProtected(prop, static.protected[prop]); } for(var prop in static.private){ defineStaticPrivate(prop, static.private[prop]); } if(p != undefined){ var parentInternal = classes[p].engine.create("extends"); internal.parent = {}; prot.parent = internal.parent; priv.parent = prot.parent; pub.parent = {}; for(var prop in parentInternal){ defineInherited(prop); } } for(var prop in proto.public){ definePublic(prop, proto.public[prop]); } for(var prop in proto.protected){ defineProtected(prop, proto.protected[prop]); } for(var prop in proto.private){ definePrivate(prop, proto.private[prop]); } function defineStaticPublic(prop, defaul){ classes[curr].engine.public.push(prop); if(pub[prop] != undefined){delete pub[prop];} if(priv[prop] != undefined){delete priv[prop];} if(prot[prop] != undefined){delete prot[prop];} if(internal[prop] != undefined){delete internal[prop];} if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){ defaul.args = []; } Object.defineProperty(internal, prop, { get: function(){ if(typeof staInternal[prop] == "function"){ return staInternal2[prop]; } return staInternal[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ staInternal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return staInternal[prop].apply(staInternal, arguments); } } return staInternal[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(pub, prop, { get: function(){ return internal[prop]; }, set: function(val){ return internal[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(prot, prop, { get: function(){ return internal[prop]; }, set: function(val){ return internal[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ return internal[prop]; }, set: function(val){ return internal[prop] = val; }, enumerable:true, configurable:true }); } function defineStaticProtected(prop, defaul){ if(priv[prop] != undefined){delete priv[prop];} if(prot[prop] != undefined){delete prot[prop];} if(internal[prop] != undefined){delete internal[prop];} if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){ defaul.args = []; } Object.defineProperty(internal, prop, { get: function(){ if(typeof staInternal[prop] == "function"){ return staInternal2[prop]; } return staInternal[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ staInternal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return staInternal[prop].apply(staInternal, arguments); } } return staInternal[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(prot, prop, { get: function(){ return internal[prop]; }, set: function(val){ return internal[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ return internal[prop]; }, set: function(val){ return internal[prop] = val; }, enumerable:true, configurable:true }); } function defineStaticPrivate(prop, defaul){ if(internal[prop] != undefined){delete internal[prop];} if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){ defaul.args = []; } Object.defineProperty(internal, prop, { get: function(){ if(typeof staInternal[prop] == "function"){ return staInternal2[prop]; } return staInternal[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ staInternal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return staInternal[prop].apply(staInternal, arguments); } } return staInternal[prop] = val; }, enumerable:true, configurable:true }); if(priv[prop] != undefined){delete priv[prop];} Object.defineProperty(priv, prop, { get: function(){ return internal[prop]; }, set: function(val){ return internal[prop] = val; }, enumerable:true, configurable:true }); } function defineInherited(prop, value){ if(prop != "parent"){ Object.defineProperty(virtual, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(internal, prop, { get: function(){ return parentInternal[prop]; }, set: function(val){ parentInternal[prop] = val; }, enumerable: true, configurable:true }); Object.defineProperty(prot, prop, { get: function(){ return parentInternal[prop]; }, set: function(val){ parentInternal[prop] = val; }, enumerable: true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ return parentInternal[prop]; }, set: function(val){ parentInternal[prop] = val; }, enumerable: true, configurable:true }); if(classes[p].engine.public.indexOf(prop) >= 0){ Object.defineProperty(pub, prop, { get: function(){ return parentInternal[prop]; }, set: function(val){ parentInternal[prop] = val; }, enumerable: true, configurable:true }); } } Object.defineProperty(priv.parent, prop, { get: function(){ return parentInternal[prop]; }, set: function(val){ parentInternal[prop] = val; }, enumerable: true, configurable:true }); if(classes[p].engine.public.indexOf(prop) >= 0){ Object.defineProperty(pub.parent, prop, { get: function(){ return parentInternal[prop]; }, set: function(val){ parentInternal[prop] = val; }, enumerable: true, configurable:true }); } } function definePublic(prop, defaul){ classes[curr].engine.public.push(prop); delete pub[prop]; delete priv[prop]; delete virtual[prop]; delete prot[prop]; delete internal2[prop]; delete internal[prop]; if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){ defaul.args = []; } Object.defineProperty(pub, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); if(defaul.abstract || defaul.virtual){ classes[curr].engine.virtual.push(prop); Object.defineProperty(priv, prop, { get: function(){ return prot[prop]; }, set: function(val){ return prot[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(internal, prop, { get: function(){ return prot[prop]; }, set: function(val){ return prot[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(prot, prop, { get: function(){ if(typeof virtual[prop] == "function"){ return internal2[prop]; } return virtual[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ internal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return virtual[prop].apply(virtual, arguments); } } return virtual[prop] = val; }, enumerable:true, configurable:true }); pub[prop] = defaul.value || getDefault(defaul.type); } else{ Object.defineProperty(prot, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(virtual, prop, { get: function(){ return prot[prop]; }, set: function(val){ return prot[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ if(typeof internal[prop] == "function"){ return internal2[prop]; } return internal[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ internal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return internal[prop].apply(internal, arguments); } } return internal[prop] = val; }, enumerable:true, configurable:true }); pub[prop] = defaul.value || getDefault(defaul.type); } if(parentInternal != undefined && parentInternal[prop] != undefined && classes[p].engine.virtual.indexOf(prop) >= 0){ Object.defineProperty(parentInternal, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); } } function defineProtected(prop, defaul){ delete priv[prop]; delete virtual[prop]; delete prot[prop]; delete internal2[prop]; delete internal[prop]; if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){ defaul.args = []; } if(defaul.abstract || defaul.virtual){ classes[curr].engine.virtual.push(prop); Object.defineProperty(priv, prop, { get: function(){ return prot[prop]; }, set: function(val){ return prot[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(internal, prop, { get: function(){ return prot[prop]; }, set: function(val){ return prot[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(prot, prop, { get: function(){ if(typeof virtual[prop] == "function"){ return internal2[prop]; } return virtual[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ internal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return virtual[prop].apply(virtual, arguments); } } return virtual[prop] = val; }, enumerable:true, configurable:true }); prot[prop] = defaul.value || getDefault(defaul.type); } else{ Object.defineProperty(prot, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(virtual, prop, { get: function(){ return prot[prop]; }, set: function(val){ return prot[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ if(typeof internal[prop] == "function"){ return internal2[prop]; } return internal[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ internal2[prop] = function(){ checkArgs(defaul.args, arguments, prop); return internal[prop].apply(internal, arguments); } } return internal[prop] = val; }, enumerable:true, configurable:true }); prot[prop] = defaul.value || getDefault(defaul.type); } if(parentInternal != undefined && parentInternal[prop] != undefined && classes[p].engine.virtual.indexOf(prop) >= 0){ Object.defineProperty(parentInternal, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); } } function definePrivate(prop, defaul){ delete priv[prop]; delete virtual[prop]; delete internal2[prop]; delete internal[prop]; if((defaul.type == Function || defaul.type == "function") && defaul.args == undefined){ defaul.args = []; } Object.defineProperty(virtual, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); Object.defineProperty(priv, prop, { get: function(){ if(typeof internal[prop] == "function"){ return internal2[prop]; } return internal[prop]; }, set: function(val){ if(defaul.type != undefined && defaul.type != null && !checkNativeType(defaul.type, val) && !checkObjType(defaul.type, val)){ throw new Error("Property "+prop+" not correctly setted. Conflicting types."); } if(typeof val == "function"){ checkArgs(defaul.args, arguments, prop); internal2[prop] = function(){ return internal[prop].apply(internal, arguments); } } return internal[prop] = val; }, enumerable:true, configurable:true }); priv[prop] = defaul.value || getDefault(defaul.type); if(parentInternal != undefined && parentInternal[prop] != undefined && classes[p].engine.virtual.indexOf(prop) >= 0){ Object.defineProperty(parentInternal, prop, { get: function(){ return priv[prop]; }, set: function(val){ return priv[prop] = val; }, enumerable:true, configurable:true }); } } if(calltype == "new"){ if(pub.constructor != undefined){ pub.constructor.apply(internal, args); } Object.defineProperty(pub, "constructor", {get:function(){return cls;}, configurable:true, enumerable:true}); return pub; } else if(calltype = "extends"){ return prot; } } if(!def.abstract){ cls.new = function(){ return classes[curr].engine.create("new", arguments); } } return cls; } iced.interface = function(def){ if(def.public == undefined){def.public = {}; } if(def.private == undefined){def.private = {}; } if(def.protected == undefined){def.protected = {}; } interfaces.push(def); return def; } function search(c){ for(var i = 0; i < classes.length; i++){ if(classes[i].class == c){ return i; } } return -1; } function checkAbstract(impl, prop, priv, abs){ var privacy = searchPriv(prop, abs); if(prop == "public" && privacy != "public" || prop == "protected" && privacy == "private" || abs[privacy][prop].static && !impl.static || !abs[privacy][prop].static && impl.static){ return false; } if(abs[privacy][prop].args == undefined){ abs[privacy][prop].args = []; } if(impl.args == undefined){ impl.args = []; } if(!argcmp( abs[privacy][prop].args, impl.args)){ return false; } return true; function argcmp(expected, implemented){ var opt; for(var i = 0; i < expected.length; i++){ opt = (expected[i].required === undefined ? "optional" : "required"); if(expected[i][opt] === undefined){ throw new Error("function arguments can only be required or optional."); } if(implemented[i][opt] === undefined || implemented[i][opt] != expected[i][opt]){ return false; } } if(implemented.length > expected.length){ for(var i = expected.length; i < implemented.length; i++){ if(implemented[i].optional === undefined){ return false; } } } return true; } function searchPriv(prp, abst){ var privs = ["public","protected","private"]; for(var i = 0; i < privs.length; i++){ for(var prop in abst[privs[i]]){ if(prop == prp){ return privs[i]; } } } } } function checkNativeType(type, val){ if(type == Number || type == "number"){ return !isNaN(val); } if(typeof type == "string"){ return typeof val == type; } return typeof val == ( type == undefined || type.name == undefined ? type : (type.name.toLowerCase())); } function checkObjType(type, val){ if(interfaces.indexOf(type) >= 0 && val === null){ return true; } var parent = (val instanceof Object && val.constructor != undefined ? val.constructor : false); while(parent != Object && parent){ if(parent == type){ return true; } if(classes[search(parent)].engine.roles.indexOf(type) >= 0){ return true; } parent = parent.parent; } return false; } function getDefault(type){ if(type != undefined && type.new != undefined){ return type.new(); } if(typeof type == "string"){ type = type.slice(0,1).toUpperCase() + type.slice(1, type.length); return (typeof window[type] == "function" ? window[type]() : undefined); } if(typeof type == "function"){ return type(); } return null; } function checkArgs(expected, passed, funcname){ funcname = funcname || arguments.callee.name; var required = true; var opt = "required"; for(var i = 0; i < expected.length; i++){ if(expected[i].required === undefined){ required = false; opt = "optional"; } else{ opt = "required" } if(expected[i][opt] === undefined){ throw new Error("function arguments can only be required or optional."); } if(required && passed[i] === undefined){ throw new Error("Too few arguments for function "+funcname); } if(passed[i] != undefined && expected[i][opt] != undefined && expected[i][opt] != null && !checkNativeType(expected[i][opt], passed[i]) && !checkObjType(expected[i][opt], passed[i]) ){ throw new Error("argument of number "+(i+1)+" was passed with wrong type."); } } } iced.getDefault = getDefault; iced.checkObjType = checkObjType; iced.checkNativeType = checkNativeType; })();