protected FunctionInstance(Engine engine, string[] parameters, LexicalEnvironment scope, bool strict) : base(engine)
 {
     _engine = engine;
     FormalParameters = parameters;
     Scope = scope;
     Strict = strict;
 }
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2
        /// </summary>
        /// <param name="engine"></param>
        /// <param name="functionDeclaration"></param>
        /// <param name="scope"></param>
        /// <param name="strict"></param>
        public ScriptFunctionInstance(Engine engine, IFunctionDeclaration functionDeclaration, LexicalEnvironment scope, bool strict)
            : base(engine, functionDeclaration.Parameters.Select(x => x.Name).ToArray(), scope, strict)
        {
            _functionDeclaration = functionDeclaration;

            Engine = engine;
            Extensible = true;
            Prototype = engine.Function.PrototypeObject;

            DefineOwnProperty("length", new PropertyDescriptor(new JsValue(FormalParameters.Length), false, false, false ), false);

            var proto = engine.Object.Construct(Arguments.Empty);
            proto.DefineOwnProperty("constructor", new PropertyDescriptor(this, true, false, true), false);
            DefineOwnProperty("prototype", new PropertyDescriptor(proto, true, false, false ), false);
            if (_functionDeclaration.Id != null)
            {
                DefineOwnProperty("name", new PropertyDescriptor(_functionDeclaration.Id.Name, null, null, null), false);
            }

            if (strict)
            {
                var thrower = engine.Function.ThrowTypeError;
                DefineOwnProperty("caller", new PropertyDescriptor(thrower, thrower, false, false), false);
                DefineOwnProperty("arguments", new PropertyDescriptor(thrower, thrower, false, false), false);
            }
        }
Exemplo n.º 3
0
 public Continuation(Continuation cont, LexicalEnvironment envt, object evalStack, Template template, uint pc)
 {
     CONT = cont;
     ENVT = envt;
     EVAL_STACK = evalStack;
     TEMPLATE = template;
     PC = pc;
 }
Exemplo n.º 4
0
        public ObjectInstance Construct(JsValue[] arguments)
        {
            var    argCount = arguments.Length;
            string p        = "";
            string body     = "";

            if (argCount == 1)
            {
                body = TypeConverter.ToString(arguments[0]);
            }
            else if (argCount > 1)
            {
                var firstArg = arguments[0];
                p = TypeConverter.ToString(firstArg);
                for (var k = 1; k < argCount - 1; k++)
                {
                    var nextArg = arguments[k];
                    p += "," + TypeConverter.ToString(nextArg);
                }

                body = TypeConverter.ToString(arguments[argCount - 1]);
            }

            var parameters = this.ParseArgumentNames(p);
            var parser     = new JavaScriptParser();
            FunctionExpression function;

            try
            {
                var functionExpression = "function(" + p + ") { " + body + "}";
                function = parser.ParseFunctionExpression(functionExpression);
            }
            catch (ParserException)
            {
                throw new JavaScriptException(Engine.SyntaxError);
            }

            // todo: check if there is not a way to use the FunctionExpression directly instead of creating a FunctionDeclaration
            var functionObject = new ScriptFunctionInstance(
                Engine,
                new FunctionDeclaration
            {
                Type = SyntaxNodes.FunctionDeclaration,
                Body = new BlockStatement
                {
                    Type = SyntaxNodes.BlockStatement,
                    Body = new [] { function.Body }
                },
                Parameters = parameters.Select(x => new Identifier
                {
                    Type = SyntaxNodes.Identifier,
                    Name = x
                }).ToArray(),
                FunctionDeclarations = function.FunctionDeclarations,
                VariableDeclarations = function.VariableDeclarations
            },
                LexicalEnvironment.NewDeclarativeEnvironment(Engine, Engine.ExecutionContext.LexicalEnvironment),
                function.Strict
                )
            {
                Extensible = true
            };

            return(functionObject);
        }
Exemplo n.º 5
0
 public Closure(LexicalEnvironment envt, Template template)
 {
     Envt = envt;
     Template = template;
 }
 public EvalFunctionInstance(Engine engine, string[] parameters, LexicalEnvironment scope, bool strict) : base(engine, parameters, scope, strict)
 {
     _engine   = engine;
     Prototype = Engine.Function.PrototypeObject;
     FastAddProperty("length", 1, false, false, false);
 }
Exemplo n.º 7
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-performeval
        /// </summary>
        public JsValue Call(JsValue thisObject, JsValue[] arguments, bool direct)
        {
            if (!(arguments.At(0) is JsString x))
            {
                return(arguments.At(0));
            }

            var    parser = new JavaScriptParser(x.ToString(), ParserOptions);
            Script script;

            try
            {
                script = parser.ParseScript(StrictModeScope.IsStrictModeCode);
            }
            catch (ParserException e)
            {
                return(e.Description == Messages.InvalidLHSInAssignment
                    ? ExceptionHelper.ThrowReferenceError <JsValue>(_engine)
                    : ExceptionHelper.ThrowSyntaxError <JsValue>(_engine));
            }

            var body = script.Body;

            if (body.Count == 0)
            {
                return(Undefined);
            }

            var strictEval = script.Strict || _engine._isStrict;
            var ctx        = _engine.ExecutionContext;

            using (new StrictModeScope(strictEval))
            {
                LexicalEnvironment lexEnv;
                LexicalEnvironment varEnv;
                if (direct)
                {
                    lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
                    varEnv = ctx.VariableEnvironment;
                }
                else
                {
                    lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, Engine.GlobalEnvironment);
                    varEnv = Engine.GlobalEnvironment;
                }

                if (strictEval)
                {
                    varEnv = lexEnv;
                }

                // If ctx is not already suspended, suspend ctx.

                Engine.EnterExecutionContext(lexEnv, varEnv);

                try
                {
                    Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, strictEval);

                    var statement = new JintScript(_engine, script);
                    var result    = statement.Execute();
                    var value     = result.GetValueOrDefault();

                    if (result.Type == CompletionType.Throw)
                    {
                        var ex = new JavaScriptException(value).SetCallstack(_engine, result.Location);
                        throw ex;
                    }
                    else
                    {
                        return(value);
                    }
                }
                finally
                {
                    Engine.LeaveExecutionContext();
                }
            }
        }
