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); } }
public Continuation(Continuation cont, LexicalEnvironment envt, object evalStack, Template template, uint pc) { CONT = cont; ENVT = envt; EVAL_STACK = evalStack; TEMPLATE = template; PC = pc; }
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); }
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); }
/// <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(); } } }
public static void ExecuteResource(LexicalEnvironment env, string resourceFile) { ExecuteResource(new Statistics(), Assembly.GetCallingAssembly(), env, resourceFile); }
/// <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); } }
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); } } }
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); } } } }
/// <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); }
public Closure(LexicalEnvironment env, IEnumerable <ArgBody> argBodies) { this.env = env; this.argBodies = argBodies; }
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()); }
public FunctionShim(Engine engine, string[] parameters, LexicalEnvironment scope) : base(engine, parameters, scope, false) { }
/// <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; } }
/// <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 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)); }
public JavaScriptEngine() { _engine = new Engine(); _engine.SetValue("console", new ConsoleInstance(_engine)); _variable = LexicalEnvironment.NewObjectEnvironment(_engine, _engine.Global, null, false); }
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); } }
protected abstract JsValue CallInternal(LexicalEnvironment env);
/// <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); } }
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); }
public JsCompiledFunction(LexicalEnvironment lexEnv, string[] parameters) : base(lexEnv) { Parameters = parameters; }
public FunctionShim(JSEngine engine, string[] parameters, LexicalEnvironment scope) : base(engine, parameters, scope, false) { }
internal void UpdateLexicalEnvironment(LexicalEnvironment newEnv) { _executionContexts.ReplaceTopLexicalEnvironment(newEnv); }
public override Continuation Evaluate(Continuation c, LexicalEnvironment env, Datum args) { return(c.PushResult(evaluate(c, env, args))); }
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); }
public ExecutionContext EnterExecutionContext(LexicalEnvironment lexicalEnvironment, LexicalEnvironment variableEnvironment, JsValue thisBinding) { var executionContext = new ExecutionContext { LexicalEnvironment = lexicalEnvironment, VariableEnvironment = variableEnvironment, ThisBinding = thisBinding }; _executionContexts.Push(executionContext); return executionContext; }
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); } } }