예제 #1
0
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);
}
예제 #2
0
static void scStringMatch(const CFunctionsScopePtr &c, void *) {
	string str = this2string(c);

	string flags="flags", substr, newsubstr, match;
	bool global, ignoreCase, sticky;
	CScriptVarRegExpPtr RegExp = getRegExpData(c, "regexp", true, "flags", substr, global, ignoreCase, sticky);
	if(!global) {
		if(!RegExp)
			RegExp = ::newScriptVar(c->getContext(), substr, flags);
		if(RegExp) {
			try {
				c->setReturnVar(RegExp->exec(str));
			} catch(regex_error e) {
				c->throwError(SyntaxError, string(e.what())+" - "+CScriptVarRegExp::ErrorStr(e.code()));
			}
		}
	} else {
		try { 
			CScriptVarArrayPtr retVar = c->newScriptVar(Array);
			int idx=0;
			string::size_type offset=0;
			global = global && substr.length();
			string::const_iterator search_begin=str.begin(), match_begin, match_end;
			if(regex_search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end)) {
				do {
					offset = match_begin-str.begin();
					retVar->addChild(int2string(idx++), c->newScriptVar(string(match_begin, match_end)));
#if 1 /* Fix from "vcmpeq" (see Issue 14) currently untested */
					if (match_begin == match_end) {
						if (search_begin != str.end())
							++search_begin;
						else
							break;
					} else {
						search_begin = match_end;
					}
#else
					search_begin = match_end;
#endif
				} while(global && regex_search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end));
			}
			if(idx) {
				retVar->addChild("input", c->newScriptVar(str));
				retVar->addChild("index", c->newScriptVar((int)offset));
				c->setReturnVar(retVar);
			} else
				c->setReturnVar(c->constScriptVar(Null));
		} catch(regex_error e) {
			c->throwError(SyntaxError, string(e.what())+" - "+CScriptVarRegExp::ErrorStr(e.code()));
		}
	}
}
예제 #3
0
/*
static void scIntegerValueOf(const CFunctionsScopePtr &c, void *) {
	string str = c->getArgument("str")->toString();

	int val = 0;
	if (str.length()==1)
		val = str.operator[](0);
	c->setReturnVar(c->newScriptVar(val));
}
*/
static void scJSONStringify(const CFunctionsScopePtr &c, void *) {
	uint32_t UniqueID = c->getContext()->allocUniqueID();
	bool hasRecursion=false;
	c->setReturnVar(c->newScriptVar(c->getArgument("obj")->getParsableString("", "   ", UniqueID, hasRecursion)));
	c->getContext()->freeUniqueID();
	if(hasRecursion) c->throwError(TypeError, "cyclic object value");
}
예제 #4
0
static void scRegExpExec(const CFunctionsScopePtr &c, void *) {
	CScriptVarRegExpPtr This = c->getArgument("this");
	if(This)
		c->setReturnVar(This->exec(c->getArgument("str")->toString()));
	else
		c->throwError(TypeError, "Object is not a RegExp-Object in exec(str)");
}
예제 #5
0
//************************************
// Method:    getRegExpData
// FullName:  getRegExpData
// Access:    public static 
// Returns:   bool true if regexp-param=RegExp-Object / other false
// Qualifier:
// Parameter: const CFunctionsScopePtr & c
// Parameter: const string & regexp - parameter name of the regexp
// Parameter: bool noUndefined - true an undefined regexp aims in "" else in "undefined"
// Parameter: const string & flags - parameter name of the flags
// Parameter: string & substr - rgexp.source
// Parameter: bool & global
// Parameter: bool & ignoreCase
// Parameter: bool & sticky
//************************************
static CScriptVarPtr getRegExpData(const CFunctionsScopePtr &c, const string &regexp, bool noUndefined, const char *flags_argument, string &substr, bool &global, bool &ignoreCase, bool &sticky) {
	CScriptVarPtr regexpVar = c->getArgument(regexp);
	if(regexpVar->isRegExp()) {
#ifndef NO_REGEXP
		CScriptVarRegExpPtr RegExp(regexpVar);
		substr = RegExp->Regexp();
		ignoreCase = RegExp->IgnoreCase();
		global = RegExp->Global();
		sticky = RegExp->Sticky();
		return RegExp;
#endif /* NO_REGEXP */
	} else {
		substr.clear();
		if(!noUndefined || !regexpVar->isUndefined()) substr = regexpVar->toString();
		CScriptVarPtr flagVar;
		if(flags_argument && (flagVar = c->getArgument(flags_argument)) && !flagVar->isUndefined()) {
			string flags = flagVar->toString();
			string::size_type pos = flags.find_first_not_of("gimy");
			if(pos != string::npos) {
				c->throwError(SyntaxError, string("invalid regular expression flag ")+flags[pos]);
			}
			global = flags.find_first_of('g')!=string::npos;
			ignoreCase = flags.find_first_of('i')!=string::npos;
			sticky = flags.find_first_of('y')!=string::npos;
		} else
			global = ignoreCase = sticky = false;
	}
	return CScriptVarPtr();
}
예제 #6
0
static void scStringSearch(const CFunctionsScopePtr &c, void *userdata) {
	string str = this2string(c);

	string substr;
	bool global, ignoreCase, sticky;
	getRegExpData(c, "regexp", true, "flags", substr, global, ignoreCase, sticky);
	string::const_iterator search_begin=str.begin(), match_begin, match_end;
#ifndef NO_REGEXP
	try { 
		c->setReturnVar(c->newScriptVar(regex_search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end)?match_begin-search_begin:-1));
	} catch(regex_error e) {
		c->throwError(SyntaxError, string(e.what())+" - "+CScriptVarRegExp::ErrorStr(e.code()));
	}