Exemplo n.º 8
0
 public static void ExecuteResource(LexicalEnvironment env, string resourceFile)
 {
     ExecuteResource(new Statistics(), Assembly.GetCallingAssembly(), env, resourceFile);
 }
Exemplo n.º 9
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2
        /// </summary>
        /// <param name="engine"></param>
        /// <param name="functionDeclaration"></param>
        /// <param name="scope"></param>
        /// <param name="strict"></param>
        public ScriptFunctionInstance(Engine engine, IFunctionDeclaration functionDeclaration, LexicalEnvironment scope, bool strict)
            : base(engine, functionDeclaration.Parameters.Select(x => x.Name).ToArray(), scope, strict)
        {
            _functionDeclaration = functionDeclaration;

            Engine     = engine;
            Extensible = true;
            Prototype  = engine.Function.PrototypeObject;

            DefineOwnProperty("length", new PropertyDescriptor(new JsValue(FormalParameters.Length), false, false, false), false);

            var proto = engine.Object.Construct(Arguments.Empty);

            proto.DefineOwnProperty("constructor", new PropertyDescriptor(this, true, false, true), false);
            DefineOwnProperty("prototype", new PropertyDescriptor(proto, true, false, false), false);
            if (_functionDeclaration.Id != null)
            {
                DefineOwnProperty("name", new PropertyDescriptor(_functionDeclaration.Id.Name, null, null, null), false);
            }

            if (strict)
            {
                var thrower = engine.Function.ThrowTypeError;
                DefineOwnProperty("caller", new PropertyDescriptor(thrower, thrower, false, false), false);
                DefineOwnProperty("arguments", new PropertyDescriptor(thrower, thrower, false, false), false);
            }
        }
Exemplo n.º 10
0
        private static void HandleArrayPattern(Engine engine, ArrayPattern pattern, JsValue argument, LexicalEnvironment environment)
        {
            var             obj             = TypeConverter.ToObject(engine, argument);
            ArrayOperations arrayOperations = null;
            IIterator       iterator        = null;

            if (obj.IsArrayLike)
            {
                arrayOperations = ArrayOperations.For(obj);
            }
            else
            {
                if (!obj.TryGetIterator(engine, out iterator))
                {
                    ExceptionHelper.ThrowTypeError(engine);
                    return;
                }
            }

            var  completionType = CompletionType.Normal;
            var  close          = false;
            var  done           = false;
            uint i = 0;

            try
            {
                for (; i < pattern.Elements.Count; i++)
                {
                    var left = pattern.Elements[(int)i];

                    if (left is null)
                    {
                        if (arrayOperations != null)
                        {
                            arrayOperations.TryGetValue(i, out _);
                        }
                        else
                        {
                            if (!ConsumeFromIterator(iterator, out _, out done))
                            {
                                break;
                            }
                        }
                        // skip assignment
                        continue;
                    }

                    if (left is Identifier identifier)
                    {
                        JsValue value;
                        if (arrayOperations != null)
                        {
                            arrayOperations.TryGetValue(i, out value);
                        }
                        else
                        {
                            if (!ConsumeFromIterator(iterator, out value, out done))
                            {
                                break;
                            }
                        }

                        AssignToIdentifier(engine, identifier.Name, value, environment);
                    }
                    else if (left is MemberExpression me)
                    {
                        close = true;
                        var     reference = GetReferenceFromMember(engine, me);
                        JsValue value;
                        if (arrayOperations != null)
                        {
                            arrayOperations.TryGetValue(i, out value);
                        }
                        else
                        {
                            ConsumeFromIterator(iterator, out value, out done);
                        }

                        AssignToReference(engine, reference, value, environment);
                    }
                    else if (left is BindingPattern bindingPattern)
                    {
                        JsValue value;
                        if (arrayOperations != null)
                        {
                            arrayOperations.TryGetValue(i, out value);
                        }
                        else
                        {
                            iterator.TryIteratorStep(out var temp);
                            value = temp;
                        }
                        ProcessPatterns(engine, bindingPattern, value, environment);
                    }
                    else if (left is RestElement restElement)
                    {
                        close = true;
                        Reference reference = null;
                        if (restElement.Argument is MemberExpression memberExpression)
                        {
                            reference = GetReferenceFromMember(engine, memberExpression);
                        }

                        ArrayInstance array;
                        if (arrayOperations != null)
                        {
                            var length = arrayOperations.GetLength();
                            array = engine.Array.ConstructFast(length - i);
                            for (uint j = i; j < length; ++j)
                            {
                                arrayOperations.TryGetValue(j, out var indexValue);
                                array.SetIndexValue(j - i, indexValue, updateLength: false);
                            }
                        }
                        else
                        {
                            array = engine.Array.ConstructFast(0);
                            uint index = 0;
                            done = true;
                            do
                            {
                                if (!iterator.TryIteratorStep(out var item))
                                {
                                    done = true;
                                    break;
                                }

                                var value = item.Get(CommonProperties.Value);
                                array.SetIndexValue(index++, value, updateLength: false);
                            } while (true);

                            array.SetLength(index);
                        }

                        if (restElement.Argument is Identifier leftIdentifier)
                        {
                            AssignToIdentifier(engine, leftIdentifier.Name, array, environment);
                        }
                        else if (restElement.Argument is BindingPattern bp)
                        {
                            ProcessPatterns(engine, bp, array, environment);
                        }
                        else
                        {
                            AssignToReference(engine, reference, array, environment);
                        }
                    }
                    else if (left is AssignmentPattern assignmentPattern)
                    {
                        JsValue value;
                        if (arrayOperations != null)
                        {
                            arrayOperations.TryGetValue(i, out value);
                        }
                        else
                        {
                            ConsumeFromIterator(iterator, out value, out done);
                        }

                        if (value.IsUndefined())
                        {
                            var jintExpression = Build(engine, assignmentPattern.Right);
                            value = jintExpression.GetValue();
                        }

                        if (assignmentPattern.Left is Identifier leftIdentifier)
                        {
                            if (assignmentPattern.Right.IsFunctionWithName())
                            {
                                ((FunctionInstance)value).SetFunctionName(new JsString(leftIdentifier.Name));
                            }

                            AssignToIdentifier(engine, leftIdentifier.Name, value, environment);
                        }
                        else if (assignmentPattern.Left is BindingPattern bp)
                        {
                            ProcessPatterns(engine, bp, value, environment);
                        }
                    }
                    else
                    {
                        ExceptionHelper.ThrowArgumentOutOfRangeException("pattern",
                                                                         "Unable to determine how to handle array pattern element " + left);
                        break;
                    }
                }

                close = true;
            }
            catch
            {
                completionType = CompletionType.Throw;
                throw;
            }
            finally
            {
                if (close && !done)
                {
                    iterator?.Close(completionType);
                }
            }
        }
