Пример #1
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.1
        /// </summary>
        /// <param name="thisArg"></param>
        /// <param name="arguments"></param>
        /// <returns></returns>
        public override JsValue Call(JsValue thisArg, JsValue[] arguments)
        {
            using (new StrictModeScope(Strict, true))
            {
                // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
                JsValue thisBinding;
                if (StrictModeScope.IsStrictModeCode)
                {
                    thisBinding = thisArg;
                }
                else if (thisArg == Undefined.Instance || thisArg == Null.Instance)
                {
                    thisBinding = Engine.Global;
                }
                else if (!thisArg.IsObject())
                {
                    thisBinding = TypeConverter.ToObject(Engine, thisArg);
                }
                else
                {
                    thisBinding = thisArg;
                }

                var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Engine, Scope);

                Engine.EnterExecutionContext(localEnv, localEnv, thisBinding);

                try
                {
                    Engine.DeclarationBindingInstantiation(
                        DeclarationBindingType.FunctionCode,
                        _functionDeclaration.FunctionDeclarations, 
                        _functionDeclaration.VariableDeclarations, 
                        this,
                        arguments);

                    var result = Engine.ExecuteStatement(_functionDeclaration.Body);

                    if (result.Type == Completion.Throw)
                    {
                        JavaScriptException ex = new JavaScriptException(result.GetValueOrDefault());
                        ex.Location = result.Location;
                        throw ex;
                    }

                    if (result.Type == Completion.Return)
                    {
                        return result.GetValueOrDefault();
                    }
                }
                finally
                {
                    Engine.LeaveExecutionContext();
                }

                return Undefined.Instance;
            }
        }
 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;            
 }
Пример #3
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.2
        /// </summary>
        /// <param name="o"></param>
        /// <returns></returns>
        public static bool ToBoolean(JsValue o)
        {
            if (o.IsObject())
            {
                return true;
            }

            if (o == Undefined.Instance || o == Null.Instance)
            {
                return false;
            }
            
            if (o.IsBoolean())
            {
                return o.AsBoolean();
            }

            if (o.IsNumber())
            {
                var n = o.AsNumber();
                if (n.Equals(0) || double.IsNaN(n))
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }

            if (o.IsString())
            {
                var s = o.AsString();
                if (String.IsNullOrEmpty(s))
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }

            return true;
        }
Пример #4
0
        /// <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)));
        }
Пример #5
0
        public static Vector2?FromJsValue(JsValue obj)
        {
            if (obj == null || obj.IsNull() || obj.IsUndefined())
            {
                return(null);
            }

            if (obj.IsNumber())
            {
                var num = (float)obj.AsNumber();
                return(new Vector2(num, num));
            }

            if (obj.IsArray())
            {
                var v0 = obj.AsArray()[0];
                var v1 = obj.AsArray()[1];

                var x = v0.IsNumber() ? (float)v0.AsNumber() : 0;
                var y = v1.IsNumber() ? (float)v1.AsNumber() : 0;
                return(new Vector2(x, y));
            }

            if (obj.IsObject())
            {
                var ob = obj.AsObject();

                var v0 = ob.Get("x");
                var v1 = ob.Get("y");

                var x = v0.IsNumber() ? (float)v0.AsNumber() : 0;
                var y = v1.IsNumber() ? (float)v1.AsNumber() : 0;

                return(new Vector2(x, y));
            }

            return(null);
        }
        public static ObjectInstance ToObject(Engine engine, JsValue value)
        {
            if (value.IsObject())
            {
                return(value.AsObject());
            }

            if (value == Undefined.Instance)
            {
                //throw new JavaScriptException(engine.TypeError);
                return(null);
            }

            if (value == Null.Instance)
            {
                //throw new JavaScriptException(engine.TypeError);
                return(null);
            }

            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, value + " is not a object");
        }
