public override IScriptable Construct (Context cx, IScriptable scope, object [] args) { BuiltinRegExp re = new BuiltinRegExp (); re.compile (cx, scope, args); ScriptRuntime.setObjectProtoAndParent (re, scope); return re; }
public bool Delete(Context cx) { if (type == Types.None) { return ScriptRuntime.deleteObjectElem (target, name, cx); } return false; }
public override object Call (Context cx, IScriptable scope, IScriptable thisObj, object [] args) { if (args.Length > 0 && args [0] is BuiltinRegExp && (args.Length == 1 || args [1] == Undefined.Value)) { return args [0]; } return Construct (cx, scope, args); }
// neg: // implement the '-' operator inline in the caller // as "-ScriptConvert.ToNumber(val)" // not: // implement the '!' operator inline in the caller // as "!toBoolean(val)" // bitnot: // implement the '~' operator inline in the caller // as "~toInt32(val)" public static object Add(object val1, object val2, Context cx) { if (CliHelper.IsNumber (val1) && CliHelper.IsNumber (val2)) { return (double)val1 + (double)val2; } if (val1 is XMLObject) { object test = ((XMLObject)val1).AddValues (cx, true, val2); if (test != UniqueTag.NotFound) { return test; } } if (val2 is XMLObject) { object test = ((XMLObject)val2).AddValues (cx, false, val1); if (test != UniqueTag.NotFound) { return test; } } if (val1 is EcmaScript.NET.Types.Cli.CliEventInfo) { return ((EcmaScript.NET.Types.Cli.CliEventInfo)val1).Add (val2, cx); } if (val1 is IScriptable) val1 = ((IScriptable)val1).GetDefaultValue (null); if (val2 is IScriptable) val2 = ((IScriptable)val2).GetDefaultValue (null); if (!(val1 is string) && !(val2 is string)) if ((CliHelper.IsNumber (val1)) && (CliHelper.IsNumber (val2))) return (double)val1 + (double)val2; else return ScriptConvert.ToNumber (val1) + ScriptConvert.ToNumber (val2); return string.Concat (ScriptConvert.ToString (val1), ScriptConvert.ToString (val2)); }
internal static IRef createSpecial (Context cx, object obj, string name) { IScriptable target = ScriptConvert.ToObjectOrNull (cx, obj); if (target == null) { throw ScriptRuntime.UndefReadError (obj, name); } Types type; if (name.Equals ("__proto__")) { type = Types.Proto; } else if (name.Equals ("__parent__")) { type = Types.Parent; } else { throw new ArgumentException (name); } if (!cx.HasFeature (Context.Features.ParentProtoProperties)) { // Clear special after checking for valid name! type = Types.None; } return new SpecialRef (target, type, name); }
public bool Has(Context cx) { if (type == Types.None) { return ScriptRuntime.hasObjectElem (target, name, cx); } return true; }
internal InterpreterData(Context.Versions languageVersion, string sourceFile, string encodedSource) { this.languageVersion = languageVersion; this.itsSourceFile = sourceFile; this.encodedSource = encodedSource; Init (); }
public virtual object Perform (Context cx, IScriptable scope, IScriptable thisObj, object [] args, RegExpActions actionType) { GlobData data = new GlobData (); data.mode = actionType; switch ( (RegExpActions)actionType) { case EcmaScript.NET.RegExpActions.Match: { object rval; data.optarg = 1; rval = matchOrReplace (cx, scope, thisObj, args, this, data, false); return data.arrayobj == null ? rval : data.arrayobj; } case EcmaScript.NET.RegExpActions.Search: data.optarg = 1; return matchOrReplace (cx, scope, thisObj, args, this, data, false); case EcmaScript.NET.RegExpActions.Replace: { object arg1 = args.Length < 2 ? Undefined.Value : args [1]; string repstr = null; IFunction lambda = null; if (arg1 is IFunction) { lambda = (IFunction)arg1; } else { repstr = ScriptConvert.ToString (arg1); } data.optarg = 2; data.lambda = lambda; data.repstr = repstr; data.dollar = repstr == null ? -1 : repstr.IndexOf ((char)'$'); data.charBuf = null; data.leftIndex = 0; object val = matchOrReplace (cx, scope, thisObj, args, this, data, true); SubString rc = this.rightContext; if (data.charBuf == null) { if (data.global || val == null || !val.Equals (true)) { /* Didn't match even once. */ return data.str; } SubString lc = this.leftContext; replace_glob (data, cx, scope, this, lc.index, lc.length); } data.charBuf.Append (rc.charArray, rc.index, rc.length); return data.charBuf.ToString (); } default: throw Context.CodeBug (); } }
public static IScriptable ToObjectOrNull (Context cx, object obj) { if (obj is IScriptable) { return (IScriptable)obj; } else if (obj != null && obj != Undefined.Value) { return ToObject (cx, ScriptRuntime.getTopCallScope (cx), obj); } return null; }
public static ScriptableObject InitStandardObjects (Context cx, ScriptableObject scope, bool zealed) { if (scope == null) { scope = new BuiltinObject (); } scope.AssociateValue (LIBRARY_SCOPE_KEY, scope); BaseFunction.Init (scope, zealed); BuiltinObject.Init (scope, zealed); IScriptable objectProto = ScriptableObject.GetObjectPrototype (scope); // Function.prototype.__proto__ should be Object.prototype IScriptable functionProto = ScriptableObject.GetFunctionPrototype (scope); functionProto.SetPrototype (objectProto); // Set the prototype of the object passed in if need be if (scope.GetPrototype () == null) scope.SetPrototype (objectProto); // must precede NativeGlobal since it's needed therein BuiltinError.Init (scope, zealed); BuiltinGlobal.Init (cx, scope, zealed); if (scope is BuiltinGlobalObject) { ((BuiltinGlobalObject)scope).Init (scope, zealed); } BuiltinArray.Init (scope, zealed); BuiltinString.Init (scope, zealed); BuiltinBoolean.Init (scope, zealed); BuiltinNumber.Init (scope, zealed); BuiltinDate.Init (scope, zealed); BuiltinMath.Init (scope, zealed); BuiltinWith.Init (scope, zealed); BuiltinCall.Init (scope, zealed); BuiltinScript.Init (scope, zealed); BuiltinRegExp.Init (scope, zealed); if (cx.HasFeature (Context.Features.E4x)) { Types.E4X.XMLLib.Init (scope, zealed); } Continuation.Init (scope, zealed); if (cx.HasFeature (Context.Features.NonEcmaItObject)) { InitItObject (cx, scope); } return scope; }
public IdEnumeration (object value, Context cx, bool enumValues) { obj = ScriptConvert.ToObjectOrNull (cx, value); if (obj != null) { // null or undefined do not cause errors but rather lead to empty // "for in" loop this.enumValues = enumValues; // enumInit should read all initial ids before returning // or "for (a.i in a)" would wrongly enumerate i in a as well ChangeObject (); } }
public override object ExecIdCall(IdFunctionObject f, Context cx, IScriptable scope, IScriptable thisObj, object [] args) { if (!f.HasTag (FTAG)) { return base.ExecIdCall (f, cx, scope, thisObj, args); } int id = f.MethodId; switch (id) { case Id_constructor: throw Context.ReportRuntimeError ("Direct call is not supported"); } throw new ArgumentException (Convert.ToString (id)); }
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; }
public object Get (Context cx) { switch (type) { case Types.None: return ScriptRuntime.getObjectProp (target, name, cx); case Types.Proto: return target.GetPrototype (); case Types.Parent: return target.ParentScope; default: throw Context.CodeBug (); } }
public virtual object Current(Context cx) { if (!enumValues) return currentId; object result; string s = ScriptRuntime.ToStringIdOrIndex (cx, currentId); if (s == null) { int index = ScriptRuntime.lastIndexResult (cx); result = obj.Get (index, obj); } else { result = obj.Get (s, obj); } return result; }
public object Set (Context cx, object value) { switch (type) { case Types.None: return ScriptRuntime.setObjectProp (target, name, value, cx); case Types.Proto: case Types.Parent: { IScriptable obj = ScriptConvert.ToObjectOrNull (cx, value); if (obj != null) { // Check that obj does not contain on its prototype/scope // chain to prevent cycles IScriptable search = obj; do { if (search == target) { throw Context.ReportRuntimeErrorById ("msg.cyclic.value", name); } if (type == Types.Proto) { search = search.GetPrototype (); } else { search = search.ParentScope; } } while (search != null); } if (type == Types.Proto) { target.SetPrototype (obj); } else { target.ParentScope = obj; } return obj; } default: throw Context.CodeBug (); } }
protected internal string Render(object value, string templateScript) { try { string json = value.ToJson(); StringBuilder script = CreateBaseScript(); script.Append("dust.loadSource(compiledSource);"); script.Append(@"dust.render(templateName, JSON.parse(jsonData), function(err, result){ error = err; output = result; })"); EcmaScript.NET.Context ctx = EcmaScript.NET.Context.Enter(); ScriptableObject scope = ctx.InitStandardObjects(); SetParameters(scope); ScriptableObject.PutProperty(scope, "jsonData", json); ScriptableObject.PutProperty(scope, "compiledSource", Regex.Unescape(templateScript)); ScriptableObject.PutProperty(scope, "error", null); ScriptableObject.PutProperty(scope, "output", ""); ctx.EvaluateString(scope, script.ToString(), "render", 0, null); object error = ScriptableObject.GetProperty(scope, "error"); if (error != null) { throw new InvalidOperationException("An error occurred during dust.render: " + error.ToString()); } string result = ((string)ScriptableObject.GetProperty(scope, "output")); return(Regex.Unescape(result)); } catch (Exception ex) { string sig = "An error occurred rendering template ({0}) : {1}"; string msg = ex.Message; this.Exception = Args.Exception <DustException>(sig, Name, msg); return(string.Format(sig, Name, msg)); } }
private void SetCompiledScript() { try { StringBuilder script = CreateBaseScript(); script.Append("compiledTemplate = dust.compile(templateSource, templateName);"); EcmaScript.NET.Context ctx = EcmaScript.NET.Context.Enter(); ScriptableObject scope = ctx.InitStandardObjects(); SetParameters(scope); ScriptableObject.PutProperty(scope, "compiledTemplate", null); ctx.EvaluateString(scope, script.ToString(), "Compile", 0, null); CompiledScript = (string)ScriptableObject.GetProperty(scope, "compiledTemplate"); SetCompiledTemplate(); } catch (Exception ex) { CompiledScript = string.Format("alert('An error occurred compiling {0}: {1}');", Name, ex.Message); Exception = Args.Exception <DustException>("An error occurred compiling script ({0}) :{1}", ex, Name, ex.Message); } }
public static Namespace Parse (XMLLib lib, Context cx, Object prefixValue, Object uriValue) { String prefix; String uri; if (uriValue is QName) { QName qname = (QName)uriValue; uri = qname.Uri; if (uri == null) { uri = qname.ToString (); } } else { uri = ScriptConvert.ToString (uriValue); } if (uri.Length == 0) { if (prefixValue == Undefined.Value) { prefix = ""; } else { prefix = ScriptConvert.ToString (prefixValue); if (prefix.Length != 0) { throw ScriptRuntime.TypeError ( "Illegal prefix '" + prefix + "' for 'no namespace'."); } } } else if (prefixValue == Undefined.Value) { prefix = ""; } else if (!lib.IsXMLName (cx, prefixValue)) { prefix = ""; } else { prefix = ScriptConvert.ToString (prefixValue); } return new Namespace (lib, prefix, uri); }
private object jsConstructor (Context cx, bool inNewExpr, object [] args) { if (!inNewExpr && args.Length == 1) { return Namespace.Parse (lib, cx, args [0]); } if (args.Length == 0) { return Namespace.Parse (lib, cx); } else if (args.Length == 1) { return Namespace.Parse (lib, cx, args [0]); } else { return Namespace.Parse (lib, cx, args [0], args [1]); } }
public override object ExecIdCall (IdFunctionObject f, Context cx, IScriptable scope, IScriptable thisObj, object [] args) { if (!f.HasTag (NAMESPACE_TAG)) { return base.ExecIdCall (f, cx, scope, thisObj, args); } int id = f.MethodId; switch (id) { case Id_constructor: return jsConstructor (cx, (thisObj == null), args); case Id_toString: return realThis (thisObj, f).ToString (); case Id_toSource: return realThis (thisObj, f).js_toSource (); } throw new System.ArgumentException (System.Convert.ToString (id)); }
/// <summary> Call a method of an object.</summary> /// <param name="cx">the Context object associated with the current thread. /// </param> /// <param name="obj">the JavaScript object /// </param> /// <param name="methodName">the name of the function property /// </param> /// <param name="args">the arguments for the call /// </param> public static object CallMethod (Context cx, IScriptable obj, string methodName, object [] args) { object funObj = GetProperty (obj, methodName); if (!(funObj is IFunction)) { throw ScriptRuntime.NotFunctionError (obj, methodName); } IFunction fun = (IFunction)funObj; // TODO: What should be the scope when calling funObj? // The following favor scope stored in the object on the assumption // that is more useful especially under dynamic scope setup. // An alternative is to check for dynamic scope flag // and use ScriptableObject.getTopLevelScope(fun) if the flag is not // set. But that require access to Context and messy code // so for now it is not checked. IScriptable scope = ScriptableObject.GetTopLevelScope (obj); if (cx != null) { return fun.Call (cx, scope, obj, args); } else { return Context.Call (null, fun, scope, obj, args); } }
internal object SetValue (Context cx, IScriptable scope, IScriptable thisObj, object value) { if (setter == null) { if (getter == null) { return (this.value = value); } else { throw ScriptRuntime.TypeError ("setting a property that has only a getter"); } } else { if (cx == null) cx = Context.CurrentContext; return setter.Call (cx, scope, thisObj, new object [] { value }); } }
internal object GetValue (Context cx, IScriptable scope, IScriptable thisObj) { if (getter == null) { return value; } else { if (cx == null) cx = Context.CurrentContext; return getter.Call (cx, scope, thisObj, ScriptRuntime.EmptyArgs); } }
/// <summary> Analog of C match_or_replace.</summary> private static object matchOrReplace (Context cx, IScriptable scope, IScriptable thisObj, object [] args, RegExpImpl reImpl, GlobData data, bool forceFlat) { BuiltinRegExp re; string str = ScriptConvert.ToString (thisObj); data.str = str; IScriptable topScope = ScriptableObject.GetTopLevelScope (scope); if (args.Length == 0) { object compiled = BuiltinRegExp.compileRE ("", "", false); re = new BuiltinRegExp (topScope, compiled); } else if (args [0] is BuiltinRegExp) { re = (BuiltinRegExp)args [0]; } else { string src = ScriptConvert.ToString (args [0]); string opt; if (data.optarg < args.Length) { args [0] = src; opt = ScriptConvert.ToString (args [data.optarg]); } else { opt = null; } object compiled = BuiltinRegExp.compileRE (src, opt, forceFlat); re = new BuiltinRegExp (topScope, compiled); } data.regexp = re; data.global = (re.Flags & BuiltinRegExp.JSREG_GLOB) != 0; int [] indexp = new int [] { 0 }; object result = null; if (data.mode == EcmaScript.NET.RegExpActions.Search) { result = re.executeRegExp (cx, scope, reImpl, str, indexp, BuiltinRegExp.TEST); if (result != null && result.Equals (true)) result = (int)reImpl.leftContext.length; else result = -1; } else if (data.global) { re.lastIndex = 0; for (int count = 0; indexp [0] <= str.Length; count++) { result = re.executeRegExp (cx, scope, reImpl, str, indexp, BuiltinRegExp.TEST); if (result == null || !result.Equals (true)) break; if (data.mode == EcmaScript.NET.RegExpActions.Match) { match_glob (data, cx, scope, count, reImpl); } else { if (data.mode != EcmaScript.NET.RegExpActions.Replace) Context.CodeBug (); SubString lastMatch = reImpl.lastMatch; int leftIndex = data.leftIndex; int leftlen = lastMatch.index - leftIndex; data.leftIndex = lastMatch.index + lastMatch.length; replace_glob (data, cx, scope, reImpl, leftIndex, leftlen); } if (reImpl.lastMatch.length == 0) { if (indexp [0] == str.Length) break; indexp [0]++; } } } else { result = re.executeRegExp (cx, scope, reImpl, str, indexp, ((data.mode == EcmaScript.NET.RegExpActions.Replace) ? BuiltinRegExp.TEST : BuiltinRegExp.MATCH)); } return result; }
/// <summary> Analog of do_replace in jsstr.c</summary> private static void do_replace (GlobData rdata, Context cx, RegExpImpl regExpImpl) { System.Text.StringBuilder charBuf = rdata.charBuf; int cp = 0; string da = rdata.repstr; int dp = rdata.dollar; if (dp != -1) { int [] skip = new int [1]; do { int len = dp - cp; charBuf.Append (da.Substring (cp, (dp) - (cp))); cp = dp; SubString sub = interpretDollar (cx, regExpImpl, da, dp, skip); if (sub != null) { len = sub.length; if (len > 0) { charBuf.Append (sub.charArray, sub.index, len); } cp += skip [0]; dp += skip [0]; } else { ++dp; } dp = da.IndexOf ((char)'$', dp); } while (dp >= 0); } int daL = da.Length; if (daL > cp) { charBuf.Append (da.Substring (cp, (daL) - (cp))); } }
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 IScriptable Wrap (Context cx, IScriptable scope, object compiled) { return new BuiltinRegExp (scope, compiled); }
public virtual object Compile (Context cx, string source, string flags) { return BuiltinRegExp.compileRE (source, flags, false); }
internal static Namespace Parse (XMLLib lib, Context cx) { return new Namespace (lib, "", ""); }
internal static Namespace Parse (XMLLib lib, Context cx, Object uriValue) { String prefix; String uri; if (uriValue is Namespace) { Namespace ns = (Namespace)uriValue; prefix = ns.Prefix; uri = ns.Uri; } else if (uriValue is QName) { QName qname = (QName)uriValue; uri = qname.Uri; if (uri != null) { prefix = qname.Prefix; } else { uri = qname.ToString (); prefix = null; } } else { uri = ScriptConvert.ToString (uriValue); prefix = (uri.Length == 0) ? "" : null; } return new Namespace (lib, prefix, uri); }
/* * Analog of replace_glob() in jsstr.c */ private static void replace_glob (GlobData rdata, Context cx, IScriptable scope, RegExpImpl reImpl, int leftIndex, int leftlen) { int replen; string lambdaStr; if (rdata.lambda != null) { // invoke lambda function with args lastMatch, $1, $2, ... $n, // leftContext.length, whole string. SubString [] parens = reImpl.parens; int parenCount = (parens == null) ? 0 : parens.Length; object [] args = new object [parenCount + 3]; args [0] = reImpl.lastMatch.ToString (); for (int i = 0; i < parenCount; i++) { SubString sub = parens [i]; if (sub != null) { args [i + 1] = sub.ToString (); } else { args [i + 1] = Undefined.Value; } } args [parenCount + 1] = (int)reImpl.leftContext.length; args [parenCount + 2] = rdata.str; // This is a hack to prevent expose of reImpl data to // JS function which can run new regexps modifing // regexp that are used later by the engine. // TODO: redesign is necessary if (reImpl != cx.RegExpProxy) Context.CodeBug (); RegExpImpl re2 = new RegExpImpl (); re2.multiline = reImpl.multiline; re2.input = reImpl.input; cx.RegExpProxy = re2; try { IScriptable parent = ScriptableObject.GetTopLevelScope (scope); object result = rdata.lambda.Call (cx, parent, parent, args); lambdaStr = ScriptConvert.ToString (result); } finally { cx.RegExpProxy = reImpl; } replen = lambdaStr.Length; } else { lambdaStr = null; replen = rdata.repstr.Length; if (rdata.dollar >= 0) { int [] skip = new int [1]; int dp = rdata.dollar; do { SubString sub = interpretDollar (cx, reImpl, rdata.repstr, dp, skip); if (sub != null) { replen += sub.length - skip [0]; dp += skip [0]; } else { ++dp; } dp = rdata.repstr.IndexOf ((char)'$', dp); } while (dp >= 0); } } int growth = leftlen + replen + reImpl.rightContext.length; System.Text.StringBuilder charBuf = rdata.charBuf; if (charBuf == null) { charBuf = new System.Text.StringBuilder (growth); rdata.charBuf = charBuf; } else { charBuf.EnsureCapacity (rdata.charBuf.Length + growth); } charBuf.Append (reImpl.leftContext.charArray, leftIndex, leftlen); if (rdata.lambda != null) { charBuf.Append (lambdaStr); } else { do_replace (rdata, cx, reImpl); } }