Exemplo n.º 11
0
        private static void HandleObjectPattern(Engine engine, ObjectPattern pattern, JsValue argument, LexicalEnvironment environment, bool checkReference)
        {
            var processedProperties = pattern.Properties.Count > 0 && pattern.Properties[pattern.Properties.Count - 1] is RestElement
                ? new HashSet <JsValue>()
                : null;

            var source = TypeConverter.ToObject(engine, argument);

            for (var i = 0; i < pattern.Properties.Count; i++)
            {
                if (pattern.Properties[i] is Property p)
                {
                    JsValue sourceKey;
                    var     identifier = p.Key as Identifier;
                    if (identifier == null || p.Computed)
                    {
                        var keyExpression = Build(engine, p.Key);
                        sourceKey = TypeConverter.ToPropertyKey(keyExpression.GetValue());
                    }
                    else
                    {
                        sourceKey = identifier.Name;
                    }

                    processedProperties?.Add(sourceKey.ToString());
                    if (p.Value is AssignmentPattern assignmentPattern)
                    {
                        source.TryGetValue(sourceKey, out var value);
                        if (value.IsUndefined())
                        {
                            var jintExpression = Build(engine, assignmentPattern.Right);
                            value = jintExpression.GetValue();
                        }

                        if (assignmentPattern.Left is BindingPattern bp)
                        {
                            ProcessPatterns(engine, bp, value, environment);
                            continue;
                        }

                        var target = assignmentPattern.Left as Identifier ?? identifier;

                        if (assignmentPattern.Right.IsFunctionWithName())
                        {
                            ((FunctionInstance)value).SetFunctionName(target.Name);
                        }

                        AssignToIdentifier(engine, target.Name, value, environment);
                    }
                    else if (p.Value is BindingPattern bindingPattern)
                    {
                        source.TryGetValue(sourceKey, out var value);
                        ProcessPatterns(engine, bindingPattern, value, environment);
                    }
                    else if (p.Value is MemberExpression memberExpression)
                    {
                        var reference = GetReferenceFromMember(engine, memberExpression);
                        source.TryGetValue(sourceKey, out var value);
                        AssignToReference(engine, reference, value, environment);
                    }
                    else
                    {
                        var identifierReference = p.Value as Identifier;
                        var target = identifierReference ?? identifier;
                        source.TryGetValue(sourceKey, out var v);
                        AssignToIdentifier(engine, target.Name, v, environment, checkReference);
                    }
                }
                else
                {
                    var restElement = (RestElement)pattern.Properties[i];
                    if (restElement.Argument is Identifier leftIdentifier)
                    {
                        var count = Math.Max(0, source.Properties?.Count ?? 0) - processedProperties.Count;
                        var rest  = engine.Object.Construct(count);
                        source.CopyDataProperties(rest, processedProperties);
                        AssignToIdentifier(engine, leftIdentifier.Name, rest, environment);
                    }
                    else if (restElement.Argument is BindingPattern bp)
                    {
                        ProcessPatterns(engine, bp, argument, environment);
                    }
                    else if (restElement.Argument is MemberExpression memberExpression)
                    {
                        var left = GetReferenceFromMember(engine, memberExpression);
                        var rest = engine.Object.Construct(0);
                        source.CopyDataProperties(rest, processedProperties);
                        AssignToReference(engine, left, rest, environment);
                    }
                    else
                    {
                        ExceptionHelper.ThrowArgumentException("cannot handle parameter type " + restElement.Argument);
                    }
                }
            }
        }