Пример #7
0
        private static void RunEvalLoop()
        {
            try
            {
                if (File.Exists(HistoryFilePath))
                {
                    foreach (string line in File.ReadLines(HistoryFilePath).TakeLast(60))
                    {
                        if (line != _removedString)
                        {
                            ReadLine.AddHistory(line);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                CliConsole.WriteErrorLine($"Could not load cmd history from {HistoryFilePath} {e.Message}");
            }

            ReadLine.AutoCompletionHandler = new AutoCompletionHandler();

            while (true)
            {
                try
                {
                    if (_terminal != Terminal.Cmder)
                    {
                        Console.ForegroundColor = ColorScheme.Text;
                    }
                    int    bufferSize = 1024 * 16;
                    string statement;
                    using (Stream inStream = System.Console.OpenStandardInput(bufferSize))
                    {
                        Console.SetIn(new StreamReader(inStream, Console.InputEncoding, false, bufferSize));
                        CliConsole.WriteLessImportant("nethermind> ");
                        statement = _terminal == Terminal.Cygwin ? Console.ReadLine() : ReadLine.Read();
                        CleanStatement(statement);

                        if (!File.Exists(HistoryFilePath))
                        {
                            File.Create(HistoryFilePath).Dispose();
                        }

                        if (!SecuredCommands.Any(sc => statement.Contains(sc)))
                        {
                            ReadLine.AddHistory(statement);

                            using (var fileStream = File.AppendText(HistoryFilePath))
                            {
                                fileStream.WriteLine(statement);
                            }
                        }
                        else
                        {
                            ReadLine.AddHistory(_removedString);
                        }
                    }

                    if (statement == "exit")
                    {
                        break;
                    }

                    JsValue result = _engine.Execute(statement);
                    if (result.IsObject() && result.AsObject().Class == "Function")
                    {
                        CliConsole.WriteGood(result.ToString());
                        CliConsole.WriteLine();
                    }
                    else if (!result.IsNull())
                    {
                        string text = Serializer.Serialize(result.ToObject(), true);
//                        File.AppendAllText("C:\\temp\\cli.txt", text);
                        CliConsole.WriteGood(text);
                    }
                    else
                    {
                        CliConsole.WriteLessImportant("null");
                        CliConsole.WriteLine();
                    }

//                    bool isNull = result.IsNull();
//                    if (!isNull)
//                    {
//                        CliConsole.WriteString(result);
//                    }
                }
                catch (Exception e)
                {
                    CliConsole.WriteException(e);
                }
            }
        }
Пример #8
0
            private static JsValue ScalarToRawString(JsValue self2, JsValue[] args)
            {
                if (args.Length != 2)
                {
                    throw new InvalidOperationException("scalarToRawString(document, lambdaToField) may be called on with two parameters only");
                }


                JsValue firstParam = args[0];

                if (firstParam.IsObject() == false || args[0].AsObject() is BlittableObjectInstance == false)
                {
                    throw new InvalidOperationException("scalarToRawString(document, lambdaToField) may be called with a document first parameter only");
                }

                JsValue secondParam = args[1];

                if (args[1].IsObject() == false || secondParam.AsObject() is FunctionInstance == false)
                {
                    throw new InvalidOperationException("scalarToRawString(document, lambdaToField) must be called with a second lambda argument");
                }



                BlittableObjectInstance selfInstance = firstParam.AsObject() as BlittableObjectInstance;
                FunctionInstance        lambda       = secondParam.AsObject() as FunctionInstance;
                //TODO: expose this in Jint directly instead of reflection


                var funcDeclField = typeof(ScriptFunctionInstance).GetField("_functionDeclaration", BindingFlags.Instance | BindingFlags.NonPublic);
                var func          = (IFunction)funcDeclField.GetValue(lambda);


                var ret = func.Body.Body.As <ReturnStatement[]>();

                if (ret.Length != 1)
                {
                    throw new InvalidOperationException("scalarToRawString(document, lambdaToField) lambda to field must contain a single return expression");
                }
                StaticMemberExpression staticMemberExpression = ret[0].Argument.As <StaticMemberExpression>();
                var prop = staticMemberExpression.Property;

                if (staticMemberExpression.Object is Identifier == false)
                {
                    throw new InvalidOperationException("scalarToRawString(document, lambdaToField) lambda to field must contain a single return expression of a single field");
                }
                var propName = prop.As <Identifier>().Name;

                if (selfInstance.OwnValues.TryGetValue(propName, out var existingValue))
                {
                    if (existingValue.Changed)
                    {
                        return(existingValue.Value);
                    }
                }

                var propertyIndex = selfInstance.Blittable.GetPropertyIndex(propName);

                if (propertyIndex == -1)
                {
                    return(new JsValue(new ObjectInstance(selfInstance.Engine)
                    {
                        Extensible = true
                    }));
                }

                BlittableJsonReaderObject.PropertyDetails propDetails = new BlittableJsonReaderObject.PropertyDetails();
                selfInstance.Blittable.GetPropertyByIndex(propertyIndex, ref propDetails);
                var value = propDetails.Value;

                switch (propDetails.Token & BlittableJsonReaderBase.TypesMask)
                {
                case BlittableJsonToken.Null:
                    return(JsValue.Null);

                case BlittableJsonToken.Boolean:
                    return(new JsValue((bool)propDetails.Value));

                case BlittableJsonToken.Integer:
                    return(new JsValue(new ObjectWrapper(selfInstance.Engine, value)));

                case BlittableJsonToken.LazyNumber:
                    return(new JsValue(new ObjectWrapper(selfInstance.Engine, value)));

                case BlittableJsonToken.String:
                    return(new JsValue(new ObjectWrapper(selfInstance.Engine, value)));

                case BlittableJsonToken.CompressedString:
                    return(new JsValue(new ObjectWrapper(selfInstance.Engine, value)));

                default:
                    throw new InvalidOperationException("scalarToRawString(document, lambdaToField) lambda to field must return either raw numeric or raw string types");
                }
            }
Пример #9
0
        public JsValue EvaluateBinaryExpression(BinaryExpression expression)
        {
            JsValue left  = _engine.GetValue(EvaluateExpression(expression.Left));
            JsValue right = _engine.GetValue(EvaluateExpression(expression.Right));
            JsValue value;

            switch (expression.Operator)
            {
            case "+":
                var lprim = TypeConverter.ToPrimitive(left);
                var rprim = TypeConverter.ToPrimitive(right);
                if (lprim.IsString() || rprim.IsString())
                {
                    value = TypeConverter.ToString(lprim) + TypeConverter.ToString(rprim);
                }
                else
                {
                    value = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim);
                }
                break;

            case "-":
                value = TypeConverter.ToNumber(left) - TypeConverter.ToNumber(right);
                break;

            case "*":
                if (left == Undefined.Instance || right == Undefined.Instance)
                {
                    value = Undefined.Instance;
                }
                else
                {
                    value = TypeConverter.ToNumber(left) * TypeConverter.ToNumber(right);
                }
                break;

            case "/":
                value = Divide(left, right);
                break;

            case "%":
                if (left == Undefined.Instance || right == Undefined.Instance)
                {
                    value = Undefined.Instance;
                }
                else
                {
                    value = TypeConverter.ToNumber(left) % TypeConverter.ToNumber(right);
                }
                break;

            case "==":
                value = Equal(left, right);
                break;

            case "!=":
                value = !Equal(left, right);
                break;

            case ">":
                value = Compare(right, left, false);
                if (value == Undefined.Instance)
                {
                    value = false;
                }
                break;

            case ">=":
                value = Compare(left, right);
                if (value == Undefined.Instance || value.AsBoolean())
                {
                    value = false;
                }
                else
                {
                    value = true;
                }
                break;

            case "<":
                value = Compare(left, right);
                if (value == Undefined.Instance)
                {
                    value = false;
                }
                break;

            case "<=":
                value = Compare(right, left, false);
                if (value == Undefined.Instance || value.AsBoolean())
                {
                    value = false;
                }
                else
                {
                    value = true;
                }
                break;

            case "===":
                return(StrictlyEqual(left, right));

            case "!==":
                return(!StrictlyEqual(left, right));

            case "&":
                return(TypeConverter.ToInt32(left) & TypeConverter.ToInt32(right));

            case "|":
                return(TypeConverter.ToInt32(left) | TypeConverter.ToInt32(right));

            case "^":
                return(TypeConverter.ToInt32(left) ^ TypeConverter.ToInt32(right));

            case "<<":
                return(TypeConverter.ToInt32(left) << (int)(TypeConverter.ToUint32(right) & 0x1F));

            case ">>":
                return(TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F));

            case ">>>":
                return((uint)TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F));

            case "instanceof":
                var f = right.TryCast <FunctionInstance>();

                if (f == null)
                {
                    throw new JavaScriptException(_engine.TypeError, "instanceof can only be used with a function object");
                }

                value = f.HasInstance(left);
                break;

            case "in":
                if (!right.IsObject())
                {
                    throw new JavaScriptException(_engine.TypeError, "in can only be used with an object");
                }

                value = right.AsObject().HasProperty(TypeConverter.ToString(left));
                break;

            default:
                throw new NotImplementedException();
            }

            return(value);
        }
