public Arguments(BuiltinCall activation) { this.activation = activation; IScriptable parent = activation.ParentScope; ParentScope = parent; SetPrototype(ScriptableObject.GetObjectPrototype(parent)); args = activation.originalArgs; lengthObj = (int)args.Length; BuiltinFunction f = activation.function; calleeObj = f; Context.Versions version = f.LanguageVersion; if (version <= Context.Versions.JS1_3 && version != Context.Versions.Default) { callerObj = null; } else { callerObj = UniqueTag.NotFound; } }
internal InterpreterData(Context.Versions languageVersion, string sourceFile, string encodedSource) { this.languageVersion = languageVersion; this.itsSourceFile = sourceFile; this.encodedSource = encodedSource; Init (); }
internal InterpreterData(Context.Versions languageVersion, string sourceFile, string encodedSource) { this.languageVersion = languageVersion; this.itsSourceFile = sourceFile; this.encodedSource = encodedSource; Init(); }
internal InterpreterData(InterpreterData parent) { this.parentData = parent; this.languageVersion = parent.languageVersion; this.itsSourceFile = parent.itsSourceFile; this.encodedSource = parent.encodedSource; Init (); }
public CompilerEnvirons() { errorReporter = DefaultErrorReporter.instance; languageVersion = Context.Versions.Default; generateDebugInfo = true; useDynamicScope = false; reservedKeywordAsIdentifier = false; allowMemberExprAsFunctionName = false; xmlAvailable = true; optimizationLevel = 0; generatingSource = true; }
/* * See ECMA 15.5.4.8. Modified to match JS 1.2 - optionally takes * a limit argument and accepts a regular expression as the split * argument. */ private static object ImplSplit(Context cx, IScriptable scope, string target, object [] args) { // create an empty Array to return; IScriptable top = GetTopLevelScope(scope); IScriptable result = ScriptRuntime.NewObject(cx, top, "Array", null); // return an array consisting of the target if no separator given // don't check against undefined, because we want // 'fooundefinedbar'.split(void 0) to split to ['foo', 'bar'] if (args.Length < 1) { result.Put(0, result, target); return(result); } // Use the second argument as the split limit, if given. bool limited = (args.Length > 1) && (args [1] != Undefined.Value); long limit = 0; // Initialize to avoid warning. if (limited) { /* Clamp limit between 0 and 1 + string length. */ limit = ScriptConvert.ToUint32(args [1]); if (limit > target.Length) { limit = 1 + target.Length; } } string separator = null; int [] matchlen = new int [1]; IScriptable re = null; RegExpProxy reProxy = null; if (args [0] is IScriptable) { reProxy = cx.RegExpProxy; if (reProxy != null) { IScriptable test = (IScriptable)args [0]; if (reProxy.IsRegExp(test)) { re = test; } } } if (re == null) { separator = ScriptConvert.ToString(args [0]); matchlen [0] = separator.Length; } // split target with separator or re int [] ip = new int [] { 0 }; int match; int len = 0; bool [] matched = new bool [] { false }; string [] [] parens = new string [] [] { null }; Context.Versions version = cx.Version; while ((match = find_split(cx, scope, target, separator, version, reProxy, re, ip, matchlen, matched, parens)) >= 0) { if ((limited && len >= limit) || (match > target.Length)) { break; } string substr; if (target.Length == 0) { substr = target; } else { substr = target.Substring(ip [0], (match) - (ip [0])); } result.Put(len, result, substr); len++; /* * Imitate perl's feature of including parenthesized substrings * that matched part of the delimiter in the new array, after the * split substring that was delimited. */ // CB, 02.01.2007: Don't do this, causes bug #287630 // https://bugzilla.mozilla.org/show_bug.cgi?query_format=specific&order=relevance+desc&bug_status=__open__&id=287630 /* * if (re != null && matched [0] == true) { * int size = parens [0].Length; * for (int num = 0; num < size; num++) { * if (limited && len >= limit) * break; * result.Put (len, result, parens [0] [num]); * len++; * } * matched [0] = false; * } */ ip [0] = match + matchlen [0]; if (version < Context.Versions.JS1_3 && version != Context.Versions.Default) { /* * Deviate from ECMA to imitate Perl, which omits a final * split unless a limit argument is given and big enough. */ if (!limited && ip [0] == target.Length) { break; } } } return(result); }
/* * Used by js_split to find the next split point in target, * starting at offset ip and looking either for the given * separator substring, or for the next re match. ip and * matchlen must be reference variables (assumed to be arrays of * length 1) so they can be updated in the leading whitespace or * re case. * * Return -1 on end of string, >= 0 for a valid index of the next * separator occurrence if found, or the string length if no * separator is found. */ private static int find_split(Context cx, IScriptable scope, string target, string separator, Context.Versions version, RegExpProxy reProxy, IScriptable re, int [] ip, int [] matchlen, bool [] matched, string [] [] parensp) { int i = ip [0]; int length = target.Length; /* * Perl4 special case for str.split(' '), only if the user has selected * JavaScript1.2 explicitly. Split on whitespace, and skip leading w/s. * Strange but true, apparently modeled after awk. */ if (version == Context.Versions.JS1_2 && re == null && separator.Length == 1 && separator [0] == ' ') { /* Skip leading whitespace if at front of str. */ if (i == 0) { while (i < length && char.IsWhiteSpace(target [i])) { i++; } ip [0] = i; } /* Don't delimit whitespace at end of string. */ if (i == length) { return(-1); } /* Skip over the non-whitespace chars. */ while (i < length && !char.IsWhiteSpace(target [i])) { i++; } /* Now skip the next run of whitespace. */ int j = i; while (j < length && char.IsWhiteSpace(target [j])) { j++; } /* Update matchlen to count delimiter chars. */ matchlen [0] = j - i; return(i); } /* * Stop if past end of string. If at end of string, we will * return target length, so that * * "ab,".split(',') => new Array("ab", "") * * and the resulting array converts back to the string "ab," * for symmetry. NB: This differs from perl, which drops the * trailing empty substring if the LIMIT argument is omitted. */ if (i > length) { return(-1); } /* * Match a regular expression against the separator at or * above index i. Return -1 at end of string instead of * trying for a match, so we don't get stuck in a loop. */ if (re != null) { return(reProxy.FindSplit(cx, scope, target, separator, re, ip, matchlen, matched, parensp)); } /* * Deviate from ECMA by never splitting an empty string by any separator * string into a non-empty array (an array of length 1 that contains the * empty string). */ if (version != Context.Versions.Default && version < Context.Versions.JS1_3 && length == 0) { return(-1); } /* * Special case: if sep is the empty string, split str into * one character substrings. Let our caller worry about * whether to split once at end of string into an empty * substring. * * For 1.2 compatibility, at the end of the string, we return the length as * the result, and set the separator length to 1 -- this allows the caller * to include an additional null string at the end of the substring list. */ if (separator.Length == 0) { if (version == Context.Versions.JS1_2) { if (i == length) { matchlen [0] = 1; return(i); } return(i + 1); } return((i == length) ? -1 : i + 1); } /* Punt to j.l.s.indexOf; return target length if seperator is * not found. */ if (ip [0] >= length) { return(length); } i = target.IndexOf(separator, ip [0]); return((i != -1) ? i : length); }
public virtual void initFromContext(Context cx) { setErrorReporter (cx.ErrorReporter); this.languageVersion = cx.Version; useDynamicScope = cx.compileFunctionsWithDynamicScopeFlag; generateDebugInfo = (!cx.GeneratingDebugChanged || cx.GeneratingDebug); reservedKeywordAsIdentifier = cx.HasFeature (Context.Features.ReservedKeywordAsIdentifier); allowMemberExprAsFunctionName = cx.HasFeature (Context.Features.MemberExprAsFunctionName); xmlAvailable = cx.HasFeature (Context.Features.E4x); getterAndSetterSupport = cx.HasFeature (Context.Features.GetterAndSetter); optimizationLevel = cx.OptimizationLevel; generatingSource = cx.GeneratingSource; activationNames = cx.activationNames; }
private static SubString interpretDollar(Context cx, RegExpImpl res, string da, int dp, int [] skip) { char dc; int num, tmp; if (da [dp] != '$') { Context.CodeBug(); } /* Allow a real backslash (literal "\\") to escape "$1" etc. */ Context.Versions version = cx.Version; if (version != Context.Versions.Default && version <= Context.Versions.JS1_4) { if (dp > 0 && da [dp - 1] == '\\') { return(null); } } int daL = da.Length; if (dp + 1 >= daL) { return(null); } /* Interpret all Perl match-induced dollar variables. */ dc = da [dp + 1]; if (BuiltinRegExp.isDigit(dc)) { int cp; if (version != Context.Versions.Default && version <= Context.Versions.JS1_4) { if (dc == '0') { return(null); } /* Check for overflow to avoid gobbling arbitrary decimal digits. */ num = 0; cp = dp; while (++cp < daL && BuiltinRegExp.isDigit(dc = da [cp])) { tmp = 10 * num + (dc - '0'); if (tmp < num) { break; } num = tmp; } } else { /* ECMA 3, 1-9 or 01-99 */ int parenCount = (res.parens == null) ? 0 : res.parens.Length; num = dc - '0'; if (num > parenCount) { return(null); } cp = dp + 2; if ((dp + 2) < daL) { dc = da [dp + 2]; if (BuiltinRegExp.isDigit(dc)) { tmp = 10 * num + (dc - '0'); if (tmp <= parenCount) { cp++; num = tmp; } } } if (num == 0) { return(null); /* $0 or $00 is not valid */ } } /* Adjust num from 1 $n-origin to 0 array-index-origin. */ num--; skip [0] = cp - dp; return(res.getParenSubString(num)); } skip [0] = 2; switch (dc) { case '$': return(new SubString("$")); case '&': return(res.lastMatch); case '+': return(res.lastParen); case '`': if (version == Context.Versions.JS1_2) { /* * JS1.2 imitated the Perl4 bug where left context at each step * in an iterative use of a global regexp started from last match, * not from the start of the target string. But Perl4 does start * $` at the beginning of the target string when it is used in a * substitution, so we emulate that special case here. */ res.leftContext.index = 0; res.leftContext.length = res.lastMatch.index; } return(res.leftContext); case '\'': return(res.rightContext); } return(null); }
public virtual int FindSplit(Context cx, IScriptable scope, string target, string separator, IScriptable reObj, int [] ip, int [] matchlen, bool [] matched, string [] [] parensp) { int i = ip [0]; int length = target.Length; int result; Context.Versions version = cx.Version; BuiltinRegExp re = (BuiltinRegExp)reObj; while (true) { // imitating C label /* JS1.2 deviated from Perl by never matching at end of string. */ int ipsave = ip [0]; // reuse ip to save object creation ip [0] = i; object ret = re.executeRegExp(cx, scope, this, target, ip, BuiltinRegExp.TEST); if (ret == null || !ret.Equals(true)) { // Mismatch: ensure our caller advances i past end of string. ip [0] = ipsave; matchlen [0] = 1; matched [0] = false; return(length); } i = ip [0]; ip [0] = ipsave; matched [0] = true; SubString sep = this.lastMatch; matchlen [0] = sep.length; if (matchlen [0] == 0) { /* * Empty string match: never split on an empty * match at the start of a find_split cycle. Same * rule as for an empty global match in * match_or_replace. */ if (i == ip [0]) { /* * "Bump-along" to avoid sticking at an empty * match, but don't bump past end of string -- * our caller must do that by adding * sep->length to our return value. */ if (i == length) { if (version == Context.Versions.JS1_2) { matchlen [0] = 1; result = i; } else { result = -1; } break; } i++; goto again; // imitating C goto } } // PR_ASSERT((size_t)i >= sep->length); result = i - matchlen [0]; break; again: ; } int size = (parens == null) ? 0 : parens.Length; parensp [0] = new string [size]; for (int num = 0; num < size; num++) { SubString parsub = getParenSubString(num); parensp [0] [num] = parsub.ToString(); } return(result); }