Exemplo n.º 12
0
 public Closure(LexicalEnvironment envt, Template template)
 {
     Envt     = envt;
     Template = template;
 }
        /// <summary>
        /// https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
        /// </summary>
        public override JsValue Call(JsValue thisArgument, JsValue[] arguments)
        {
            // ** PrepareForOrdinaryCall **
            // var callerContext = _engine.ExecutionContext;
            // Let calleeRealm be F.[[Realm]].
            // Set the Realm of calleeContext to calleeRealm.
            // Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
            var localEnv = LexicalEnvironment.NewFunctionEnvironment(_engine, this, Undefined);

            // If callerContext is not already suspended, suspend callerContext.
            // Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
            // NOTE: Any exception objects produced after this point are associated with calleeRealm.
            // Return calleeContext.

            _engine.EnterExecutionContext(localEnv, localEnv);

            // ** OrdinaryCallBindThis **

            JsValue thisValue;

            if (_thisMode == FunctionThisMode.Strict)
            {
                thisValue = thisArgument;
            }
            else
            {
                if (thisArgument.IsNullOrUndefined())
                {
                    var globalEnv    = _engine.GlobalEnvironment;
                    var globalEnvRec = (GlobalEnvironmentRecord)globalEnv._record;
                    thisValue = globalEnvRec.GlobalThisValue;
                }
                else
                {
                    thisValue = TypeConverter.ToObject(_engine, thisArgument);
                }
            }

            var envRec = (FunctionEnvironmentRecord)localEnv._record;

            envRec.BindThisValue(thisValue);

            // actual call

            var strict = _thisMode == FunctionThisMode.Strict || _engine._isStrict;

            using (new StrictModeScope(strict, true))
            {
                try
                {
                    var argumentsInstance = _engine.FunctionDeclarationInstantiation(
                        functionInstance: this,
                        arguments,
                        localEnv);

                    var result = _function.Execute();
                    var value  = result.GetValueOrDefault().Clone();
                    argumentsInstance?.FunctionWasCalled();

                    if (result.Type == CompletionType.Throw)
                    {
                        ExceptionHelper.ThrowJavaScriptException(_engine, value, result);
                    }

                    if (result.Type == CompletionType.Return)
                    {
                        return(value);
                    }
                }
                finally
                {
                    _engine.LeaveExecutionContext();
                }

                return(Undefined);
            }
        }
 public void SetContext(LexicalEnvironment lexicalEnvironment, ParseContext parseContext)
 {
     ParseContext = parseContext;
     Context      = Engine.CreateContext(parseContext);
     ParseContext.LexicalEnvironment = Context.LexicalEnvironment = lexicalEnvironment;
 }
        public Engine(Action <Options> options)
        {
            _executionContexts = new Stack <ExecutionContext>();

            Global = GlobalObject.CreateGlobalObject(this);

            Object   = ObjectConstructor.CreateObjectConstructor(this);
            Function = FunctionConstructor.CreateFunctionConstructor(this);

            Array   = ArrayConstructor.CreateArrayConstructor(this);
            String  = StringConstructor.CreateStringConstructor(this);
            RegExp  = RegExpConstructor.CreateRegExpConstructor(this);
            Number  = NumberConstructor.CreateNumberConstructor(this);
            Boolean = BooleanConstructor.CreateBooleanConstructor(this);
            Date    = DateConstructor.CreateDateConstructor(this);
            Math    = MathInstance.CreateMathObject(this);
            Json    = JsonInstance.CreateJsonObject(this);

            Error          = ErrorConstructor.CreateErrorConstructor(this, "Error");
            EvalError      = ErrorConstructor.CreateErrorConstructor(this, "EvalError");
            RangeError     = ErrorConstructor.CreateErrorConstructor(this, "RangeError");
            ReferenceError = ErrorConstructor.CreateErrorConstructor(this, "ReferenceError");
            SyntaxError    = ErrorConstructor.CreateErrorConstructor(this, "SyntaxError");
            TypeError      = ErrorConstructor.CreateErrorConstructor(this, "TypeError");
            UriError       = ErrorConstructor.CreateErrorConstructor(this, "URIError");

            // Because the properties might need some of the built-in object
            // their configuration is delayed to a later step

            Global.Configure();

            Object.Configure();
            Object.PrototypeObject.Configure();

            Function.Configure();
            Function.PrototypeObject.Configure();

            Array.Configure();
            Array.PrototypeObject.Configure();

            String.Configure();
            String.PrototypeObject.Configure();

            RegExp.Configure();
            RegExp.PrototypeObject.Configure();

            Number.Configure();
            Number.PrototypeObject.Configure();

            Boolean.Configure();
            Boolean.PrototypeObject.Configure();

            Date.Configure();
            Date.PrototypeObject.Configure();

            Math.Configure();
            Json.Configure();

            Error.Configure();
            Error.PrototypeObject.Configure();

            // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
            GlobalEnvironment = LexicalEnvironment.NewObjectEnvironment(this, Global, null, false);

            // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
            EnterExecutionContext(GlobalEnvironment, GlobalEnvironment, Global);

            Options = new Options();

            if (options != null)
            {
                options(Options);
            }

            Eval = new EvalFunctionInstance(this, new string[0], LexicalEnvironment.NewDeclarativeEnvironment(this, ExecutionContext.LexicalEnvironment), StrictModeScope.IsStrictModeCode);
            Global.FastAddProperty("eval", Eval, true, false, true);

            _statements  = new StatementInterpreter(this);
            _expressions = new ExpressionInterpreter(this);

            if (Options.IsClrAllowed())
            {
                Global.FastAddProperty("System", new NamespaceReference(this, "System"), false, false, false);
                Global.FastAddProperty("importNamespace", new ClrFunctionInstance(this, (thisObj, arguments) =>
                {
                    return(new NamespaceReference(this, TypeConverter.ToString(arguments.At(0))));
                }), false, false, false);
            }

            ClrTypeConverter = new DefaultTypeConverter(this);
        }
Exemplo n.º 16
0
 public Closure(LexicalEnvironment env, IEnumerable <ArgBody> argBodies)
 {
     this.env       = env;
     this.argBodies = argBodies;
 }