Пример #10
0
        private JsValue Sort(JsValue thisObj, JsValue[] arguments)
        {
            if (!thisObj.IsObject())
            {
                ExceptionHelper.ThrowTypeError(_engine, "Array.prorotype.sort can only be applied on objects");
            }

            var obj = ArrayOperations.For(thisObj.AsObject());

            var       compareArg = arguments.At(0);
            ICallable compareFn  = null;

            if (!compareArg.IsUndefined())
            {
                if (compareArg.IsNull() || !(compareArg is ICallable))
                {
                    ExceptionHelper.ThrowTypeError(_engine, "The comparison function must be either a function or undefined");
                }

                compareFn = (ICallable)compareArg;
            }

            var len = obj.GetLength();

            if (len <= 1)
            {
                return(obj.Target);
            }

            int Comparer(JsValue x, JsValue y)
            {
                if (ReferenceEquals(x, null))
                {
                    return(1);
                }

                if (ReferenceEquals(y, null))
                {
                    return(-1);
                }

                var xUndefined = x.IsUndefined();
                var yUndefined = y.IsUndefined();

                if (xUndefined && yUndefined)
                {
                    return(0);
                }

                if (xUndefined)
                {
                    return(1);
                }

                if (yUndefined)
                {
                    return(-1);
                }

                if (compareFn != null)
                {
                    var s = TypeConverter.ToNumber(compareFn.Call(Undefined, new[] { x, y }));
                    if (s < 0)
                    {
                        return(-1);
                    }

                    if (s > 0)
                    {
                        return(1);
                    }

                    return(0);
                }

                var xString = TypeConverter.ToString(x);
                var yString = TypeConverter.ToString(y);

                var r = CompareOrdinal(xString, yString);

                return(r);
            }

            var array = new JsValue[len];

            for (uint i = 0; i < (uint)array.Length; ++i)
            {
                var value = obj.TryGetValue(i, out var temp)
                    ? temp
                    : null;
                array[i] = value;
            }

            // don't eat inner exceptions
            try
            {
                System.Array.Sort(array, Comparer);
            }
            catch (InvalidOperationException e)
            {
                throw e.InnerException;
            }

            for (uint i = 0; i < (uint)array.Length; ++i)
            {
                if (!ReferenceEquals(array[i], null))
                {
                    obj.Set(i, array[i], updateLength: false, throwOnError: false);
                }
                else
                {
                    obj.DeletePropertyOrThrow(i);
                }
            }

            return(obj.Target);
        }
Пример #11
0
        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);
        }
Пример #12
0
        private LocalVariable GetLocalVariableJS(string key, JsValue value)
        {
            var result = new LocalVariable()
            {
                Name = key, TypeName = value.Type.ToString()
            };

            if (value.IsArray())
            {
                var trueValue = value.AsArray();
                if (trueValue.GetLength() > 0)
                {
                    var props = trueValue.GetOwnProperties();
                    foreach (var item in props)
                    {
                        var ch = GetLocalVariableJS(item.Key, item.Value.Value);
                        result.Children.Add(ch);
                    }
                }
                //result.Value=trueValue.
            }
            else if (value.IsBoolean())
            {
                var trueValue = value.AsBoolean();
                result.Value = trueValue.ToString();
            }
            else if (value.IsDate())
            {
                var trueValue = value.AsDate();
                result.Value = trueValue.ToDateTime().ToString("yyyy-MM-dd HH:mm:ss");
            }
            else if (value.IsNumber())
            {
                var trueValue = value.AsNumber();
                result.Value = trueValue.ToString();
            }
            else if (value.IsString())
            {
                var trueValue = value.AsString();
                result.Value = trueValue;
            }
            else if (value.IsObject())
            {
                var trueValue = value.AsObject();
                //判断对象是否原生JS
                if (trueValue.GetType().Name == "ObjectInstance")
                {
                    var props = trueValue.GetOwnProperties();
                    foreach (var item in props)
                    {
                        var ch = GetLocalVariableJS(item.Key, item.Value.Value);
                        result.Children.Add(ch);
                    }
                }
                else
                {
                    var csharpValue = value.ToObject();
                    if (csharpValue != null)
                    {
                        //只处理DapperRow
                        result = GetLocalVariableCSharp(key, csharpValue);
                        //csharpValue.
                    }
                }
            }
            return(result);
        }
Пример #13
0
        private RavenJToken ToRavenJToken(JsValue v, string propertyKey, bool recursiveCall)
        {
            if (v.IsBoolean())
            {
                return(new RavenJValue(v.AsBoolean()));
            }
            if (v.IsString())
            {
                const string RavenDataByteArrayToBase64 = "raven-data:byte[];base64,";
                var          valueAsObject = v.ToObject();
                var          value         = valueAsObject != null?valueAsObject.ToString() : null;

                if (value != null && value.StartsWith(RavenDataByteArrayToBase64))
                {
                    value = value.Remove(0, RavenDataByteArrayToBase64.Length);
                    var byteArray = Convert.FromBase64String(value);
                    return(new RavenJValue(byteArray));
                }
                return(new RavenJValue(value));
            }
            if (v.IsNumber())
            {
                var num = v.AsNumber();

                KeyValuePair <RavenJValue, JsValue> property;
                if (propertiesByValue.TryGetValue(propertyKey, out property))
                {
                    var originalValue = property.Key;
                    if (originalValue.Type == JTokenType.Float ||
                        originalValue.Type == JTokenType.Integer)
                    {
                        // If the current value is exactly as the original value, we can return the original value before we made the JS conversion,
                        // which will convert a Int64 to jsFloat.
                        var originalJsValue = property.Value;
                        if (originalJsValue.IsNumber() && Math.Abs(num - originalJsValue.AsNumber()) < double.Epsilon)
                        {
                            return(originalValue);
                        }

                        if (originalValue.Type == JTokenType.Integer)
                        {
                            return(new RavenJValue((long)num));
                        }
                        return(new RavenJValue(num));//float
                    }
                }

                // If we don't have the type, assume that if the number ending with ".0" it actually an integer.
                var integer = Math.Truncate(num);
                if (Math.Abs(num - integer) < double.Epsilon)
                {
                    return(new RavenJValue((long)integer));
                }
                return(new RavenJValue(num));
            }
            if (v.IsNull())
            {
                return(RavenJValue.Null);
            }
            if (v.IsUndefined())
            {
                return(RavenJValue.Null);
            }
            if (v.IsArray())
            {
                var jsArray = v.AsArray();
                var rja     = new RavenJArray();

                foreach (var property in jsArray.Properties)
                {
                    if (property.Key == "length")
                    {
                        continue;
                    }

                    var jsInstance = property.Value.Value;
                    if (!jsInstance.HasValue)
                    {
                        continue;
                    }

                    var ravenJToken = ToRavenJToken(jsInstance.Value, propertyKey + "[" + property.Key + "]", recursiveCall);
                    if (ravenJToken == null)
                    {
                        continue;
                    }

                    rja.Add(ravenJToken);
                }

                return(rja);
            }
            if (v.IsObject())
            {
                return(ToRavenJObject(v, propertyKey, recursiveCall));
            }
            if (v.IsRegExp())
            {
                return(null);
            }

            throw new NotSupportedException(v.Type.ToString());
        }
