#nullable enable using System.Diagnostics; using Jint.Native; namespace Jint.Runtime.Environments { /// /// Base implementation of an Environment Record /// https://tc39.es/ecma262/#sec-environment-records /// public abstract class EnvironmentRecord : JsValue { protected internal readonly Engine _engine; protected internal EnvironmentRecord? _outerEnv; protected EnvironmentRecord(Engine engine) : base(InternalTypes.ObjectEnvironmentRecord) { _engine = engine; } /// /// Determines if an environment record has a binding for an identifier. /// /// The identifier of the binding /// true if it does and false if it does not. public abstract bool HasBinding(string name); internal abstract bool TryGetBinding( in BindingName name, bool strict, out Binding binding, out JsValue value); /// /// Creates a new mutable binding in an environment record. /// /// The identifier of the binding. /// true if the binding may be subsequently deleted. public abstract void CreateMutableBinding(string name, bool canBeDeleted = false); /// /// Creates a new but uninitialized immutable binding in an environment record. /// /// The identifier of the binding. /// false if the binding may used before it's been initialized. public abstract void CreateImmutableBinding(string name, bool strict = true); /// /// Set the value of an already existing but uninitialized binding in an Environment Record. /// /// The text of the bound name /// The value for the binding. public abstract void InitializeBinding(string name, JsValue value); /// /// Sets the value of an already existing mutable binding in an environment record. /// /// The identifier of the binding /// The value of the binding. /// The identify strict mode references. public abstract void SetMutableBinding(string name, JsValue value, bool strict); internal abstract void SetMutableBinding(in BindingName name, JsValue value, bool strict); /// /// Returns the value of an already existing binding from an environment record. /// /// The identifier of the binding /// The identify strict mode references. /// The value of an already existing binding from an environment record. public abstract JsValue GetBindingValue(string name, bool strict); /// /// Returns the value of an already existing binding from an environment record. Unlike /// this does not throw an exception for uninitialized bindings, but instead returns false and sets to null. /// /// The identifier of the binding /// Strict mode /// The value of an already existing binding from an environment record. /// True if the value is initialized, otherwise false. /// This is used for debugger inspection. Note that this will currently still throw if the binding cannot be retrieved (e.g. because it doesn't exist). internal abstract bool TryGetBindingValue(string name, bool strict, out JsValue value); /// /// Delete a binding from an environment record. The String value N is the text of the bound name If a binding for N exists, remove the binding and return true. If the binding exists but cannot be removed return false. If the binding does not exist return true. /// /// The identifier of the binding /// true if the deletion is successfull. public abstract bool DeleteBinding(string name); public abstract bool HasThisBinding(); public abstract bool HasSuperBinding(); public abstract JsValue WithBaseObject(); /// /// Returns an array of all the defined binding names /// /// The array of all defined bindings internal abstract string[] GetAllBindingNames(); public override object ToObject() { ExceptionHelper.ThrowNotSupportedException(); return null; } public override bool Equals(JsValue other) { ExceptionHelper.ThrowNotSupportedException(); return false; } public abstract JsValue GetThisBinding(); public JsValue? NewTarget { get; protected set; } /// /// Helper to cache JsString/Key when environments use different lookups. /// [DebuggerDisplay("\"{Key.Name}\"")] internal readonly struct BindingName { public readonly Key Key; public readonly JsString StringValue; public BindingName(string value) { Key = (Key) value; StringValue = JsString.Create(value); } } } }