Exemplo n.º 17
0
        private Completion GlobalDeclarationInstantiation(LexicalEnvironment env)
        {
            var envRecAbstract = env.EnvironmentRecord;

            if (!(envRecAbstract is GlobalEnvironmentRecord envRec))
            {
                throw new InvalidOperationException("Spec 15.1.11 step 2");
            }
            var lexNames = scriptBody.LexicallyDeclaredNames();
            var varNames = scriptBody.VarDeclaredNames();

            foreach (var name in lexNames)
            {
                if (envRec.HasVarDeclaration(name))
                {
                    return(Completion.ThrowSyntaxError($"variable {name} is already declared"));
                }
                if (envRec.HasLexicalDeclaration(name))
                {
                    return(Completion.ThrowSyntaxError($"variable {name} is already declared"));
                }
                var hasRestrictedGlobal = envRec.HasRestrictedGlobalProperty(name);
                if (hasRestrictedGlobal.IsAbrupt())
                {
                    return(hasRestrictedGlobal);
                }
                if (hasRestrictedGlobal.Other == true)
                {
                    return(Completion.ThrowSyntaxError($"variable {name} is already a restricted global"));
                }
            }
            foreach (var name in varNames)
            {
                if (envRec.HasLexicalDeclaration(name))
                {
                    return(Completion.ThrowSyntaxError($"variable {name} is already declared"));
                }
            }
            var varDeclarations       = scriptBody.VarScopedDeclarations();
            var functionsToInitialize = new List <FunctionDeclaration>();
            var declaredFunctionNames = new List <string>();

            foreach (var d in varDeclarations.Reverse())
            {
                if (d is FunctionDeclaration f)
                {
                    var fn = f.BoundNames()[0];
                    if (!declaredFunctionNames.Contains(fn))
                    {
                        var fnDefinable = envRec.CanDeclareGlobalFunction(fn);
                        if (fnDefinable.IsAbrupt())
                        {
                            return(fnDefinable);
                        }
                        if (!fnDefinable.Other)
                        {
                            return(Completion.ThrowTypeError($"function {fn} cannot be declared."));
                        }
                        declaredFunctionNames.Add(fn);
                        functionsToInitialize.Insert(0, f);
                    }
                }
            }
            var declaredVarNames = new List <string>();

            foreach (var d in varDeclarations)
            {
                string vn;
                if (d is VariableDeclaration v)
                {
                    vn = v.name;
                }
                else if (d is ForBinding f)
                {
                    vn = f.name;
                }
                else
                {
                    continue;
                }
                if (!declaredVarNames.Contains(vn))
                {
                    var vnDefinable = envRec.CanDeclareGlobalVar(vn);
                    if (vnDefinable.IsAbrupt())
                    {
                        return(vnDefinable);
                    }
                    if (!vnDefinable.Other)
                    {
                        return(Completion.ThrowTypeError($"variable {vn} cannot be declared."));
                    }
                    declaredVarNames.Add(vn);
                }
            }
            //TODO Annex B.3.3.2
            var lexDeclarations = scriptBody.LexicallyScopedDeclarations();

            foreach (var d in lexDeclarations)
            {
                foreach (var dn in d.BoundNames())
                {
                    Completion comp;
                    if (d.IsConstantDeclaration())
                    {
                        comp = envRec.CreateImmutableBinding(dn, true);
                    }
                    else
                    {
                        comp = envRec.CreateMutableBinding(dn, false);
                    }
                    if (comp.IsAbrupt())
                    {
                        return(comp);
                    }
                }
            }
            foreach (var f in functionsToInitialize)
            {
                var fn   = f.BoundNames()[0];
                var fo   = f.InstantiateFunctionObject(env);
                var comp = envRec.CreateGlobalFunctionBinding(fn, fo, false);
                if (comp.IsAbrupt())
                {
                    return(comp);
                }
            }
            foreach (var vn in declaredVarNames)
            {
                var comp = envRec.CreateGlobalVarBinding(vn, false);
                if (comp.IsAbrupt())
                {
                    return(comp);
                }
            }
            return(Completion.NormalCompletion());
        }
Exemplo n.º 18
0
 public FunctionShim(Engine engine, string[] parameters, LexicalEnvironment scope) : base(engine, parameters, scope, false)
 {
 }
Exemplo n.º 19
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.14
        /// </summary>
        /// <param name="tryStatement"></param>
        /// <returns></returns>
        public void ExecuteTryStatement(RuntimeState state)
        {
            TryStatement             tryStatement = (TryStatement)state.arg;
            ExecuteTryStatementLocal local;

            if (state.local == null)
            {
                state.local = local = new ExecuteTryStatementLocal();
                local.stage = 0;
            }
            else
            {
                local = (ExecuteTryStatementLocal)state.local;
            }

            if (local.stage == 0)
            {
                if (state.calleeReturned)
                {
                    state.calleeReturned = false;
                    local.stage          = 1;
                    local.b = (Completion)state.calleeReturnValue;
                    return;
                }

                Call(_engine.ExecuteStatement, tryStatement.Block);
                return;
            }

            if (local.stage == 1)
            {
                if (state.calleeReturned)
                {
                    state.calleeReturned = false;
                    local.stage          = 2;
                    local.b = (Completion)state.calleeReturnValue;
                    return;
                }

                var catchClause = tryStatement.Handler;
                if (catchClause != null)
                {
                    var c = local.b.Value;
                    local.oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                    var catchEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, local.oldEnv);
                    catchEnv._record.CreateMutableBinding(((Identifier)catchClause.Param).Name, c);

                    _engine.UpdateLexicalEnvironment(catchEnv);
                    Call(_engine.ExecuteStatement, catchClause.Body);
                    return;
                }
                local.stage = 2;
            }

            if (local.stage == 2)
            {
                if (state.calleeReturned)
                {
                    var f = (Completion)state.calleeReturnValue;
                    if (f.Type == CompletionType.Normal)
                    {
                        Return(local.b);
                        return;
                    }

                    Return(f);
                    return;
                }

                if (tryStatement.Finalizer != null)
                {
                    Call(_engine.ExecuteStatement, tryStatement.Finalizer);
                    return;
                }

                Return(local.b);
                return;
            }
        }
Exemplo n.º 20
0
        /// <summary>
        /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2
        /// </summary>
        /// <param name="functionDeclaration"></param>
        /// <returns></returns>
        public FunctionInstance CreateFunctionObject(FunctionDeclaration functionDeclaration, LexicalEnvironment env)
        {
            var functionObject = new ScriptFunctionInstance(
                Engine,
                functionDeclaration,
                env,
                functionDeclaration.Strict || _engine._isStrict);

            return(functionObject);
        }
 public EvalFunctionInstance(Engine engine, string[] parameters, LexicalEnvironment scope, bool strict) : base(engine, parameters, scope, strict)
 {
     _engine = engine;
     Prototype = Engine.Function.PrototypeObject;
     FastAddProperty("length", 1, false, false, false);
 }