Пример #14
0
        public static Color?FromJsValue(JsValue obj)
        {
            if (obj == null || obj.IsNull() || obj.IsUndefined())
            {
                return(null);
            }

            var nativeObject = obj.ToObject();

            if (nativeObject is Color c)
            {
                return(c);
            }

            if (obj.IsString())
            {
                var s = obj.ToString();
                ColorUtility.TryParseHtmlString(s, out var color);
                return(color);
            }

            if (obj.IsNumber())
            {
                var num = (float)obj.AsNumber();
                return(new Color(num, num, num, 1));
            }

            if (obj.IsArray())
            {
                var len = obj.AsArray().Length;

                if (len == 0)
                {
                    return(Color.clear);
                }

                var v0 = obj.AsArray()[0];
                var v1 = obj.AsArray()[1];
                var v2 = obj.AsArray()[2];
                var v3 = obj.AsArray()[3];

                if (v0 != null && !v0.IsNumber() && !v0.IsNull() && !v0.IsUndefined())
                {
                    var start = FromJsValue(v0) ?? Color.clear;
                    var end   = FromJsValue(v2);
                    if (end.HasValue)
                    {
                        var t = v1.IsNumber() ? (float)v1.AsNumber() : 0;
                        return(Color.LerpUnclamped(start, end.Value, t));
                    }
                    else
                    {
                        var t = v1.IsNumber() ? (float)v1.AsNumber() : 1;
                        start.a = t;
                        return(start);
                    }
                }

                var r = v0.IsNumber() ? (float)v0.AsNumber() : 0;
                var g = v1.IsNumber() ? (float)v1.AsNumber() : 0;
                var b = v2.IsNumber() ? (float)v2.AsNumber() : 0;
                var a = v3.IsNumber() ? (float)v3.AsNumber() : 1;

                return(new Color(r, g, b, a));
            }

            if (obj.IsObject())
            {
                var ob = obj.AsObject();

                var v0 = ob.Get("r");
                var v1 = ob.Get("g");
                var v2 = ob.Get("b");
                var v3 = ob.Get("a");

                var r = v0.IsNumber() ? (float)v0.AsNumber() : 0;
                var g = v1.IsNumber() ? (float)v1.AsNumber() : 0;
                var b = v2.IsNumber() ? (float)v2.AsNumber() : 0;
                var a = v3.IsNumber() ? (float)v3.AsNumber() : 1;

                return(new Color(r, g, b, a));
            }

            return(null);
        }
Пример #15
0
        public static bool CanConvert(this JsValue jsValue, Type targetType)
        {
            if (jsValue.IsNull() || jsValue.IsUndefined())
            {
                return(targetType.IsClass);
            }

            if (jsValue.IsString() && (targetType == typeof(string) || targetType == typeof(bool)))
            {
                return(true);
            }

            if (jsValue.IsBoolean() && (targetType == typeof(bool) || targetType == typeof(bool?)))
            {
                return(true);
            }

            if (jsValue.IsNumber() && (targetType == typeof(int) ||
                                       targetType == typeof(ulong) ||
                                       targetType == typeof(double) ||
                                       targetType == typeof(short) ||
                                       targetType == typeof(short?) ||
                                       targetType == typeof(int?) ||
                                       targetType == typeof(double?) ||
                                       targetType == typeof(string) ||
                                       targetType == typeof(bool) ||
                                       targetType == typeof(bool?)))
            {
                return(true);
            }

            if (jsValue.IsObject())
            {
                var jsObj = jsValue.AsObject();

                if (jsObj is FunctionInstance && (typeof(Delegate)).IsAssignableFrom(targetType))
                {
                    return(true);
                }

                if (jsObj is ClrObject clrObjectInstance)
                {
                    if (clrObjectInstance.Target == null)
                    {
                        return(targetType.IsClass);
                    }

                    return(targetType.IsAssignableFrom(clrObjectInstance.Target.GetType()));
                }

                if (jsObj is ArrayInstance)
                {
                    return(targetType.IsArray);
                }

                if (jsObj is ObjectInstance)
                {
                    //if the target type is class that contains only public fields
                    //it can be deserialized from js object.

                    return(targetType.IsClass && targetType != typeof(string));
                }
            }

            return(false);
        }
Пример #16
0
        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);
        }
Пример #17
0
        public static Types GetPrimitiveType(JsValue value)
        {
            if (value.IsObject())
            {
                var primitive = value.TryCast<IPrimitiveInstance>();
                if (primitive != null)
                {
                    return primitive.Type;
                }

                return Types.Object;
            }

            return value.Type;
        }
Пример #18
0
        /// <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));
        }
Пример #19
0
        /// <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));
        }
