using Jint.Native.Function; using Jint.Native.Generator; namespace Jint.Runtime.Environments; internal readonly struct ExecutionContext { internal ExecutionContext( IScriptOrModule? scriptOrModule, Environment lexicalEnvironment, Environment variableEnvironment, PrivateEnvironment? privateEnvironment, Realm realm, GeneratorInstance? generator = null, Function? function = null, ParserOptions? parserOptions = null) { ScriptOrModule = scriptOrModule; LexicalEnvironment = lexicalEnvironment; VariableEnvironment = variableEnvironment; PrivateEnvironment = privateEnvironment; Realm = realm; Function = function; Generator = generator; ParserOptions = parserOptions; } public readonly IScriptOrModule? ScriptOrModule; public readonly Environment LexicalEnvironment; public readonly Environment VariableEnvironment; public readonly PrivateEnvironment? PrivateEnvironment; public readonly Realm Realm; public readonly Function? Function; public readonly GeneratorInstance? Generator; public readonly ParserOptions? ParserOptions; public bool Suspended => Generator?._generatorState == GeneratorState.SuspendedYield; public ExecutionContext UpdateLexicalEnvironment(Environment lexicalEnvironment) { return new ExecutionContext(ScriptOrModule, lexicalEnvironment, VariableEnvironment, PrivateEnvironment, Realm, Generator, Function); } public ExecutionContext UpdateVariableEnvironment(Environment variableEnvironment) { return new ExecutionContext(ScriptOrModule, LexicalEnvironment, variableEnvironment, PrivateEnvironment, Realm, Generator, Function); } public ExecutionContext UpdatePrivateEnvironment(PrivateEnvironment? privateEnvironment) { return new ExecutionContext(ScriptOrModule, LexicalEnvironment, VariableEnvironment, privateEnvironment, Realm, Generator, Function); } public ExecutionContext UpdateGenerator(GeneratorInstance generator) { return new ExecutionContext(ScriptOrModule, LexicalEnvironment, VariableEnvironment, PrivateEnvironment, Realm, generator, Function); } /// /// https://tc39.es/ecma262/#sec-getthisenvironment /// internal Environment GetThisEnvironment() { // The loop will always terminate because the list of environments always // ends with the global environment which has a this binding. var lex = LexicalEnvironment; while (true) { if (lex is not null) { if (lex.HasThisBinding()) { return lex; } lex = lex._outerEnv; } } } internal GeneratorKind GetGeneratorKind() { if (Generator is null) { return GeneratorKind.NonGenerator; } // TODO If generator has an [[AsyncGeneratorState]] internal slot, return async. return GeneratorKind.Sync; } }