示例#1
0
 /// <summary>
 /// Инициировать вызов функции (управляемой/неуправляемой)
 /// </summary>
 /// <param name="function">Функция</param>
 /// <param name="context">Контекст</param>
 /// <param name="args">Параметры</param>
 /// <param name="copyResult">Копировать результат работы функции в стек вычислений вызывающей функции</param>
 /// <param name="onCompleteCallback">Вызывается по завершении работы функции</param>
 internal void CallFunction(
     JSFunction function,
     JSObject context,
     JSValue[] args,
     bool copyResult,
     Action onCompleteCallback = null)
 {
     if (function.IsNative)
     {
         var result = function.Invoke(this, context, CurrentFrame.LocalScope, args);
         if (copyResult)
         {
             CurrentFrame.Push(result);
         }
     }
     else
     {
         var managedFunction = (JSManagedFunction)function;
         CurrentFrame = new CallStackFrame(
             CurrentFrame,
             VM,
             managedFunction,
             context,
             new LocalVariableScope(managedFunction.OuterScope),
             args,
             copyResult,
             onCompleteCallback);
     }
 }
示例#2
0
 internal ExecutionThread(VirtualMachine vm, CompiledFunction globalFunction, JSValue[] globalArguments)
 {
     Contract.Requires(vm != null);
     Contract.Requires(globalFunction != null);
     VM             = vm;
     GlobalScope    = new GlobalVariableScope(vm.GlobalObject);
     GlobalFunction = new JSManagedFunction(VM, GlobalScope, globalFunction, VM.Function);
     CurrentFrame   = new CallStackFrame(
         null,
         VM,
         GlobalFunction,
         vm.GlobalObject,
         GlobalScope,
         globalArguments ?? JSFunction.EmptyArgumentList);
 }
示例#3
0
 private void NewObject(JSFunction constructor, JSValue[] args)
 {
     if (constructor.IsNative)
     {
         CurrentFrame.Push(constructor.Construct(this, CurrentFrame.LocalScope, args));
     }
     else
     {
         var managedConstructor = (JSManagedFunction)constructor;
         var newObject          = new JSObject(VM, managedConstructor.GetPrototype());
         CurrentFrame = new CallStackFrame(
             CurrentFrame,
             VM,
             managedConstructor,
             newObject,
             new LocalVariableScope(managedConstructor.OuterScope),
             args,
             true);
         CurrentFrame.Push(newObject);
     }
 }
示例#4
0
        internal CallStackFrame(
            CallStackFrame caller,
            VirtualMachine vm,
            JSManagedFunction function,
            JSObject context,
            VariableScope localScope,
            JSValue[] parameterValues,
            bool copyResult           = false,
            Action onCompleteCallback = null)
        {
            Contract.Requires(vm != null);
            Contract.Requires(function != null);
            Contract.Requires(context != null);
            Contract.Requires(localScope != null);
            Contract.Requires(parameterValues != null);

            Caller     = caller;
            CopyResult = copyResult;
            Function   = function;
            Context    = context;
            LocalScope = localScope;

            _evalStack = new Stack <JSValue>(4);

            CodeReader = new ByteCodeReader(Function.CompiledFunction.CompiledCode);

            OnCompleteCallback = onCompleteCallback;

            // Создать привязки для параметров
            var parameterNames = function.CompiledFunction.ParameterNames;
            var n = Math.Min(parameterNames.Length, parameterValues.Length);

            for (var i = 0; i < n; i++)
            {
                LocalScope.DeclareVariable(parameterNames[i], parameterValues[i]);
            }
            for (var i = n; i < parameterNames.Length; i++)
            {
                LocalScope.DeclareVariable(parameterNames[i], JSValue.Undefined);
            }

            // Создать привязку для arguments
            LocalScope.DeclareVariable("arguments", vm.NewArguments(parameterValues));

            // Создать привязки для объявленных функций
            for (var i = 0; i < Function.CompiledFunction.DeclaredFunctionCount; i++)
            {
                var declaredFunction = Function.CompiledFunction.NestedFunctions[i];
                if (!LocalScope.ContainsVariable(declaredFunction.Name))
                {
                    LocalScope.DeclareVariable(
                        declaredFunction.Name, vm.NewFunction(LocalScope, declaredFunction));
                }
            }

            // Создать привязки для объявленных переменных
            foreach (var variableName in Function.CompiledFunction.DeclaredVariables)
            {
                LocalScope.DeclareVariableIfNotExists(variableName, JSValue.Undefined);
            }
        }