Пример #20
0
        private JsValue AbstractWalkOperation(ObjectInstance thisObject, string prop)
        {
            JsValue value = thisObject.Get(prop);

            if (value.IsObject())
            {
                var valueAsObject = value.AsObject();
                if (valueAsObject.Class == "Array")
                {
                    var valAsArray = value.AsArray();
                    var i          = 0;
                    var arrLen     = valAsArray.GetLength();
                    while (i < arrLen)
                    {
                        var newValue = AbstractWalkOperation(valAsArray, TypeConverter.ToString(i));
                        if (newValue.IsUndefined())
                        {
                            valAsArray.Delete(TypeConverter.ToString(i), false);
                        }
                        else
                        {
                            valAsArray.DefineOwnProperty
                            (
                                TypeConverter.ToString(i),
                                new PropertyDescriptor
                                (
                                    value: newValue,
                                    flags: PropertyFlag.ConfigurableEnumerableWritable
                                ),
                                false
                            );
                        }
                        i = i + 1;
                    }
                }
                else
                {
                    var keys = valueAsObject.GetOwnProperties();
                    foreach (var p in keys)
                    {
                        var newElement = AbstractWalkOperation(valueAsObject, p.Key);
                        if (newElement.IsUndefined())
                        {
                            valueAsObject.Delete(p.Key, false);
                        }
                        else
                        {
                            valueAsObject.DefineOwnProperty(
                                p.Key,
                                new PropertyDescriptor
                                (
                                    value: newElement,
                                    flags: PropertyFlag.ConfigurableEnumerableWritable
                                ),
                                false
                                );
                        }
                    }
                }
            }
            return(_reviver.Invoke(thisObject, new JsValue[] { prop, value }));
        }
Пример #21
0
        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 callable && ReferenceEquals(replacer, Undefined.Instance))
            {
                return(Undefined.Instance);
            }

            if (replacer.IsObject())
            {
                if (replacer is ICallable)
                {
                    _replacerFunction = replacer;
                }
                else
                {
                    var replacerObj = replacer.AsObject();
                    if (replacerObj.Class == ObjectClass.Array)
                    {
                        _propertyList = new List <JsValue>();
                    }

                    foreach (var property in replacerObj.GetOwnProperties().Select(x => x.Value))
                    {
                        JsValue v    = _engine.GetValue(property, false);
                        string  item = null;
                        if (v.IsString())
                        {
                            item = v.ToString();
                        }
                        else if (v.IsNumber())
                        {
                            item = TypeConverter.ToString(v);
                        }
                        else if (v.IsObject())
                        {
                            var propertyObj = v.AsObject();
                            if (propertyObj.Class == ObjectClass.String || propertyObj.Class == ObjectClass.Number)
                            {
                                item = TypeConverter.ToString(v);
                            }
                        }

                        if (item != null && !_propertyList.Contains(item))
                        {
                            _propertyList.Add(item);
                        }
                    }
                }
            }

            if (space.IsObject())
            {
                var spaceObj = space.AsObject();
                if (spaceObj.Class == ObjectClass.Number)
                {
                    space = TypeConverter.ToNumber(spaceObj);
                }
                else if (spaceObj.Class == ObjectClass.String)
                {
                    space = TypeConverter.ToJsString(spaceObj);
                }
            }

            // defining the gap
            if (space.IsNumber())
            {
                var number = ((JsNumber)space)._value;
                if (number > 0)
                {
                    _gap = new string(' ', (int)System.Math.Min(10, number));
                }
                else
                {
                    _gap = string.Empty;
                }
            }
            else if (space.IsString())
            {
                var stringSpace = space.ToString();
                _gap = stringSpace.Length <= 10 ? stringSpace : stringSpace.Substring(0, 10);
            }
            else
            {
                _gap = string.Empty;
            }

            var wrapper = _engine.Object.Construct(Arguments.Empty);

            wrapper.DefineOwnProperty(JsString.Empty, new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable));

            return(Str(JsString.Empty, wrapper));
        }
Пример #22
0
        public object ConvertToObject(JsValue jsValue, Type targetType)
        {
            if (jsValue == _getEngine().Global)
            {
                return(_global);
            }

            if (jsValue.IsUndefined())
            {
                return(null);
            }

            if (jsValue.IsObject())
            {
                var obj = jsValue.AsObject();

                if (targetType == typeof(string))
                {
                    return(obj.ToString());
                }

                switch (obj)
                {
                case ClrObject clr:
                    return(clr.Target);

                case ObjectInstance objInst:
                    return(GetCreator(targetType)(objInst));
                }

                return(jsValue);
            }

            if (jsValue.IsBoolean())
            {
                var boolVal = jsValue.AsBoolean();
                if (targetType == typeof(string))
                {
                    return(boolVal ? "true" : "false");
                }

                return(boolVal);
            }


            if (jsValue.IsString())
            {
                return(jsValue.AsString());
            }

            if (jsValue.IsNumber())
            {
                var dbl = jsValue.AsNumber();

                if (targetType == typeof(sbyte))
                {
                    return((sbyte)dbl);
                }
                if (targetType == typeof(byte))
                {
                    return((byte)dbl);
                }
                if (targetType == typeof(int))
                {
                    return((int)dbl);
                }
                if (targetType == typeof(uint))
                {
                    return((uint)dbl);
                }
                if (targetType == typeof(short))
                {
                    return((short)dbl);
                }
                if (targetType == typeof(ushort))
                {
                    return((ushort)dbl);
                }
                if (targetType == typeof(long))
                {
                    return((long)dbl);
                }
                if (targetType == typeof(ulong))
                {
                    return((ulong)dbl);
                }
                if (targetType == typeof(float))
                {
                    return((float)dbl);
                }
                if (targetType == typeof(string))
                {
                    return(dbl.ToString(CultureInfo.InvariantCulture));
                }

                return(dbl);
            }


            return(null);
        }
Пример #23
0
        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));
        }
Пример #24
0
        /// <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 = StringPrototype.TrimEx(o.AsString());

                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)));
        }
Пример #25
0
        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);
        }
Пример #26
0
        private static object GetValue(JsValue jsValue)
        {
            if (jsValue.IsNull())
            {
                return(null);
            }
            if (jsValue.IsString())
            {
                return(jsValue.AsString());
            }
            if (jsValue.IsBoolean())
            {
                return(jsValue.AsBoolean());
            }
            if (jsValue.IsNumber())
            {
                return(jsValue.AsNumber());
            }
            if (jsValue.IsDate())
            {
                return(jsValue.AsDate());
            }
            if (jsValue is ObjectWrapper ow)
            {
                var target = ow.Target;
                switch (target)
                {
                case LazyStringValue lsv:
                    return(lsv);

                case LazyCompressedStringValue lcsv:
                    return(lcsv);

                case LazyNumberValue lnv:
                    return(lnv);    //should be already blittable supported type.
                }
                ThrowInvalidObject(jsValue);
            }
            else if (jsValue.IsArray())
            {
                var arr   = jsValue.AsArray();
                var array = new object[arr.GetLength()];
                var i     = 0;
                foreach ((var key, var val) in arr.GetOwnProperties())
                {
                    if (key == "length")
                    {
                        continue;
                    }

                    array[i++] = GetValue(val.Value);
                }

                return(array);
            }
            else if (jsValue.IsObject())
            {
                return(jsValue.AsObject());
            }
            if (jsValue.IsUndefined())
            {
                return(null);
            }

            ThrowInvalidObject(jsValue);
            return(null);
        }