Exemplo n.º 22
0
        public override ParseResult VisitFunctionDefinitionStatement(MelonParser.FunctionDefinitionStatementContext context)
        {
            string name = context.Name.GetText();

            LexicalEnvironment functionEnvironment = new LexicalEnvironment(parseContext.LexicalEnvironment, true);

            var functionParameters = new List <FunctionParameter>();

            if (context.Parameters != null)
            {
                for (var i = 0; i < context.Parameters.parameter().Length; i++)
                {
                    var parameter = context.Parameters.parameter(i);

                    bool isVarargs = parameter.VARARGS() != null;

                    if (isVarargs && i < context.Parameters.parameter().Length - 1)
                    {
                        throw new MelonException("Varargs parameter can only appear once and has to be the last parameter");
                    }

                    MelonType type = _engine.anyType;

                    if (parameter.Type != null)
                    {
                        var typeName = parameter.Type.name().value;
                        var typeKv   = _engine.Types.FirstOrDefault(x => x.Value.Name == typeName);

                        if (typeKv.Value == null)
                        {
                            throw new MelonException($"Could not find type '{typeName}'");
                        }

                        type = typeKv.Value;
                    }

                    var typeRef = new TypeReference(_engine, type);

                    functionEnvironment.AddVariable(parameter.Name.value, null, typeRef);
                    functionParameters.Add(new FunctionParameter(parameter.Name.value, typeRef, isVarargs));
                }
            }

            var function = new ScriptFunctionInstance(name, _engine)
            {
                ParameterTypes = functionParameters.ToArray()
            };

            var variable = parseContext.LexicalEnvironment.AddVariable(name, function, new TypeReference(_engine, _engine.functionType));

            parseContext.AddVariableReference(variable, VariableReferenceType.Local);

            if (context.ReturnType != null)
            {
                var typeName = context.ReturnType.value;
                var typeKv   = _engine.Types.FirstOrDefault(x => x.Value.Name == typeName);

                if (typeKv.Value == null)
                {
                    throw new MelonException($"Could not find type '{typeName}'");
                }

                function.ReturnType = new TypeReference(_engine, typeKv.Value);
            }

            MelonVisitor visitor = new MelonVisitor(_engine, function);
            ParseContext functionParseContext = visitor.Parse(context.Block, functionEnvironment);

            function.SetContext(functionEnvironment, functionParseContext);

            return(DefaultResult);
        }
        public Completion Execute(JsValue input)
        {
            if (!_initialized)
            {
                Initialize();
                _initialized = true;
            }

            JsValue        v           = Undefined.Instance;
            Location       l           = _engine._lastSyntaxNode.Location;
            JintSwitchCase defaultCase = null;
            bool           hit         = false;

            for (var i = 0; i < (uint)_jintSwitchBlock.Length; i++)
            {
                var clause = _jintSwitchBlock[i];

                LexicalEnvironment oldEnv = null;
                if (clause.LexicalDeclarations != null)
                {
                    oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                    var blockEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                    JintStatementList.BlockDeclarationInstantiation(blockEnv, clause.LexicalDeclarations);
                    _engine.UpdateLexicalEnvironment(blockEnv);
                }

                if (clause.Test == null)
                {
                    defaultCase = clause;
                }
                else
                {
                    var clauseSelector = clause.Test.GetValue();
                    if (JintBinaryExpression.StrictlyEqual(clauseSelector, input))
                    {
                        hit = true;
                    }
                }

                if (hit && clause.Consequent != null)
                {
                    var r = clause.Consequent.Execute();

                    if (oldEnv != null)
                    {
                        _engine.UpdateLexicalEnvironment(oldEnv);
                    }

                    if (r.Type != CompletionType.Normal)
                    {
                        return(r);
                    }

                    l = r.Location;
                    v = r.Value ?? Undefined.Instance;
                }
            }

            // do we need to execute the default case ?
            if (hit == false && defaultCase != null)
            {
                LexicalEnvironment oldEnv = null;
                if (defaultCase.LexicalDeclarations != null)
                {
                    oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                    var blockEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                    JintStatementList.BlockDeclarationInstantiation(blockEnv, defaultCase.LexicalDeclarations);
                    _engine.UpdateLexicalEnvironment(blockEnv);
                }

                var r = defaultCase.Consequent.Execute();

                if (oldEnv != null)
                {
                    _engine.UpdateLexicalEnvironment(oldEnv);
                }
                if (r.Type != CompletionType.Normal)
                {
                    return(r);
                }

                l = r.Location;
                v = r.Value ?? Undefined.Instance;
            }

            return(new Completion(CompletionType.Normal, v, null, l));
        }
Exemplo n.º 24
0
 public JavaScriptEngine()
 {
     _engine = new Engine();
     _engine.SetValue("console", new ConsoleInstance(_engine));
     _variable = LexicalEnvironment.NewObjectEnvironment(_engine, _engine.Global, null, false);
 }
Exemplo n.º 25
0
 protected JsFunction(LexicalEnvironment lexEnv) : base(lexEnv)
 {
     Scope = lexEnv;
 }
        public JsValue Call(JsValue thisObject, JsValue[] arguments, bool directCall)
        {
            if (arguments.At(0).Type != Types.String)
            {
                return(arguments.At(0));
            }

            var code = TypeConverter.ToString(arguments.At(0));

            try
            {
                var parser  = new JavaScriptParser(StrictModeScope.IsStrictModeCode);
                var program = parser.Parse(code);
                using (new StrictModeScope(program.Strict))
                {
                    using (new EvalCodeScope())
                    {
                        LexicalEnvironment strictVarEnv = null;

                        try
                        {
                            if (!directCall)
                            {
                                Engine.EnterExecutionContext(Engine.GlobalEnvironment, Engine.GlobalEnvironment, Engine.Global);
                            }

                            if (StrictModeScope.IsStrictModeCode)
                            {
                                strictVarEnv = LexicalEnvironment.NewDeclarativeEnvironment(Engine, Engine.ExecutionContext.LexicalEnvironment);
                                Engine.EnterExecutionContext(strictVarEnv, strictVarEnv, Engine.ExecutionContext.ThisBinding);
                            }

                            Engine.DeclarationBindingInstantiation(DeclarationBindingType.EvalCode, program.FunctionDeclarations, program.VariableDeclarations, this, arguments);

                            var result = _engine.ExecuteStatement(program);

                            if (result.Type == Completion.Throw)
                            {
                                throw new JavaScriptException(result.GetValueOrDefault());
                            }
                            else
                            {
                                return(result.GetValueOrDefault());
                            }
                        }
                        finally
                        {
                            if (strictVarEnv != null)
                            {
                                Engine.LeaveExecutionContext();
                            }

                            if (!directCall)
                            {
                                Engine.LeaveExecutionContext();
                            }
                        }
                    }
                }
            }
            catch (ParserException)
            {
                throw new JavaScriptException(Engine.SyntaxError);
            }
        }
