public JintEngine() { PermissionSet = new PermissionSet(PermissionState.None); TypeSystem = new TypeSystem(); _runtime = new JintRuntime(this); }
// 15.2.2.1 public static object Constructor(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { // TODO: This looks wrong. It looks like this should be returning // a JsObject that has the value set to the parameter. Chrome returns // 'object' for typeof(new Object(7)) and typeof(Object(7)). if (arguments.Length > 0) { var argument = arguments[0]; var global = runtime.Global; switch (argument.GetJsType()) { case JsType.String: return global.CreateObject(argument, global.StringClass); case JsType.Number: return global.CreateObject((double)argument, global.NumberClass); case JsType.Boolean: return global.CreateObject(argument, global.BooleanClass); default: return argument; } } var obj = runtime.Global.CreateObject(callee.Prototype); obj.DefineProperty( Id.constructor, callee, PropertyAttributes.DontEnum ); return obj; }
public static object Exec(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { var target = (JsObject)@this; var manager = (RegexManager)target.Value; return (object)manager.Exec(runtime, JsValue.ToString(arguments[0])) ?? JsNull.Instance; }
public static object Constructor(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { var target = (JsObject)@this; if (target == runtime.Global.GlobalScope) target = runtime.Global.CreateObject(callee.Prototype); string pattern = null; string options = null; if (arguments.Length > 0) { pattern = JsValue.ToString(arguments[0]); if (arguments.Length > 1) options = JsValue.ToString(arguments[1]); } var manager = new RegexManager(pattern, options); target.SetClass(JsNames.ClassRegexp); target.IsClr = false; target.Value = manager; target.SetProperty(Id.source, pattern); target.SetProperty(Id.lastIndex, (double)0); target.SetProperty(Id.global, BooleanBoxes.Box(manager.IsGlobal)); return target; }
public static object Call(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (!JsValue.IsFunction(@this)) throw new JsException(JsErrorType.TypeError, "The target of call() must be a function"); object target; if (arguments.Length >= 1 && !JsValue.IsNullOrUndefined(arguments[0])) target = arguments[0]; else target = runtime.GlobalScope; object[] argumentsCopy; if (arguments.Length >= 2 && !JsValue.IsNull(arguments[1])) { argumentsCopy = new object[arguments.Length - 1]; Array.Copy(arguments, 1, argumentsCopy, 0, argumentsCopy.Length); } else { argumentsCopy = JsValue.EmptyArray; } // Executes the statements in 'that' and use _this as the target of the call return ((JsObject)@this).Execute(runtime, target, argumentsCopy); }
public static object DecodeURIComponent(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (arguments.Length < 1 || JsValue.IsUndefined(arguments[0])) return String.Empty; return Uri.UnescapeDataString(JsValue.ToString(arguments[0]).Replace("+", " ")); }
public static object Apply(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (!JsValue.IsFunction(@this)) throw new ArgumentException("The target of call() must be a function"); object target; if (arguments.Length >= 1 && !JsValue.IsNullOrUndefined(arguments[0])) target = arguments[0]; else target = runtime.Global.GlobalScope; object[] argumentsCopy; if (arguments.Length >= 2) { var shim = new ArrayShim(arguments[1]); argumentsCopy = new object[shim.Length]; foreach (var item in shim) { argumentsCopy[item.Key] = item.Value; } } else { argumentsCopy = JsValue.EmptyArray; } // Executes the statements in 'that' and use _this as the target of the call return ((JsObject)@this).Execute(runtime, target, argumentsCopy); }
private object GetPropertySlow(JintRuntime runtime, int index, ref DictionaryCacheSlot cacheSlot) { if (_store != null) { return ((JsObject)_value).GetPropertySlow(index, ref cacheSlot); } #if TRACE_SPECULATION Trace.WriteLine("Dictionary cache miss"); #endif return runtime.GetMemberByIndex(_value, index); }
public object GetProperty(JintRuntime runtime, int index, ref DictionaryCacheSlot cacheSlot) { if (_store != null && cacheSlot.Schema == _store.Schema) { #if TRACE_SPECULATION // Trace.WriteLine("Dictionary cache hit"); #endif return _store.GetOwnPropertyRawUnchecked(cacheSlot.Index); } return GetPropertySlow(runtime, index, ref cacheSlot); }
// 15.2.3.2 public static object GetPrototypeOf(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { var @object = arguments[0] as JsObject; if (@object == null) throw new JsException(JsErrorType.TypeError); var constructor = @object.GetProperty(Id.constructor) as JsObject; if (constructor != null) return constructor.GetProperty(Id.prototype); return JsNull.Instance; }
// 15.5.4.6 public static object Concat(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { var sb = new StringBuilder(); sb.Append(JsValue.ToString(@this)); for (int i = 0; i < arguments.Length; i++) { sb.Append(JsValue.ToString(arguments[i])); } return sb.ToString(); }
public static object Min(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (arguments.Length == 0) return DoubleBoxes.PositiveInfinity; var result = JsValue.ToNumber(arguments[0]); foreach (var argument in arguments) { result = Math.Min(JsValue.ToNumber(argument), result); } return result; }
public static object Constructor(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { var target = (JsObject)@this; if (target == runtime.Global.GlobalScope) target = runtime.Global.CreateObject(callee.Prototype); target.SetClass(callee.Delegate.Name); target.IsClr = false; if (arguments.Length > 0) target.SetProperty(Id.message, arguments[0]); return target; }
public static object Constructor(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { var target = (JsObject)@this; if (target == runtime.Global.GlobalScope) return BooleanBoxes.Box(arguments.Length > 0 && JsValue.ToBoolean(arguments[0])); // e.g., var foo = new Boolean(true); if (arguments.Length > 0) target.Value = JsValue.ToBoolean(arguments[0]); else target.Value = false; return @this; }
// 15.5.4.5 public static object CharCodeAt(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (arguments.Length == 0) return String.Empty; int pos = (int)JsValue.ToInteger(arguments[0]); if (pos < 0) return DoubleBoxes.NaN; string value = JsValue.ToString(@this); if (pos >= value.Length) return DoubleBoxes.NaN; return (double)value[pos]; }
// 15.2.3.6 public static object DefineProperty(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { var instance = arguments[0] as JsObject; if (instance == null) throw new JsException(JsErrorType.TypeError); ToPropertyDescriptor( runtime.Global, instance, JsValue.ToString(arguments[1]), arguments[2] ); return instance; }
// 15.5.4.4 public static object CharAt(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (arguments.Length == 0) return String.Empty; int pos = (int)JsValue.ToInteger(arguments[0]); if (pos < 0) return String.Empty; string value = JsValue.ToString(@this); if (pos >= value.Length) return String.Empty; return new String(value[pos], 1); }
public static object Constructor(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { var target = (JsObject)@this; if (target == runtime.Global.GlobalScope) { // 15.7.1 - When Number is called as a function rather than as a constructor, it performs a type conversion. if (arguments.Length > 0) return JsValue.ToNumber(arguments[0]); return (double)0; } // 15.7.2 - When Number is called as part of a new expression, it is a constructor: it initializes the newly created object. target.Value = arguments.Length > 0 ? JsValue.ToNumber(arguments[0]) : 0; return @this; }
// 15.7.4.6 public static object ToExponential(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { double value = JsValue.ToNumber(@this); if (Double.IsInfinity(value) || Double.IsNaN(value)) return ((JsObject)((JsObject)@this).GetProperty(Id.toString)).Execute(runtime, @this, JsValue.EmptyArray); int fractions = 16; if (arguments.Length > 0) fractions = (int)JsValue.ToNumber(arguments[0]); if (fractions > 20 || fractions < 0) throw new JsException(JsErrorType.SyntaxError, "Fraction Digits must be greater than 0 and lesser than 20"); string format = "#." + new String('0', fractions)+ "e+0"; return value.ToString(format, CultureInfo.InvariantCulture); }
// 15.7.4.5 public static object ToFixed(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { int fractions = 0; if (arguments.Length > 0) fractions = (int)JsValue.ToNumber(arguments[0]); if (fractions > 20 || fractions < 0) throw new JsException(JsErrorType.SyntaxError, "Fraction Digits must be greater than 0 and lesser than 20"); double value = JsValue.ToNumber(@this); if (Double.IsNaN(value)) return JsValue.ToString(@this); return value.ToString( "f" + fractions.ToString(CultureInfo.InvariantCulture), CultureInfo.InvariantCulture ); }
public object GetProperty(JintRuntime runtime, double index) { if (_store != null) { int intIndex = (int)index; if (intIndex == index) { #if TRACE_SPECULATION // Trace.WriteLine("Array cache hit"); #endif return _store.GetOwnProperty(intIndex); } } #if TRACE_SPECULATION Trace.WriteLine("Array cache miss"); #endif return runtime.Operation_Member(_value, index); }
public JsGlobal(JintRuntime runtime, JintEngine engine) { if (runtime == null) throw new ArgumentNullException("runtime"); _runtime = runtime; Id.SeedGlobal(this); PrototypeSink = CreatePrototypeSink(); RootSchema = new JsSchema(); Engine = engine; // The Random instance is used by Math to generate random numbers. Random = new Random(); BuildEnvironment(); GlobalScope = CreateGlobalScope(); Marshaller = new Marshaller(runtime, this); Marshaller.Initialize(); }
public static object Constructor(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { var target = (JsObject)@this; if (target == runtime.Global.GlobalScope) { // 15.5.1 - When String is called as a function rather than as a constructor, it performs a type conversion. if (arguments.Length > 0) { var argument = arguments[0]; if (JsValue.IsString(argument)) return argument; return JsValue.ToString(argument); } return String.Empty; } else { // 15.5.2 - When String is called as part of a new expression, it is a constructor: it initializes the newly created object. if (arguments.Length > 0) { var argument = arguments[0]; if (JsValue.IsString(argument)) target.Value = argument; else target.Value = JsValue.ToString(argument); } else { target.Value = String.Empty; } return target; } }
public static object ValueOf(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { return BooleanBoxes.Box(JsValue.ToBoolean(@this)); }
public static object ToString(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { return JsConvert.ToString(JsValue.ToBoolean(@this)); }
public static object EncodeURI(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (arguments.Length < 1 || JsValue.IsUndefined(arguments[0])) return String.Empty; string encoded = Uri.EscapeDataString(JsValue.ToString(arguments[0])); foreach (char c in ReservedEncoded) { encoded = encoded.Replace(Uri.EscapeDataString(c.ToString()), c.ToString()); } foreach (char c in ReservedEncodedComponent) { encoded = encoded.Replace(Uri.EscapeDataString(c.ToString()), c.ToString()); } return encoded.ToUpper(); }
/// <summary> /// 15.1.2.2 /// </summary> public static object ParseInt(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (arguments.Length < 1 || JsValue.IsUndefined(arguments[0])) return JsUndefined.Instance; // In case of an enum, just cast it to an integer if (JsValue.IsClr(arguments[0])) { var value = JsValue.UnwrapValue(arguments[0]); if (value.GetType().IsEnum) return (double)((int)value); } string number = JsValue.ToString(arguments[0]).Trim(); int sign = 1; int radix = 10; if (number == String.Empty) return DoubleBoxes.NaN; if (number.StartsWith("-")) { number = number.Substring(1); sign = -1; } else if (number.StartsWith("+")) { number = number.Substring(1); } if ( arguments.Length >= 2 && !JsValue.IsUndefined(arguments[1]) && JsValue.ToNumber(arguments[1]) != 0 ) radix = (int)JsValue.ToNumber(arguments[1]); if (radix == 0) radix = 10; else if (radix < 2 || radix > 36) return DoubleBoxes.NaN; if (number.ToLower().StartsWith("0x")) radix = 16; try { if (radix == 10) { // most common case double result; if (double.TryParse(number, NumberStyles.Any, CultureInfo.InvariantCulture, out result)) { // parseInt(12.42) == 42 return sign * Math.Floor(result); } else { return DoubleBoxes.NaN; } } else { return (double)(sign * Convert.ToInt32(number, radix)); } } catch { return DoubleBoxes.NaN; } }
/// <summary> /// 15.1.2.3 /// </summary> public static object ParseFloat(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (arguments.Length < 1 || JsValue.IsUndefined(arguments[0])) return JsUndefined.Instance; string number = JsValue.ToString(arguments[0]).Trim(); // the parseFloat function should stop parsing when it encounters an disallowed char Regex regexp = new Regex(@"^[\+\-\d\.e]*", RegexOptions.IgnoreCase); Match match = regexp.Match(number); double result; if (match.Success && double.TryParse(match.Value, NumberStyles.Float, new CultureInfo("en-US"), out result)) return result; else return DoubleBoxes.NaN; }
/// <summary> /// 15.1.2.4 /// </summary> public static object IsNaN(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (arguments.Length < 1) { return BooleanBoxes.Box(false); } return BooleanBoxes.Box(double.NaN.Equals(JsValue.ToNumber(arguments[0]))); }
/// <summary> /// 15.1.2.5 /// </summary> public static object IsFinite(JintRuntime runtime, object @this, JsObject callee, object[] arguments) { if (arguments.Length < 1 || JsValue.IsUndefined(arguments[0])) return BooleanBoxes.False; var value = JsValue.ToNumber(arguments[0]); return BooleanBoxes.Box( !Double.IsNaN(value) && !Double.IsPositiveInfinity(value) && !Double.IsNegativeInfinity(value) ); }