Пример #27
0
 public bool IsPropertyReference()
 {
     // http://www.ecma-international.org/ecma-262/5.1/#sec-8.7
     return((_baseValue.IsObject() && !_baseValue.Is <EnvironmentRecord>()) || HasPrimitiveBase());
 }
Пример #28
0
        public static JToken Map(JsValue value)
        {
            if (value == null || value.IsNull())
            {
                return(JValue.CreateNull());
            }

            if (value.IsUndefined())
            {
                return(JValue.CreateUndefined());
            }

            if (value.IsString())
            {
                return(new JValue(value.AsString()));
            }

            if (value.IsBoolean())
            {
                return(new JValue(value.AsBoolean()));
            }

            if (value.IsNumber())
            {
                return(new JValue(value.AsNumber()));
            }

            if (value.IsDate())
            {
                return(new JValue(value.AsDate().ToDateTime()));
            }

            if (value.IsRegExp())
            {
                return(JValue.CreateString(value.AsRegExp().Value?.ToString()));
            }

            if (value.IsArray())
            {
                var arr = value.AsArray();

                var target = new JArray();

                for (var i = 0; i < arr.GetLength(); i++)
                {
                    target.Add(Map(arr.Get(i.ToString())));
                }

                return(target);
            }

            if (value.IsObject())
            {
                var obj = value.AsObject();

                var target = new JObject();

                foreach (var kvp in obj.GetOwnProperties())
                {
                    target[kvp.Key] = Map(kvp.Value.Value);
                }

                return(target);
            }

            throw new ArgumentException("Invalid json type.", nameof(value));
        }
Пример #29
0
 internal static bool IsFunction(JsValue jsValue)
 {
     return(jsValue.IsObject() && jsValue.AsObject() is Jint.Native.Function.FunctionInstance);
 }
Пример #30
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.1
        /// </summary>
        /// <param name="thisArg"></param>
        /// <param name="arguments"></param>
        /// <returns></returns>
        public override JsValue Call(JsValue thisArg, JsValue[] arguments)
        {
            var scope = Engine.PoolStrictMode.Get();

            scope.Setup(Strict, true);
            {
                // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
                JsValue thisBinding;
                if (StrictModeScope.IsStrictModeCode)
                {
                    thisBinding = thisArg;
                }
                else if (thisArg == Undefined.Instance || thisArg == Null.Instance)
                {
                    thisBinding = Engine.Global;
                }
                else if (!thisArg.IsObject())
                {
                    thisBinding = TypeConverter.ToObject(Engine, thisArg);
                }
                else
                {
                    thisBinding = thisArg;
                }

                var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Engine, Scope);

                Engine.EnterExecutionContext(localEnv, localEnv, thisBinding);

                try
                {
                    Engine.DeclarationBindingInstantiation(
                        DeclarationBindingType.FunctionCode,
                        _functionDeclaration.FunctionDeclarations,
                        _functionDeclaration.VariableDeclarations,
                        this,
                        arguments);

                    var result = Engine.ExecuteStatement(_functionDeclaration.Body);

                    if (result.Type == Completion.Throw)
                    {
                        JavaScriptException ex = new JavaScriptException(result.GetValueOrDefault())
                                                 .SetCallstack(Engine, result.Location);
                        throw ex;
                    }

                    if (result.Type == Completion.Return)
                    {
                        scope.Teardown();
                        Engine.PoolStrictMode.Put(scope);

                        return(result.GetValueOrDefault());
                    }
                }
                finally
                {
                    Engine.LeaveExecutionContext();
                }

                scope.Teardown();
                Engine.PoolStrictMode.Put(scope);

                return(Undefined.Instance);
            }
        }
Пример #31
0
        public JsValue EvaluateBinaryExpression(BinaryExpression expression)
        {
            var     leftExpression = EvaluateExpression(expression.Left);
            JsValue left           = _engine.GetValue(leftExpression);

            var     rightExpression = EvaluateExpression(expression.Right);
            JsValue right           = _engine.GetValue(rightExpression);

            JsValue value;

            switch (expression.Operator)
            {
            case BinaryOperator.Plus:
                var lprim = TypeConverter.ToPrimitive(left);
                var rprim = TypeConverter.ToPrimitive(right);
                if (lprim.IsString() || rprim.IsString())
                {
                    value = TypeConverter.ToString(lprim) + TypeConverter.ToString(rprim);
                }
                else
                {
                    value = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim);
                }
                break;

            case BinaryOperator.Minus:
                value = TypeConverter.ToNumber(left) - TypeConverter.ToNumber(right);
                break;

            case BinaryOperator.Times:
                if (left == Undefined.Instance || right == Undefined.Instance)
                {
                    value = Undefined.Instance;
                }
                else
                {
                    value = TypeConverter.ToNumber(left) * TypeConverter.ToNumber(right);
                }
                break;

            case BinaryOperator.Divide:
                value = Divide(left, right);
                break;

            case BinaryOperator.Modulo:
                if (left == Undefined.Instance || right == Undefined.Instance)
                {
                    value = Undefined.Instance;
                }
                else
                {
                    value = TypeConverter.ToNumber(left) % TypeConverter.ToNumber(right);
                }
                break;

            case BinaryOperator.Equal:
                value = Equal(left, right);
                break;

            case BinaryOperator.NotEqual:
                value = !Equal(left, right);
                break;

            case BinaryOperator.Greater:
                value = Compare(right, left, false);
                if (value == Undefined.Instance)
                {
                    value = false;
                }
                break;

            case BinaryOperator.GreaterOrEqual:
                value = Compare(left, right);
                if (value == Undefined.Instance || value.AsBoolean())
                {
                    value = false;
                }
                else
                {
                    value = true;
                }
                break;

            case BinaryOperator.Less:
                value = Compare(left, right);
                if (value == Undefined.Instance)
                {
                    value = false;
                }
                break;

            case BinaryOperator.LessOrEqual:
                value = Compare(right, left, false);
                if (value == Undefined.Instance || value.AsBoolean())
                {
                    value = false;
                }
                else
                {
                    value = true;
                }
                break;

            case BinaryOperator.StrictlyEqual:
                return(StrictlyEqual(left, right));

            case BinaryOperator.StricltyNotEqual:
                return(!StrictlyEqual(left, right));

            case BinaryOperator.BitwiseAnd:
                return(TypeConverter.ToInt32(left) & TypeConverter.ToInt32(right));

            case BinaryOperator.BitwiseOr:
                return(TypeConverter.ToInt32(left) | TypeConverter.ToInt32(right));

            case BinaryOperator.BitwiseXOr:
                return(TypeConverter.ToInt32(left) ^ TypeConverter.ToInt32(right));

            case BinaryOperator.LeftShift:
                return(TypeConverter.ToInt32(left) << (int)(TypeConverter.ToUint32(right) & 0x1F));

            case BinaryOperator.RightShift:
                return(TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F));

            case BinaryOperator.UnsignedRightShift:
                return((uint)TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F));

            case BinaryOperator.InstanceOf:
                var f = right.TryCast <FunctionInstance>();

                if (f == null)
                {
                    throw new JavaScriptException(_engine.TypeError, "instanceof can only be used with a function object");
                }

                value = f.HasInstance(left);
                break;

            case BinaryOperator.In:
                if (!right.IsObject())
                {
                    throw new JavaScriptException(_engine.TypeError, "in can only be used with an object");
                }

                value = right.AsObject().HasProperty(TypeConverter.ToString(left));
                break;

            default:
                throw new NotImplementedException();
            }

            return(value);
        }
 static bool IsObject(JsValue value)
 {
     return(value.IsObject() && value.IsArray() == false);
 }