#else /* NO_REGEXP */
	c->setReturnVar(c->newScriptVar(string_search(str, search_begin, substr, ignoreCase, sticky, match_begin, match_end)?match_begin-search_begin:-1));
#endif /* NO_REGEXP */ 
}
예제 #7
0
static void scStringSplit(const CFunctionsScopePtr &c, void *) {
	const string str = this2string(c);

	string seperator;
	bool global, ignoreCase, sticky;
#ifndef NO_REGEXP
	CScriptVarRegExpPtr RegExp = getRegExpData(c, "separator", true, 0, seperator, global, ignoreCase, sticky);
#else 
	getRegExpData(c, "separator", true, 0, seperator, global, ignoreCase, sticky);
#endif
		
	CScriptVarPtr sep_var = c->getArgument("separator");
	CScriptVarPtr limit_var = c->getArgument("limit");
	int limit = limit_var->isUndefined() ? 0x7fffffff : limit_var->toNumber().toInt32();

	CScriptVarPtr result(c->newScriptVar(Array));
	c->setReturnVar(result);
	if(limit == 0)
		return;
	else if(!str.size() || sep_var->isUndefined()) {
		result->addChild("0", c->newScriptVar(str));
		return;
	}
	if(seperator.size() == 0) {
		for(int i=0; i<min((int)str.size(), limit); ++i)
			result->addChild(i, c->newScriptVar(str.substr(i,1)));
		return;
	}
	int length = 0;
	string::const_iterator search_begin=str.begin(), match_begin, match_end;
#ifndef NO_REGEXP
	smatch match;
#endif
	bool found=true;
	while(found) {
#ifndef NO_REGEXP
		if(RegExp) {
			try { 
				found = regex_search(str, search_begin, seperator, ignoreCase, sticky, match_begin, match_end, match);
			} catch(regex_error e) {
				c->throwError(SyntaxError, string(e.what())+" - "+CScriptVarRegExp::ErrorStr(e.code()));
			}
		} else /* NO_REGEXP */
#endif
			found = string_search(str, search_begin, seperator, ignoreCase, sticky, match_begin, match_end);
		string f;
		if(found) {
			result->addChild(length++, c->newScriptVar(string(search_begin, match_begin)));
			if(length>=limit) break;
#ifndef NO_REGEXP
			for(uint32_t i=1; i<match.size(); i++) {
				if(match[i].matched) 
					result->addChild(length++, c->newScriptVar(string(match[i].first, match[i].second)));
				else
					result->addChild(length++, c->constScriptVar(Undefined));
				if(length>=limit) break;
			}
			if(length>=limit) break;
#endif
			search_begin = match_end;
		} else {
			result->addChild(length++, c->newScriptVar(string(search_begin,str.end())));
			if(length>=limit) break;
		}
	}
}