Exemplo n.º 27
0
 protected abstract JsValue CallInternal(LexicalEnvironment env);
Exemplo n.º 28
0
        /// <summary>
        /// https://tc39.es/ecma262/#sec-runtime-semantics-forin-div-ofbodyevaluation-lhs-stmt-iterator-lhskind-labelset
        /// </summary>
        private Completion BodyEvaluation(
            JintExpression lhs,
            JintStatement stmt,
            IIterator iteratorRecord,
            IterationKind iterationKind,
            LhsKind lhsKind,
            IteratorKind iteratorKind = IteratorKind.Sync)
        {
            var    oldEnv        = _engine.ExecutionContext.LexicalEnvironment;
            var    v             = Undefined.Instance;
            var    destructuring = _destructuring;
            string lhsName       = null;

            var completionType = CompletionType.Normal;
            var close          = false;

            try
            {
                while (true)
                {
                    LexicalEnvironment iterationEnv = null;
                    if (!iteratorRecord.TryIteratorStep(out var nextResult))
                    {
                        close = true;
                        return(new Completion(CompletionType.Normal, v, null, Location));
                    }

                    if (iteratorKind == IteratorKind.Async)
                    {
                        // nextResult = await nextResult;
                    }

                    var nextValue = nextResult.Get(CommonProperties.Value);
                    close = true;

                    Reference lhsRef = null;
                    if (lhsKind != LhsKind.LexicalBinding)
                    {
                        if (!destructuring)
                        {
                            lhsRef = (Reference)lhs.Evaluate();
                        }
                    }
                    else
                    {
                        iterationEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                        if (_tdzNames != null)
                        {
                            BindingInstantiation(iterationEnv);
                        }
                        _engine.UpdateLexicalEnvironment(iterationEnv);

                        if (!destructuring)
                        {
                            if (lhsName == null)
                            {
                                lhsName = ((Identifier)((VariableDeclaration)_leftNode).Declarations[0].Id).Name;
                            }
                            lhsRef = _engine.ResolveBinding(lhsName);
                        }
                    }

                    if (!destructuring)
                    {
                        // If lhsRef is an abrupt completion, then
                        // Let status be lhsRef.

                        if (lhsKind == LhsKind.LexicalBinding)
                        {
                            lhsRef.InitializeReferencedBinding(nextValue);
                        }
                        else
                        {
                            _engine.PutValue(lhsRef, nextValue);
                        }
                    }
                    else
                    {
                        BindingPatternAssignmentExpression.ProcessPatterns(
                            _engine,
                            _assignmentPattern,
                            nextValue,
                            iterationEnv,
                            checkObjectPatternPropertyReference: _lhsKind != LhsKind.VarBinding);

                        if (lhsKind == LhsKind.Assignment)
                        {
                            // DestructuringAssignmentEvaluation of assignmentPattern using nextValue as the argument.
                        }
                        else if (lhsKind == LhsKind.VarBinding)
                        {
                            // BindingInitialization for lhs passing nextValue and undefined as the arguments.
                        }
                        else
                        {
                            // BindingInitialization for lhs passing nextValue and iterationEnv as arguments
                        }
                    }

                    var result = stmt.Execute();
                    _engine.UpdateLexicalEnvironment(oldEnv);

                    if (!ReferenceEquals(result.Value, null))
                    {
                        v = result.Value;
                    }

                    if (result.Type == CompletionType.Break && (result.Identifier == null || result.Identifier == _statement?.LabelSet?.Name))
                    {
                        return(new Completion(CompletionType.Normal, v, null, Location));
                    }

                    if (result.Type != CompletionType.Continue || (result.Identifier != null && result.Identifier != _statement?.LabelSet?.Name))
                    {
                        if (result.Type != CompletionType.Normal)
                        {
                            return(result);
                        }
                    }
                }
            }
            catch
            {
                completionType = CompletionType.Throw;
                throw;
            }
            finally
            {
                if (close)
                {
                    iteratorRecord.Close(completionType);
                }
                _engine.UpdateLexicalEnvironment(oldEnv);
            }
        }
Exemplo n.º 29
0
 protected override JsValue CallInternal(LexicalEnvironment env)
 {
     throw new NotImplementedException();
 }
        public ExecutionContext EnterExecutionContext(LexicalEnvironment lexicalEnvironment, LexicalEnvironment variableEnvironment, JsValue thisBinding)
        {
            var executionContext = new ExecutionContext
            {
                LexicalEnvironment  = lexicalEnvironment,
                VariableEnvironment = variableEnvironment,
                ThisBinding         = thisBinding
            };

            _executionContexts.Push(executionContext);

            return(executionContext);
        }
Exemplo n.º 31
0
 public JsCompiledFunction(LexicalEnvironment lexEnv, string[] parameters) : base(lexEnv)
 {
     Parameters = parameters;
 }
Exemplo n.º 32
0
 public FunctionShim(JSEngine engine, string[] parameters, LexicalEnvironment scope) : base(engine, parameters, scope, false)
 {
 }
Exemplo n.º 33
0
 internal void UpdateLexicalEnvironment(LexicalEnvironment newEnv)
 {
     _executionContexts.ReplaceTopLexicalEnvironment(newEnv);
 }
Exemplo n.º 34
0
 public override Continuation Evaluate(Continuation c, LexicalEnvironment env, Datum args)
 {
     return(c.PushResult(evaluate(c, env, args)));
 }