Пример #33
0
            private static JsValue ScalarToRawString(JsValue self2, JsValue[] args)
            {
                if (args.Length != 2)
                {
                    throw new InvalidOperationException("scalarToRawString(document, lambdaToField) may be called on with two parameters only");
                }


                JsValue firstParam = args[0];

                if (firstParam.IsObject() && args[0].AsObject() is BlittableObjectInstance selfInstance)
                {
                    JsValue secondParam = args[1];
                    if (secondParam.IsObject() && secondParam.AsObject() is ScriptFunctionInstance lambda)
                    {
                        var functionAst = lambda.GetFunctionAst();
                        var propName    = functionAst.TryGetFieldFromSimpleLambdaExpression();

                        if (selfInstance.OwnValues.TryGetValue(propName, out var existingValue))
                        {
                            if (existingValue.Changed)
                            {
                                return(existingValue.Value);
                            }
                        }

                        var propertyIndex = selfInstance.Blittable.GetPropertyIndex(propName);

                        if (propertyIndex == -1)
                        {
                            return(new JsValue(new ObjectInstance(selfInstance.Engine)
                            {
                                Extensible = true
                            }));
                        }

                        BlittableJsonReaderObject.PropertyDetails propDetails = new BlittableJsonReaderObject.PropertyDetails();
                        selfInstance.Blittable.GetPropertyByIndex(propertyIndex, ref propDetails);
                        var value = propDetails.Value;

                        switch (propDetails.Token & BlittableJsonReaderBase.TypesMask)
                        {
                        case BlittableJsonToken.Null:
                            return(JsValue.Null);

                        case BlittableJsonToken.Boolean:
                            return(new JsValue((bool)propDetails.Value));

                        case BlittableJsonToken.Integer:
                            return(new JsValue(new ObjectWrapper(selfInstance.Engine, value)));

                        case BlittableJsonToken.LazyNumber:
                            return(new JsValue(new ObjectWrapper(selfInstance.Engine, value)));

                        case BlittableJsonToken.String:
                            return(new JsValue(new ObjectWrapper(selfInstance.Engine, value)));

                        case BlittableJsonToken.CompressedString:
                            return(new JsValue(new ObjectWrapper(selfInstance.Engine, value)));

                        default:
                            throw new InvalidOperationException("scalarToRawString(document, lambdaToField) lambda to field must return either raw numeric or raw string types");
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("scalarToRawString(document, lambdaToField) must be called with a second lambda argument");
                    }
                }
                else
                {
                    throw new InvalidOperationException("scalarToRawString(document, lambdaToField) may be called with a document first parameter only");
                }
            }
Пример #34
0
        public static IJsonValue Map(JsValue value)
        {
            if (value == null || value.IsNull() || value.IsUndefined())
            {
                return(JsonValue.Null);
            }

            if (value.IsString())
            {
                return(JsonValue.Create(value.AsString()));
            }

            if (value.IsBoolean())
            {
                return(JsonValue.Create(value.AsBoolean()));
            }

            if (value.IsNumber())
            {
                return(JsonValue.Create(value.AsNumber()));
            }

            if (value.IsDate())
            {
                return(JsonValue.Create(value.AsDate().ToString()));
            }

            if (value.IsRegExp())
            {
                return(JsonValue.Create(value.AsRegExp().Value?.ToString()));
            }

            if (value.IsArray())
            {
                var arr = value.AsArray();

                var result = JsonValue.Array();

                for (var i = 0; i < arr.GetLength(); i++)
                {
                    result.Add(Map(arr.Get(i.ToString())));
                }

                return(result);
            }

            if (value.IsObject())
            {
                var obj = value.AsObject();

                var result = JsonValue.Object();

                foreach (var kvp in obj.GetOwnProperties())
                {
                    result[kvp.Key] = Map(kvp.Value.Value);
                }

                return(result);
            }

            throw new ArgumentException("Invalid json type.", nameof(value));
        }
Пример #35
0
        private object ToBlittableValue(JsValue v, string propertyKey, bool recursiveCall)
        {
            if (v.IsBoolean())
            {
                return(v.AsBoolean());
            }

            if (v.IsString())
            {
                const string RavenDataByteArrayToBase64 = "raven-data:byte[];base64,";
                var          valueAsObject = v.ToObject();
                var          value         = valueAsObject?.ToString();
                if (value != null && value.StartsWith(RavenDataByteArrayToBase64))
                {
                    value = value.Remove(0, RavenDataByteArrayToBase64.Length);
                    var byteArray = Convert.FromBase64String(value);
                    return(Encoding.UTF8.GetString(byteArray));
                }
                return(value);
            }

            if (v.IsNumber())
            {
                var num = v.AsNumber();

                KeyValuePair <object, JsValue> property;
                if (_propertiesByValue.TryGetValue(propertyKey, out property))
                {
                    var originalValue = property.Key;
                    if (originalValue is float || originalValue is int)
                    {
                        // If the current value is exactly as the original value, we can return the original value before we made the JS conversion,
                        // which will convert a Int64 to jsFloat.
                        var jsValue = property.Value;
                        if (jsValue.IsNumber() && Math.Abs(num - jsValue.AsNumber()) < double.Epsilon)
                        {
                            return(originalValue);
                        }

                        //We might have change the type of num from Integer to long in the script by design
                        //Making sure the number isn't a real float before returning it as integer
                        if (originalValue is int && (Math.Abs(num - Math.Floor(num)) <= double.Epsilon || Math.Abs(num - Math.Ceiling(num)) <= double.Epsilon))
                        {
                            return((long)num);
                        }
                        return(num); //float
                    }
                }

                // If we don't have the type, assume that if the number ending with ".0" it actually an integer.
                var integer = Math.Truncate(num);
                if (Math.Abs(num - integer) < double.Epsilon)
                {
                    return((long)integer);
                }
                return(num);
            }
            if (v.IsNull() || v.IsUndefined())
            {
                return(null);
            }
            if (v.IsArray())
            {
                var jsArray = v.AsArray();
                var array   = new DynamicJsonArray();

                foreach (var property in jsArray.GetOwnProperties())
                {
                    if (InheritedProperties.Contains(property.Key))
                    {
                        continue;
                    }

                    var jsInstance = property.Value.Value;
                    if (!jsInstance.HasValue)
                    {
                        continue;
                    }

                    var ravenJToken = ToBlittableValue(jsInstance.Value, propertyKey + "[" + property.Key + "]", recursiveCall);
                    if (ravenJToken == null)
                    {
                        continue;
                    }

                    array.Add(ravenJToken);
                }

                return(array);
            }
            if (v.IsDate())
            {
                return(v.AsDate().ToDateTime());
            }
            if (v.IsObject())
            {
                return(ToBlittable(v.AsObject(), propertyKey, recursiveCall));
            }
            if (v.IsRegExp())
            {
                return(null);
            }

            throw new NotSupportedException(v.Type.ToString());
        }
Пример #36
0
 /// <summary>
 /// Checks if object
 /// </summary>
 /// <param name="value">Value</param>
 /// <returns>True if object</returns>
 public static bool IsObject(JsValue value)
 {
     return(value.IsObject());
 }
Пример #37
0
        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;
        }
