var BetterJS=function(){var QGetterSetter={};QGetterSetter._Property=function(baseObject,property){console.assert(typeof baseObject==="object"||typeof baseObject==="function");console.assert(typeof property==="string");var originValue=baseObject[property];var _this=this;this._getters=[];this._setters=[];Object.defineProperty(baseObject,"__"+property,{enumerable:false,writable:true,value:baseObject[property]});Object.defineProperty(baseObject,property,{enumerable:true,get:function getterHandler(){var value=baseObject["__"+property];for(var i=0;i<_this._getters.length;i++){value=_this._getters[i](value,getterHandler.caller,property)}return value},set:function setterHandler(value){for(var i=0;i<_this._setters.length;i++){value=_this._setters[i](value,setterHandler.caller,property)}baseObject["__"+property]=value}})};if(typeof window==="undefined")module.exports=QGetterSetter;QGetterSetter._initObjectIfNeeded=function(baseObject,property){var name="__bjsGetSet_"+property;if(baseObject[name]===undefined){Object.defineProperty(baseObject,name,{enumerable:false,value:new QGetterSetter._Property(baseObject,property)})}return name};QGetterSetter.defineGetter=function(baseObject,property,getterFn){var name=QGetterSetter._initObjectIfNeeded(baseObject,property);baseObject[name]._getters.push(getterFn)};QGetterSetter.defineSetter=function(baseObject,property,setterFn){var name=QGetterSetter._initObjectIfNeeded(baseObject,property);baseObject[name]._setters.push(setterFn)};QGetterSetter.overloadObjectPrototype=function(){Object.prototype.__defineQGetter__=function(property,getterFn){QGetterSetter.defineGetter(this,property,getterFn)};Object.prototype.__defineQSetter__=function(property,setterFn){QGetterSetter.defineSetter(this,property,setterFn)}};var Stacktrace={};if(typeof window==="undefined")module.exports=Stacktrace;Stacktrace.parse=function(nShift,error){nShift=nShift!==undefined?nShift:0;if(error===undefined){try{i.dont.exist+=0}catch(exception){error=exception}}console.assert(error instanceof Error);if(typeof window==="undefined"){var stacktrace=_parserV8(error)}else if(navigator.userAgent.match("Chrome/")){var stacktrace=_parserV8(error)}else if(navigator.userAgent.match("Firefox/")){var stacktrace=_parserFirefox(error)}else if(navigator.userAgent.match("PhantomJS/")){var stacktrace=_parserPhantomJS(error)}else{console.assert(false,"Stacktrace.parse() not yet implemented for",navigator.userAgent);return[]}nShift+=1;console.assert(stacktrace.length>=nShift,"stacktrace length not large enougth to shift "+nShift);return stacktrace.slice(nShift);function _parserV8(error){var lines=error.stack.split("\n").slice(1);var stacktrace=[];lines.forEach(function(line){if(line.match(/\(native\)$/)){var matches=line.match(/^\s*at (.+) \(native\)/);stacktrace.push(new Stacktrace.Frame({fct:matches[1],url:"native",line:1,column:1}))}else if(line.match(/\)$/)){var matches=line.match(/^\s*at (.+) \((.+):(\d+):(\d+)\)/);stacktrace.push(new Stacktrace.Frame({fct:matches[1],url:matches[2],line:parseInt(matches[3],10),column:parseInt(matches[4],10)}))}else{var matches=line.match(/^\s*at (.+):(\d+):(\d+)/);stacktrace.push(new Stacktrace.Frame({url:matches[1],fct:"",line:parseInt(matches[2],10),column:parseInt(matches[3],10)}))}});return stacktrace}function _parserFirefox(error){var lines=error.stack.split("\n").slice(0,-1);var stacktrace=[];lines.forEach(function(line){var matches=line.match(/^(.*)@(.+):(\d+)$/);stacktrace.push(new Stacktrace.Frame({fct:matches[1]===""?"":matches[1],url:matches[2],line:parseInt(matches[3],10),column:1}))});return stacktrace}function _parserPhantomJS(error){var lines=error.stack.split("\n").slice(1);var stacktrace=[];lines.forEach(function(line){if(line.match(/\(native\)$/)){var matches=line.match(/^\s*at (.+) \(native\)/);stacktrace.push(new Stacktrace.Frame({fct:matches[1],url:"native",line:1,column:1}))}else if(line.match(/\)$/)){var matches=line.match(/^\s*at (.+) \((.+):(\d+)\)/);stacktrace.push(new Stacktrace.Frame({fct:matches[1],url:matches[2],line:parseInt(matches[3],10),column:1}))}else{var matches=line.match(/^\s*at (.+):(\d+)/);stacktrace.push(new Stacktrace.Frame({url:matches[1],fct:"",line:parseInt(matches[2],10),column:1}))}});return stacktrace}};Stacktrace.Frame=function(opts){this.url=opts.url;this.fct=opts.fct;this.line=opts.line;this.column=opts.column};Stacktrace.Frame.prototype.originId=function(){var str=this.fct+"@"+this.url+":"+this.line+":"+this.column;return str};Stacktrace.Frame.prototype.toString=function(){return this.originId()};Stacktrace.Frame.prototype.basename=function(){return this.url.match(/([^/]*)$/)[1]||"."};Stacktrace.Tracker=function(){this._klasses={}};Stacktrace.Tracker.prototype.record=function(className,stackLevel){stackLevel=stackLevel!==undefined?stackLevel:0;var at=Stacktrace.Track;var stackFrame=Stacktrace.parse()[stackLevel+2];this._klasses[className]=this._klasses[className]||{counter:0,perOrigins:{}};var klass=this._klasses[className];klass.counter+=1;var originId=stackFrame.fct+"@"+stackFrame.url+":"+stackFrame.line;var perOrigins=klass.perOrigins;perOrigins[originId]=perOrigins[originId]!==undefined?perOrigins[originId]:0;perOrigins[originId]+=1};Stacktrace.Tracker.prototype.reset=function(){this._klasses={}};Stacktrace.Tracker.prototype.klasses=function(){return this._klasses};Stacktrace.Tracker.prototype.dump=function(){var report=this.reportString.apply(this,arguments);console.log(report)};Stacktrace.Tracker.prototype.reportString=function(classNameRegExp,maxNOrigin){classNameRegExp=classNameRegExp||/./;maxNOrigin=maxNOrigin!==undefined?maxNOrigin:3;var output=[];var classNames=Object.keys(this._klasses);classNames.sort(function(a,b){return this._klasses[b].counter-this._klasses[a].counter}.bind(this));classNames=classNames.filter(function(className){return className.match(classNameRegExp)?true:false});classNames.forEach(function(className){var klass=this._klasses[className];output.push(className+": total "+klass.counter+" times");var perOrigins=klass.perOrigins;var ranks=Object.keys(perOrigins);ranks.sort(function(a,b){return perOrigins[b]-perOrigins[a]});ranks.slice(0,maxNOrigin).forEach(function(originId){var perOrigin=perOrigins[originId];output.push(" "+originId+" - "+perOrigin+" times")})}.bind(this));return output.join("\n")};var assertWhichStop=function(condition,message,useDebugger){if(condition)return;if(assertWhichStop.useDebugger||useDebugger)debugger;throw new Error(message||"Assert Failed")};assertWhichStop.useDebugger=false;if(typeof window==="undefined")module.exports=assertWhichStop;assertWhichStop.overloadConsole=function(){console.assert=assertWhichStop};var Stacktrace=Stacktrace||require("./stacktrace.js");var ConsoleLogger={};ConsoleLogger._origConsole={console:console,log:console.log,warn:console.warn,error:console.error};if(typeof window==="undefined")module.exports=ConsoleLogger;ConsoleLogger.Severity={all:0,log:1,warn:2,error:3,nothing:99};ConsoleLogger.Severity.dfl=ConsoleLogger.Severity.all;ConsoleLogger.formatterIdentity=function(args,stackFrame,severity){return args};ConsoleLogger.formatterTimeStamp=function(args,stackFrame,severity){var present=new Date;var prefixColor=ConsoleLogger._formatterSeverityColor(severity);var prefix=prefixColor+pad(present.getHours(),2)+":"+pad(present.getMinutes(),2)+":"+pad(present.getSeconds(),2)+ConsoleLogger._formatterColor.reset;args=Array.prototype.slice.call(args,0);args.unshift(prefix);return args;function pad(val,len){val=String(val);while(val.length=filter.severity?true:false}return ConsoleLogger.Severity[severity]>=ConsoleLogger.Severity.dfl?true:false};ConsoleLogger._print=function(severity,args){var stackFrame=Stacktrace.parse()[2];if(ConsoleLogger.filter(severity,stackFrame)===false)return;var args=ConsoleLogger.formatter(args,stackFrame,severity);var _console=ConsoleLogger._origConsole;if(severity==="log"){_console.log.apply(_console.console,args)}else if(severity==="warn"){_console.warn.apply(_console.console,args)}else if(severity==="error"){_console.error.apply(_console.console,args)}else console.assert(false,"invalid severity: "+severity)};ConsoleLogger.log=function(){ConsoleLogger._print("log",arguments)};ConsoleLogger.warn=function(){ConsoleLogger._print("warn",arguments)};ConsoleLogger.error=function(){ConsoleLogger._print("error",arguments)};ConsoleLogger.overloadConsole=function(){console.log=ConsoleLogger.log;console.warn=ConsoleLogger.warn;console.error=ConsoleLogger.error};var GcMonitor=function(){var _this=this;var timerid=null;var inNode=typeof window==="undefined"?true:false;var usedHeapSize=inNode?function(){return process.memoryUsage().heapUsed}:function(){if(!window.performance||!window.performance.memory)return 0;return window.performance.memory.usedJSHeapSize};if(GcMonitor.isAvailable()===false){console.warn("memory info are unavailable... for chrome, use --enable-memory-info. Other browsers dont have this feature.")}this.start=function(onChange,period){period=period||1e3/60;onChange=onChange||function(delta){function bytesToSize(bytes,nFractDigit){var sizes=["Bytes","KB","MB","GB","TB"];if(bytes==0)return"0";nFractDigit=nFractDigit!==undefined?nFractDigit:2;var precision=Math.pow(10,nFractDigit);var i=Math.floor(Math.log(bytes)/Math.log(1024));return Math.round(bytes*precision/Math.pow(1024,i))/precision+" "+sizes[i]}console.warn(new Date+" -- GC occured! saved",bytesToSize(delta),"consuming at",bytesToSize(burnRate),"per second")};timerid=setInterval(function(){_this.check(onChange)},period);return this};this.stop=function(){cancelInterval(timerid)};var lastUsedHeap=null;var lastTimestamp=null;var burnRate=null;this.check=function(onChange){onChange=onChange||function(property){};var present=Date.now();var currUsedSize=usedHeapSize();if(lastUsedHeap===null){lastUsedHeap=currUsedSize;lastTimestamp=present;return}var deltaMem=currUsedSize-lastUsedHeap;if(deltaMem<0){onChange(-deltaMem,burnRate)}else{var deltaTime=present-lastTimestamp;var newBurnrate=deltaMem/(deltaTime/1e3);if(burnRate===null)burnRate=newBurnrate;var friction=.99;burnRate=burnRate*friction+newBurnrate*(1-friction)}lastUsedHeap=currUsedSize;lastTimestamp=present};this.burnRate=function(){if(burnRate===null)return 0;return burnRate};this.usedHeapSize=function(){return usedHeapSize()}};GcMonitor.isAvailable=function(){var inNode=typeof window==="undefined"?true:false;if(inNode)return true;if(!window.performance)return false;if(!window.performance.memory)return false;return true};if(typeof window==="undefined")module.exports=GcMonitor;var GlobalDetector=function(){var inBrowser=typeof window!=="undefined"?true:false;var _global=inBrowser?window:global;console.assert(_global,"failed to find a global namespace! bailing out!");var initialGlobals={};for(var propname in _global){initialGlobals[propname]=true}var foundGlobals={};var _this=this;var timerid=null;this.start=function(onChange,period){period=period||1e3;onChange=onChange||function(newProperty){var str=new Date+" -- Warning Global Detected!!! ";str+=inBrowser?"window":"global";str+="['"+newProperty+"'] === "+_global[newProperty];console.warn(str)};timerid=setInterval(function(){_this.check(onChange)},period);return this};this.stop=function(){cancelInterval(_timerid)};this.check=function(onChange){var newGlobal=false;onChange=onChange||function(property){};for(var property in _global){if(initialGlobals[property])continue;if(GlobalDetector.ignoreList.indexOf(property)!==-1)continue;if(foundGlobals[property])continue;foundGlobals[property]=true;newGlobal=true;onChange(property)}return newGlobal};this.foundGlobals=function(){return foundGlobals}};GlobalDetector.ignoreList=[];if(typeof window==="undefined")module.exports=GlobalDetector;var Privatize={};var Stacktrace=Stacktrace||require("./stacktrace.js");var QGetterSetter=QGetterSetter||require("./qgettersetter.js");if(typeof window==="undefined")module.exports=Privatize;Privatize.pushPrivateOkFn=function(instance,privateFn){Privatize.init(instance);var callerFn=privateFn.__betterjsOriginalFn||privateFn;instance._privateOkFn.push(callerFn)};Privatize.init=function(instance){if(instance._privateOkFn===undefined){Object.defineProperty(instance,"_privateOkFn",{enumerable:false,writable:true,value:[]})}};Privatize.property=function(instance,property){Privatize.init(instance);QGetterSetter.defineGetter(instance,property,function aFunction(value,caller,property){if(instance._privateOkFn.indexOf(caller)===-1){var stackFrame=Stacktrace.parse()[2];console.assert(false,'access to private property "'+property+'" from '+stackFrame)}return value});QGetterSetter.defineSetter(instance,property,function aFunction(value,caller,property){if(instance._privateOkFn.indexOf(caller)===-1){var stackFrame=Stacktrace.parse()[2];console.assert(false,'access to private property "'+property+'" from '+stackFrame)}return value})};Privatize.function=function(instance,fn){var functionName=fn.name||"anonymous";return function _checkFunction(){var caller=_checkFunction.caller;if(instance._privateOkFn.indexOf(caller)===-1){var stackFrame=Stacktrace.parse()[1];console.assert(false,'access to private function "'+functionName+'" from '+stackFrame)}return fn.apply(this,arguments)}};Privatize.prepare=function(instance){Privatize.init(instance);for(var property in instance){if(typeof instance[property]!=="function")continue;Privatize.pushPrivateOkFn(instance,instance[property])}};Privatize.privatize=function(instance,selectorRegexp){selectorRegexp=selectorRegexp||/^_.*/;Privatize.init(instance);for(var property in instance){if(property.match(selectorRegexp)===null)continue;if(typeof instance[property]==="function"){instance[property]=Privatize.function(instance,instance[property])}else{Privatize.property(instance,property)}}};var StrongTyping={};var QGetterSetter=QGetterSetter||require("../src/qgettersetter.js");if(typeof window==="undefined")module.exports=StrongTyping;StrongTyping.setter=function(baseObject,property,allowedTypes){var value=baseObject[property];var isValid=StrongTyping.value(value,allowedTypes);console.assert(isValid,"initial value got invalid type");QGetterSetter.defineSetter(baseObject,property,function(value){var isValid=StrongTyping.value(value,allowedTypes);console.assert(isValid,"Invalid type. MUST be a",StrongTyping.allowedTypesToString(allowedTypes),"and it is",StrongTyping.valueTypeToString(value));return value})};StrongTyping.fn=function(originalFn,paramsTypes,returnTypes){return function StrongTyping_fn(){console.assert(arguments.length<=paramsTypes.length,"function received "+arguments.length+" parameters but allows only "+paramsTypes.length+"!");for(var i=0;i0)output+=", ";output+=typeToString(allowedTypes[i])}output+="]";return output;function typeToString(allowedType){if(allowedType===Number)return"Number";if(allowedType===String)return"String";if(allowedType===Object)return"Object";if(allowedType===undefined)return"undefined";return allowedType.toString()}};StrongTyping.valueTypeToString=function(value){if(typeof value==="string")return"String";if(typeof value==="number")return"Number";if(typeof value==="object")return"Object";return typeof value};var ObjectIcer=function(target,permission){console.assert(ObjectIcer.isAvailable,"harmony Proxy not enable. try chrome://flags or node --harmony");permission=permission||"rw";console.assert(permission==="rw"||permission==="write"||permission==="read","permission argument is invalid");var checkRead=permission==="read"||permission==="rw";var checkWrite=permission==="write"||permission==="rw";return Proxy.create({get:function(receiver,name){if(checkRead&&name in target===false){console.assert(name in target===true,"reading unexisting property "+name)}return target[name]},set:function(receiver,name,value){if(checkWrite&&name in target===false){console.assert(name in target===true,"setting unexisting property "+name)}target[name]=value;return true},has:function(name){return name in target?true:false}})};ObjectIcer.isAvailable=typeof Proxy!=="undefined"&&typeof Proxy.create==="function";if(typeof window==="undefined")module.exports=ObjectIcer;var StrongTyping=StrongTyping||require("../strongtyping.js");var Privatize=Privatize||require("../privatize.js");var FunctionAttr=function(originalFn,attributes){var functionName=attributes.name||originalFn.name;var privateDone=false;return wrapFunction(originalFn,functionName,function(instance,args){if(privateDone===false&&attributes.private===true){Privatize.pushPrivateOkFn(instance,originalFn);privateDone=true}if(attributes.arguments!==undefined){var allowedTypes=attributes.arguments;console.assert(args.length<=allowedTypes.length,"function received "+args.length+" parameters but allows only "+allowedTypes.length+"!");for(var i=0;i