示例#5
0
        private void ExecuteStep(CallStackFrame currentFrame)
        {
            try {
                switch (currentFrame.CodeReader.ReadOpCode())
                {
                case OpCode.Nop:
                    break;

                case OpCode.Break:
//						currentFrame.Dump();
                    break;

                    #region Загрузка значений

                case OpCode.LdUndefined:
                    currentFrame.Push(JSValue.Undefined);
                    break;

                case OpCode.LdNull:
                    currentFrame.Push(JSValue.Null);
                    break;

                case OpCode.LdBoolean:
                    currentFrame.Push(currentFrame.CodeReader.ReadBoolean());
                    break;

                case OpCode.LdInteger:
                    currentFrame.Push(currentFrame.CodeReader.ReadInteger());
                    break;

                case OpCode.LdFloat:
                    currentFrame.Push(currentFrame.CodeReader.ReadFloat());
                    break;

                case OpCode.LdString:
                    currentFrame.Push(currentFrame.CodeReader.ReadString());
                    break;

                case OpCode.LdThis:
                    currentFrame.Push(CurrentFrame.Context);
                    break;

                    #endregion

                    #region Локальные переменные и функции

                case OpCode.LdLocalFunc:
                    currentFrame.Push(currentFrame.GetFunction(VM, currentFrame.CodeReader.ReadInteger()));
                    break;

                case OpCode.LdLocal:
                    currentFrame.Push(currentFrame.LocalScope.GetVariable(currentFrame.CodeReader.ReadString()));
                    break;

                case OpCode.StLocal:
                    currentFrame.LocalScope.SetVariable(currentFrame.CodeReader.ReadString(), currentFrame.Pop());
                    break;

                    #endregion

                    #region Свойства объектов

                case OpCode.IsMember: {
                    var obj    = currentFrame.Pop().ToObject(VM);
                    var member = currentFrame.Pop();
                    currentFrame.Push(obj.ContainsMember(member));
                    break;
                }

                case OpCode.MakeRef: {
                    var member = currentFrame.Pop();
                    var obj    = currentFrame.Pop().ToObject(VM);
                    currentFrame.Push(new JSReference(obj, member));
                    break;
                }

                case OpCode.LdMember: {
                    var member = currentFrame.Pop();
                    var obj    = currentFrame.Pop().ToObject(VM);
                    currentFrame.Push(obj.GetMember(member));
                    break;
                }

                case OpCode.StMember: {
                    var value  = currentFrame.Pop();
                    var member = currentFrame.Pop();
                    var obj    = currentFrame.Pop().RequireObject();
                    obj.SetMember(member, value);
                    break;
                }

                case OpCode.StMemberDup: {
                    var value  = currentFrame.Pop();
                    var member = currentFrame.Pop();
                    var obj    = currentFrame.Pop().RequireObject();
                    obj.SetMember(member, value);
                    currentFrame.Push(value);
                    break;
                }

                case OpCode.LdMemberByRef: {
                    var reference = currentFrame.Pop().RequireReference();
                    currentFrame.Push(reference.Value);
                    break;
                }

                case OpCode.StMemberByRef: {
                    var value     = currentFrame.Pop();
                    var reference = currentFrame.Pop().RequireReference();
                    reference.Value = value;
                    break;
                }

                case OpCode.StMemberByRefDup: {
                    var value     = currentFrame.Pop();
                    var reference = currentFrame.Pop().RequireReference();
                    reference.Value = value;
                    currentFrame.Push(value);
                    break;
                }

                case OpCode.DelMember: {
                    var member = currentFrame.Pop();
                    var obj    = currentFrame.Pop().RequireObject();
                    currentFrame.Push(obj.DeleteMember(member));
                    break;
                }

                    #endregion

                    #region Управляющие

                case OpCode.Dup:
                    currentFrame.Push(currentFrame.Peek());
                    break;

                case OpCode.Dup2: {
                    var top  = currentFrame.Pop();
                    var top1 = currentFrame.Peek();
                    currentFrame.Push(top);
                    currentFrame.Push(top1);
                    currentFrame.Push(top);
                    break;
                }

                case OpCode.Pop:
                    currentFrame.Pop();
                    break;

                case OpCode.Pop2:
                    currentFrame.Pop();
                    currentFrame.Pop();
                    break;

                case OpCode.Swap: {
                    var top  = currentFrame.Pop();
                    var top1 = currentFrame.Pop();
                    currentFrame.Push(top);
                    currentFrame.Push(top1);
                    break;
                }

                case OpCode.SwapDup: {
                    var top  = currentFrame.Pop();
                    var top1 = currentFrame.Pop();
                    currentFrame.Push(top);
                    currentFrame.Push(top1);
                    currentFrame.Push(top);
                    break;
                }

                case OpCode.Goto:
                    currentFrame.CodeReader.Seek(currentFrame.CodeReader.ReadInteger());
                    break;

                case OpCode.GotoIfTrue: {
                    var offset = currentFrame.CodeReader.ReadInteger();
                    if (currentFrame.Pop().CastToBoolean())
                    {
                        currentFrame.CodeReader.Seek(offset);
                    }
                    break;
                }

                case OpCode.GotoIfFalse: {
                    var offset = currentFrame.CodeReader.ReadInteger();
                    if (!currentFrame.Pop().CastToBoolean())
                    {
                        currentFrame.CodeReader.Seek(offset);
                    }
                    break;
                }

                case OpCode.Switch:
                    Switch(currentFrame.CodeReader.ReadInteger(), currentFrame.Pop());
                    break;

                case OpCode.BeginScope:
                    currentFrame.BeginScope();
                    break;

                case OpCode.EndScope:
                    currentFrame.EndScope();
                    break;

                case OpCode.EnterTry:
                    currentFrame.EnterTry();
                    break;

                case OpCode.LeaveTry:
                    currentFrame.LeaveTry();
                    break;

                case OpCode.EnterCatch:
                    EnterCatch();
                    break;

                case OpCode.LeaveCatch:
                    LeaveCatch();
                    break;

                case OpCode.Throw:
                    Throw(currentFrame.Pop());
                    break;

                case OpCode.Rethrow:
                    Rethrow();
                    break;

                    #endregion

                    #region Вызовы функций

                case OpCode.NewObj: {
                    var arguments   = currentFrame.PopArguments();
                    var constructor = currentFrame.Pop().RequireFunction();
                    NewObject(constructor, arguments);
                    break;
                }

                case OpCode.MakeEmptyObject:
                    currentFrame.Push(VM.NewObject());
                    break;

                case OpCode.MakeObject:
                    MakeObject(currentFrame.Pop().RequireInteger());
                    break;

                case OpCode.MakeEmptyArray:
                    currentFrame.Push(VM.NewArray(new List <JSValue>()));
                    break;

                case OpCode.MakeArray:
                    MakeArray(currentFrame.Pop().RequireInteger());
                    break;

                case OpCode.Call: {
                    var arguments = currentFrame.PopArguments();
                    var function  = currentFrame.Pop().RequireFunction();
                    CallFunction(function, VM.GlobalObject, arguments, currentFrame.CodeReader.ReadBoolean());
                    break;
                }

                case OpCode.CallMember: {
                    var arguments = currentFrame.PopArguments();
                    var function  = currentFrame.Pop().RequireFunction();
                    var context   = currentFrame.Pop().ToObject(VM);
                    CallFunction(function, context, arguments, currentFrame.CodeReader.ReadBoolean());
                    break;
                }

                case OpCode.Return:
                    if (currentFrame.CopyResult)
                    {
                        Contract.Assume(currentFrame.Caller != null);
                        CurrentFrame.Caller.Push(currentFrame.Pop());
                    }
                    CurrentFrame = currentFrame.Caller;
                    currentFrame.OnCompleteCallback?.Invoke();
                    break;

                    #endregion

                    #region Перечислители

                case OpCode.GetEnumerator:
                    currentFrame.Push(currentFrame.Pop().GetJSEnumerator());
                    break;

                case OpCode.MoveNext: {
                    var enumerator   = currentFrame.Peek().RequireEnumerator();
                    var hasMoreValue = enumerator.MoveNext();
                    currentFrame.LocalScope.SetVariable(
                        currentFrame.CodeReader.ReadString(),
                        hasMoreValue ? enumerator.Current : JSValue.Undefined);
                    currentFrame.Push(hasMoreValue);
                    break;
                }

                    #endregion

                    #region Преобразования

                case OpCode.CastToPrimitive: {
                    var top = currentFrame.Peek();
                    if (top.Type == JSValueType.Object)
                    {
                        currentFrame.Pop();
                        top.CastToPrimitiveValue(this, currentFrame.Push);
                    }
                    break;
                }

                    #endregion

                    #region Числовые

                case OpCode.Inc:
                    currentFrame.Push(currentFrame.Pop().ToNumber().Inc());
                    break;

                case OpCode.Dec:
                    currentFrame.Push(currentFrame.Pop().ToNumber().Dec());
                    break;

                case OpCode.Pos:
                    currentFrame.Push(currentFrame.Pop().ToNumber());
                    break;

                case OpCode.Neg:
                    currentFrame.Push(currentFrame.Pop().ToNumber().Neg());
                    break;

                case OpCode.Plus: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(op1.Plus(op2));
                    break;
                }

                case OpCode.Minus: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.Minus(op2));
                    break;
                }

                case OpCode.Mul: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.Mul(op2));
                    break;
                }

                case OpCode.IntDiv: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.IntDiv(op2));
                    break;
                }

                case OpCode.FltDiv: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.FltDiv(op2));
                    break;
                }

                case OpCode.Mod: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.Mod(op2));
                    break;
                }

                case OpCode.BitNot:
                    currentFrame.Push(currentFrame.Pop().ToNumber().BitNot());
                    break;

                case OpCode.BitAnd: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.BitAnd(op2));
                    break;
                }

                case OpCode.BitOr: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.BitOr(op2));
                    break;
                }

                case OpCode.BitXor: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.BitXor(op2));
                    break;
                }

                case OpCode.Shl: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.BitShl(op2));
                    break;
                }

                case OpCode.ShrS: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.BitShrS(op2));
                    break;
                }

                case OpCode.ShrU: {
                    var op2 = currentFrame.Pop().ToNumber();
                    var op1 = currentFrame.Pop().ToNumber();
                    currentFrame.Push(op1.BitShrU(op2));
                    break;
                }

                    #endregion

                    #region Логические

                case OpCode.Not:
                    currentFrame.Push(currentFrame.Pop().Not());
                    break;

                case OpCode.And: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(op1.And(op2));
                    break;
                }

                case OpCode.Or: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(op1.Or(op2));
                    break;
                }

                    #endregion

                    #region  авенства

                case OpCode.ConvEq: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(op1.ConvEqualsTo(op2));
                    break;
                }

                case OpCode.StrictEq: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(op1.StrictEqualsTo(op2));
                    break;
                }

                case OpCode.ConvNeq: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(!op1.ConvEqualsTo(op2));
                    break;
                }

                case OpCode.StrictNeq: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(!op1.StrictEqualsTo(op2));
                    break;
                }

                    #endregion

                    #region Отношения

                case OpCode.Lt: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(op1.Lt(op2));
                    break;
                }

                case OpCode.Lte: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(op1.Lte(op2));
                    break;
                }

                case OpCode.Gt: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(op2.Lt(op1));
                    break;
                }

                case OpCode.Gte: {
                    var op2 = currentFrame.Pop();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(op2.Lte(op1));
                    break;
                }

                case OpCode.InstanceOf: {
                    var op2 = currentFrame.Pop().RequireFunction();
                    var op1 = currentFrame.Pop();
                    currentFrame.Push(op1.IsInstanceOf(op2));
                    break;
                }

                case OpCode.TypeOf:
                    currentFrame.Push(currentFrame.Pop().TypeOf());
                    break;

                    #endregion

                default:
                    throw new UnknownOpCodeException();
                }

                IsTerminated = CurrentFrame == null;
                if (IsTerminated)
                {
                    Result = currentFrame.Pop();
                }
            }
            catch (ReferenceErrorException ex) {
                Throw(VM.NewReferenceError(ex.Message));
            }
            catch (SyntaxErrorException ex) {
                Throw(VM.NewSyntaxError(ex.Message));
            }
            catch (TypeErrorException ex) {
                Throw(VM.NewTypeError(ex.Message));
            }
            catch (RangeErrorException ex) {
                Throw(VM.NewRangeError(ex.Message));
            }
            catch (RuntimeErrorException ex) {
                Throw(VM.NewInternalError(ex.Message, ex.StackTrace));
            }
        }
示例#6
0
 public CallStackFrameView(CallStackFrame stackFrame)
 {
     Contract.Requires(stackFrame != null);
     FunctionName = stackFrame.Function.CompiledFunction.Name;
     CodeOffset   = stackFrame.CodeReader.Offset;
 }