Exemplo n.º 35
0
        public Engine(Action <Options> options)
        {
            _executionContexts = new ExecutionContextStack();

            Global = GlobalObject.CreateGlobalObject(this);

            Object   = ObjectConstructor.CreateObjectConstructor(this);
            Function = FunctionConstructor.CreateFunctionConstructor(this);

            Symbol   = SymbolConstructor.CreateSymbolConstructor(this);
            Array    = ArrayConstructor.CreateArrayConstructor(this);
            Map      = MapConstructor.CreateMapConstructor(this);
            Set      = SetConstructor.CreateSetConstructor(this);
            Iterator = IteratorConstructor.CreateIteratorConstructor(this);
            String   = StringConstructor.CreateStringConstructor(this);
            RegExp   = RegExpConstructor.CreateRegExpConstructor(this);
            Number   = NumberConstructor.CreateNumberConstructor(this);
            Boolean  = BooleanConstructor.CreateBooleanConstructor(this);
            //            Date = DateConstructor.CreateDateConstructor(this);
            Math = MathInstance.CreateMathObject(this);
            Json = JsonInstance.CreateJsonObject(this);

            Error          = ErrorConstructor.CreateErrorConstructor(this, "Error");
            EvalError      = ErrorConstructor.CreateErrorConstructor(this, "EvalError");
            RangeError     = ErrorConstructor.CreateErrorConstructor(this, "RangeError");
            ReferenceError = ErrorConstructor.CreateErrorConstructor(this, "ReferenceError");
            SyntaxError    = ErrorConstructor.CreateErrorConstructor(this, "SyntaxError");
            TypeError      = ErrorConstructor.CreateErrorConstructor(this, "TypeError");
            UriError       = ErrorConstructor.CreateErrorConstructor(this, "URIError");

            GlobalSymbolRegistry = new GlobalSymbolRegistry();

            // Because the properties might need some of the built-in object
            // their configuration is delayed to a later step

            Global.Configure();

            Object.Configure();
            Object.PrototypeObject.Configure();

            Symbol.Configure();
            Symbol.PrototypeObject.Configure();

            Function.Configure();
            Function.PrototypeObject.Configure();

            Array.Configure();
            Array.PrototypeObject.Configure();

            Map.Configure();
            Map.PrototypeObject.Configure();

            Set.Configure();
            Set.PrototypeObject.Configure();

            Iterator.Configure();
            Iterator.PrototypeObject.Configure();

            String.Configure();
            String.PrototypeObject.Configure();

            RegExp.Configure();
            RegExp.PrototypeObject.Configure();

            Number.Configure();
            Number.PrototypeObject.Configure();

            Boolean.Configure();
            Boolean.PrototypeObject.Configure();

            //            Date.Configure();
            //            Date.PrototypeObject.Configure();

            Math.Configure();
            Json.Configure();

            Error.Configure();
            Error.PrototypeObject.Configure();

            // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
            GlobalEnvironment = LexicalEnvironment.NewObjectEnvironment(this, Global, null, false);

            // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
            EnterExecutionContext(GlobalEnvironment, GlobalEnvironment, Global);

            Options = new Options();

            options?.Invoke(Options);

            // gather some options as fields for faster checks
            _isDebugMode = Options.IsDebugMode;

            if (_isDebugMode)
            {
                MyAPIGateway.Utilities.ShowMessage("SpaceJS", "Debug mode enabled.");
            }

            _isStrict                 = Options.IsStrict;
            _maxStatements            = Options._MaxStatements;
            _referenceResolver        = Options.ReferenceResolver;
            _memoryLimit              = Options._MemoryLimit;
            _runBeforeStatementChecks = (_maxStatements > 0 && _maxStatements < int.MaxValue) ||
                                        Options._TimeoutInterval.Ticks > 0 ||
                                        _memoryLimit > 0 ||
                                        _isDebugMode;

            _referencePool         = new ReferencePool();
            _argumentsInstancePool = new ArgumentsInstancePool(this);
            _jsValueArrayPool      = new JsValueArrayPool();

            Eval = new EvalFunctionInstance(this, System.ArrayExt.Empty <string>(), LexicalEnvironment.NewDeclarativeEnvironment(this, ExecutionContext.LexicalEnvironment), StrictModeScope.IsStrictModeCode);
            Global.FastAddProperty("eval", Eval, true, false, true);

            _statements  = new StatementInterpreter(this);
            _expressions = new ExpressionInterpreter(this);

            /*            if (Options._IsClrAllowed)
             *          {
             *              Global.FastAddProperty("System", new NamespaceReference(this, "System"), false, false, false);
             *              Global.FastAddProperty("importNamespace", new ClrFunctionInstance(
             *                  this,
             *                  "importNamespace",
             *                  (thisObj, arguments) => new NamespaceReference(this, TypeConverter.ToString(arguments.At(0)))), false, false, false);
             *          }
             */
            //            ClrTypeConverter = new DefaultTypeConverter(this);
        }
Exemplo n.º 36
0
        public ExecutionContext EnterExecutionContext(LexicalEnvironment lexicalEnvironment, LexicalEnvironment variableEnvironment, JsValue thisBinding)
        {
            var executionContext = new ExecutionContext
                {
                    LexicalEnvironment = lexicalEnvironment,
                    VariableEnvironment = variableEnvironment,
                    ThisBinding = thisBinding
                };
            _executionContexts.Push(executionContext);

            return executionContext;
        }
Exemplo n.º 37
0
        public static void BlockDeclarationInstantiation(IHasLexicallyScopedDeclarations code, LexicalEnvironment env)
        {
            var envRec = env.EnvironmentRecord;

            if (!(envRec is DeclarativeEnvironmentRecord))
            {
                throw new InvalidOperationException("Block.BlockDeclarationInstantiation: env must be declarative");
            }
            var declarations = code.LexicallyScopedDeclarations();

            foreach (var d in declarations)
            {
                foreach (var dn in d.BoundNames())
                {
                    if (d.IsConstantDeclaration())
                    {
                        envRec.CreateImmutableBinding(dn, true);
                    }
                    else
                    {
                        envRec.CreateMutableBinding(dn, false);
                    }
                }
                if (d is FunctionDeclaration functionDeclaration)
                {
                    var fn = d.BoundNames()[0];
                    var fo = functionDeclaration.InstantiateFunctionObject(env);
                    envRec.InitializeBinding(fn, fo);
                }
            }
        }