static void scTrace(const CFunctionsScopePtr &c, void * userdata) { CTinyJS *js = (CTinyJS*)userdata; if(c->getArgumentsLength()) c->getArgument(0)->trace(); else js->getRoot()->trace("root"); }
static void scStringConcat(const CFunctionsScopePtr &c, void *userdata) { int length = c->getArgumentsLength(); string str = c->getArgument("this")->getString(); for(int i=(int)userdata; i<length; i++) str.append(c->getArgument(i)->getString()); c->setReturnVar(c->newScriptVar(str)); }
static void scStringConcat(const CFunctionsScopePtr &c, void *userdata) { int length = c->getArgumentsLength(); string str = this2string(c); for(int32_t i=ptr2int32(userdata); i<length; i++) str.append(c->getArgument(i)->toString()); c->setReturnVar(c->newScriptVar(str)); }
static void scArrayPush(const CFunctionsScopePtr &c, void *data) { CScriptVarPtr arr = c->getArgument("this"); int l = arr->getArrayLength(); int args = c->getArgumentsLength(); for (int i=0;i<args;i++) arr->setArrayIndex(l+i, c->getArgument(i)); }
static void scArraySort(const CFunctionsScopePtr &c, void *data) { CScriptVarPtr arr = c->getArgument("this"); CScriptVarFunctionPtr cmp_fnc; uint32_t len = arr->getLength(); if(len > 1) { int args = c->getArgumentsLength(); if(args) { cmp_fnc = c->getArgument(0); if(!cmp_fnc) c->throwError(TypeError, "invalid Array.prototype.sort argument"); } SCRIPTVAR_CHILDS_it begin = lower_bound(arr->Childs.begin(), arr->Childs.end(), "0"); /* in ECMAScript the sort algorithm is not specified * in some cases sort throws a TypeError e.G. an array element is read-only, non-configurable, getter or setter * this will result in a partially sorted array * in worst case the sort algorithm results in an endless loop (more getters with constant return value) * * 42TinyJS checks before sort if an element read-only, setter or getter and throws immediately a TypeError */ for(SCRIPTVAR_CHILDS_it it = begin; it != arr->Childs.end(); ++it) { if(!(*it)->isWritable()) c->throwError(TypeError, "property "+(*it)->getName()+" is read-only"); if(!(*it)->isConfigurable()) c->throwError(TypeError, "property "+(*it)->getName()+" is non-configurable"); if(!(*it)->getVarPtr()->isAccessor()) c->throwError(TypeError, "property "+(*it)->getName()+" is a getter and/or a setter"); } sort(begin, arr->Childs.end(), ::cmp_fnc(c, cmp_fnc)); uint32_t idx = 0; for(SCRIPTVAR_CHILDS_it it=begin; it != arr->Childs.end(); ++it, ++idx) (*it)->reName(int2string(idx)); sort(begin, arr->Childs.end(), cmp_by_name); } c->setReturnVar(arr); }
static void scArrayPush(const CFunctionsScopePtr &c, void *data) { CScriptVarPtr arr = c->getArgument("this"); uint32_t len = c->getLength(arr); uint32_t args = c->getArgumentsLength(); for (uint32_t i=0; i<args; ++i) c->setProperty(arr, i, c->getArgument(i)); }
static void scStringSubstr(const CFunctionsScopePtr &c, void *userdata) { string str = this2string(c); int32_t length = c->getArgumentsLength()-ptr2int32(userdata); int32_t start = c->getArgument("start")->toNumber().toInt32(); if(start<0 || start>=(int)str.size()) c->setReturnVar(c->newScriptVar("")); else if(length>1) { int length = c->getArgument("length")->toNumber().toInt32(); c->setReturnVar(c->newScriptVar(str.substr(start, length))); } else c->setReturnVar(c->newScriptVar(str.substr(start))); }
static void scStringSubstr(const CFunctionsScopePtr &c, void *userdata) { string str = c->getArgument("this")->getString(); int length = c->getArgumentsLength()-(int)userdata; int start = c->getArgument("start")->getInt(); if(start<0 || start>=(int)str.size()) c->setReturnVar(c->newScriptVar("")); else if(length>1) { int length = c->getArgument("length")->getInt(); c->setReturnVar(c->newScriptVar(str.substr(start, length))); } else c->setReturnVar(c->newScriptVar(str.substr(start))); }
static void scStringSlice(const CFunctionsScopePtr &c, void *userdata) { string str = this2string(c); int32_t length = c->getArgumentsLength()-(ptr2int32(userdata) & 1); bool slice = (ptr2int32(userdata) & 2) == 0; int32_t start = c->getArgument("start")->toNumber().toInt32(); int32_t end = (int32_t)str.size(); if(slice && start<0) start = (int32_t)(str.size())+start; if(length>1) { end = c->getArgument("end")->toNumber().toInt32(); if(slice && end<0) end = (int32_t)(str.size())+end; } if(!slice && end < start) { end^=start; start^=end; end^=start; } if(start<0) start = 0; if(start>=(int)str.size()) c->setReturnVar(c->newScriptVar("")); else if(end <= start) c->setReturnVar(c->newScriptVar("")); else c->setReturnVar(c->newScriptVar(str.substr(start, end-start))); }
static void scStringSlice(const CFunctionsScopePtr &c, void *userdata) { string str = c->getArgument("this")->getString(); int length = c->getArgumentsLength()-((int)userdata & 1); bool slice = ((int)userdata & 2) == 0; int start = c->getArgument("start")->getInt(); int end = (int)str.size(); if(slice && start<0) start = str.size()+start; if(length>1) { end = c->getArgument("end")->getInt(); if(slice && end<0) end = str.size()+end; } if(!slice && end < start) { end^=start; start^=end; end^=start; } if(start<0) start = 0; if(start>=(int)str.size()) c->setReturnVar(c->newScriptVar("")); else if(end <= start) c->setReturnVar(c->newScriptVar("")); else c->setReturnVar(c->newScriptVar(str.substr(start, end-start))); }