Пример #38
0
        public static JsValue Show(JavaScriptUi ui, string title, JsValue fields, JsValue validate)
        {
            if (ui == null)
            {
                throw new ArgumentNullException(nameof(ui));
            }

            using (var form = new UiForm())
            {
                if (String.IsNullOrEmpty(title))
                {
                    form.Text = ui.Owner.Text;
                }
                else
                {
                    form.Text = title;
                }

                form.Icon = ui.Owner.Icon;

                if (!fields.IsArray())
                {
                    throw new JavaScriptException("fields must be an array");
                }

                var controls = new List <Field>();

                fields.AsArray().ForEach((index, value) =>
                {
                    var container = form._container;

                    while (container.RowStyles.Count <= index)
                    {
                        container.RowCount++;
                        container.RowStyles.Add(new RowStyle(SizeType.AutoSize));
                    }

                    var field          = value.AsObject();
                    string name        = field.Get("name").ConvertToString();
                    string label       = field.Get("label").ConvertToString();
                    var type           = ParseType(field.Get("type").ConvertToString());
                    ArrayInstance list = null;
                    if (field.HasOwnProperty("list"))
                    {
                        list = field.Get("list").AsArray();
                    }

                    Field control;
                    switch (type)
                    {
                    case FieldType.Text:
                        control = new TextField(name, label);
                        break;

                    case FieldType.CheckBox:
                        control = new CheckBoxField(name, label);
                        break;

                    case FieldType.Numeric:
                        control = new NumericField(name, label);
                        break;

                    case FieldType.Date:
                        control = new DateField(name, label);
                        break;

                    case FieldType.DateTime:
                        control = new DateTimeField(name, label);
                        break;

                    case FieldType.ComboBox:
                        control = new ComboBoxField(name, label, list);
                        break;

                    default:
                        throw new ArgumentOutOfRangeException();
                    }

                    controls.Add(control);

                    if (field.HasOwnProperty("value"))
                    {
                        control.SetValue(field.Get("value"));
                    }

                    if (control.ShowLabel)
                    {
                        var labelControl = new Label
                        {
                            AutoSize  = true,
                            Text      = label,
                            Dock      = DockStyle.Fill,
                            TextAlign = ContentAlignment.MiddleLeft
                        };

                        container.SetRow(labelControl, index);
                        container.Controls.Add(labelControl);
                    }

                    control.Control.Dock     = DockStyle.Fill;
                    control.Control.AutoSize = true;
                    container.SetRow(control.Control, index);
                    container.SetColumn(control.Control, 1);
                    container.Controls.Add(control.Control);
                });

                form._acceptButton.Click += (s, e) =>
                {
                    try
                    {
                        if (validate.IsObject())
                        {
                            var values = BuildValues(ui.Engine, controls);
                            var result = validate.Invoke(values);
                            if (!result.ConvertToBoolean().GetValueOrDefault())
                            {
                                return;
                            }
                        }
                        form.DialogResult = DialogResult.OK;
                    }
                    catch (JavaScriptException exception)
                    {
                        JintDebugger.ExceptionForm.Show(form, exception);
                    }
                    catch (Exception exception)
                    {
                        MessageBox.Show(
                            form,
                            new StringBuilder()
                            .AppendLine("An exception occurred while executing the script:")
                            .AppendLine()
                            .Append(exception.Message).Append(" (").Append(exception.GetType().FullName).AppendLine(")")
                            .AppendLine()
                            .AppendLine(exception.StackTrace)
                            .ToString(),
                            "Error",
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error
                            );
                    }
                };

                var owner = ui.Owner;

                using (ui.PushOwner(form))
                {
                    if (form.ShowDialog(owner) == DialogResult.OK)
                    {
                        return(BuildValues(ui.Engine, controls));
                    }
                }
            }

            return(JsValue.Null);
        }