private static string GetErrorMessage(JsValue error) { if (error.IsObject()) { var oi = error.AsObject(); var message = oi.Get("message").AsString(); return message; } else return string.Empty; }
/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.1 /// </summary> /// <param name="input"></param> /// <param name="preferredType"></param> /// <returns></returns> public static JsValue ToPrimitive(JsValue input, Types preferredType = Types.None) { if (input == Null.Instance || input == Undefined.Instance) { return input; } if (input.IsPrimitive()) { return input; } return input.AsObject().DefaultValue(preferredType); }
private JsValue Sort(JsValue thisObj, JsValue[] arguments) { if (!thisObj.IsObject()) { throw new JavaScriptException(Engine.TypeError, "Array.prorotype.sort can only be applied on objects"); } var obj = thisObj.AsObject(); var len = obj.Get("length"); var lenVal = TypeConverter.ToInt32(len); if (lenVal <= 1) { return obj; } var compareArg = arguments.At(0); ICallable compareFn = null; if (compareArg != Undefined.Instance) { compareFn = compareArg.TryCast<ICallable>(x => { throw new JavaScriptException(Engine.TypeError, "The sort argument must be a function"); }); } Comparison<JsValue> comparer = (x, y) => { if (x == Undefined.Instance && y == Undefined.Instance) { return 0; } if (x == Undefined.Instance) { return 1; } if (y == Undefined.Instance) { return -1; } if (compareFn != null) { var s = (int) TypeConverter.ToUint32(compareFn.Call(Undefined.Instance, new[] {x, y})); return s; } var xString = TypeConverter.ToString(x); var yString = TypeConverter.ToString(y); var r = System.String.CompareOrdinal(xString, yString); return r; }; var array = Enumerable.Range(0, lenVal).Select(i => obj.Get(i.ToString())).ToArray(); // don't eat inner exceptions try { System.Array.Sort(array, comparer); } catch (InvalidOperationException e) { throw e.InnerException; } foreach (var i in Enumerable.Range(0, lenVal)) { obj.Put(i.ToString(), array[i], false); } return obj; }
public JsValue Serialize(JsValue value, JsValue replacer, JsValue space) { _stack = new Stack<object>(); // for JSON.stringify(), any function passed as the first argument will return undefined // if the replacer is not defined. The function is not called either. if (value.Is<ICallable>() && replacer == Undefined.Instance) { return Undefined.Instance; } if (replacer.IsObject()) { if (replacer.Is<ICallable>()) { _replacerFunction = replacer; } else { var replacerObj = replacer.AsObject(); if (replacerObj.Class == "Array") { _propertyList = new List<string>(); } foreach (var property in replacerObj.GetOwnProperties().Select(x => x.Value)) { JsValue v = _engine.GetValue(property); string item = null; if (v.IsString()) { item = v.AsString(); } else if (v.IsNumber()) { item = TypeConverter.ToString(v); } else if (v.IsObject()) { var propertyObj = v.AsObject(); if (propertyObj.Class == "String" || propertyObj.Class == "Number") { item = TypeConverter.ToString(v); } } if (item != null && !_propertyList.Contains(item)) { _propertyList.Add(item); } } } } if (space.IsObject()) { var spaceObj = space.AsObject(); if (spaceObj.Class == "Number") { space = TypeConverter.ToNumber(spaceObj); } else if (spaceObj.Class == "String") { space = TypeConverter.ToString(spaceObj); } } // defining the gap if (space.IsNumber()) { if (space.AsNumber() > 0) { _gap = new System.String(' ', (int)System.Math.Min(10, space.AsNumber())); } else { _gap = string.Empty; } } else if (space.IsString()) { var stringSpace = space.AsString(); _gap = stringSpace.Length <= 10 ? stringSpace : stringSpace.Substring(0, 10); } else { _gap = string.Empty; } var wrapper = _engine.Object.Construct(Arguments.Empty); wrapper.DefineOwnProperty("", new PropertyDescriptor(value, true, true, true), false); return Str("", wrapper); }
public static ObjectInstance ToObject(Engine engine, JsValue value) { if (value.IsObject()) { return value.AsObject(); } if (value == Undefined.Instance) { throw new JavaScriptException(engine.TypeError); } if (value == Null.Instance) { throw new JavaScriptException(engine.TypeError); } if (value.IsBoolean()) { return engine.Boolean.Construct(value.AsBoolean()); } if (value.IsNumber()) { return engine.Number.Construct(value.AsNumber()); } if (value.IsString()) { return engine.String.Construct(value.AsString()); } throw new JavaScriptException(engine.TypeError); }
/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.8 /// </summary> /// <param name="o"></param> /// <returns></returns> public static string ToString(JsValue o) { if (o.IsObject()) { var p = o.AsObject() as IPrimitiveInstance; if (p != null) { o = p.PrimitiveValue; } } if (o.IsString()) { return o.AsString(); } if (o == Undefined.Instance) { return Undefined.Text; } if (o == Null.Instance) { return Null.Text; } if (o.IsBoolean()) { return o.AsBoolean() ? "true" : "false"; } if (o.IsNumber()) { return NumberPrototype.ToNumberString(o.AsNumber()); } return ToString(ToPrimitive(o, Types.String)); }
/// <summary> /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.3 /// </summary> /// <param name="o"></param> /// <returns></returns> public static double ToNumber(JsValue o) { // check number first as this is what is usually expected if (o.IsNumber()) { return o.AsNumber(); } if (o.IsObject()) { var p = o.AsObject() as IPrimitiveInstance; if (p != null) { o = p.PrimitiveValue; } } if (o == Undefined.Instance) { return double.NaN; } if (o == Null.Instance) { return 0; } if (o.IsBoolean()) { return o.AsBoolean() ? 1 : 0; } if (o.IsString()) { var s = o.AsString().Trim(); if (String.IsNullOrEmpty(s)) { return 0; } if ("+Infinity".Equals(s) || "Infinity".Equals(s)) { return double.PositiveInfinity; } if ("-Infinity".Equals(s)) { return double.NegativeInfinity; } // todo: use a common implementation with JavascriptParser try { if (!s.StartsWith("0x", StringComparison.OrdinalIgnoreCase)) { var start = s[0]; if (start != '+' && start != '-' && start != '.' && !char.IsDigit(start)) { return double.NaN; } double n = Double.Parse(s, NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowExponent, CultureInfo.InvariantCulture); if (s.StartsWith("-") && n.Equals(0)) { return -0.0; } return n; } int i = int.Parse(s.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); return i; } catch (OverflowException) { return s.StartsWith("-") ? double.NegativeInfinity : double.PositiveInfinity; } catch { return double.NaN; } } return ToNumber(ToPrimitive(o, Types.Number)); }