123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- using System.Diagnostics;
- using System.Diagnostics.CodeAnalysis;
- using Jint.Native;
- namespace Jint.Runtime.Environments;
- /// <summary>
- /// Base implementation of an Environment Record
- /// https://tc39.es/ecma262/#sec-environment-records
- /// </summary>
- [DebuggerTypeProxy(typeof(EnvironmentDebugView))]
- internal abstract class Environment : JsValue
- {
- protected internal readonly Engine _engine;
- protected internal Environment? _outerEnv;
- protected Environment(Engine engine) : base(InternalTypes.ObjectEnvironmentRecord)
- {
- _engine = engine;
- }
- /// <summary>
- /// Determines if an environment record has a binding for an identifier.
- /// </summary>
- /// <param name="name">The identifier of the binding</param>
- /// <returns><c>true</c> if it does and <c>false</c> if it does not.</returns>
- internal abstract bool HasBinding(Key name);
- internal abstract bool HasBinding(BindingName name);
- internal abstract bool TryGetBinding(BindingName name, bool strict, [NotNullWhen(true)] out JsValue? value);
- /// <summary>
- /// Creates a new mutable binding in an environment record.
- /// </summary>
- /// <param name="name">The identifier of the binding.</param>
- /// <param name="canBeDeleted"><c>true</c> if the binding may be subsequently deleted.</param>
- internal abstract void CreateMutableBinding(Key name, bool canBeDeleted = false);
- /// <summary>
- /// Creates a new but uninitialized immutable binding in an environment record.
- /// </summary>
- /// <param name="name">The identifier of the binding.</param>
- /// <param name="strict"><c>false</c> if the binding may used before it's been initialized.</param>
- internal abstract void CreateImmutableBinding(Key name, bool strict = true);
- /// <summary>
- /// Set the value of an already existing but uninitialized binding in an Environment Record.
- /// </summary>
- /// <param name="name">The text of the bound name</param>
- /// <param name="value">The value for the binding.</param>
- /// <param name="hint">Disposal type hint</param>
- internal abstract void InitializeBinding(Key name, JsValue value, DisposeHint hint);
- /// <summary>
- /// Sets the value of an already existing mutable binding in an environment record.
- /// </summary>
- /// <param name="name">The identifier of the binding</param>
- /// <param name="value">The value of the binding.</param>
- /// <param name="strict">The identify strict mode references.</param>
- internal abstract void SetMutableBinding(Key name, JsValue value, bool strict);
- internal abstract void SetMutableBinding(BindingName name, JsValue value, bool strict);
- /// <summary>
- /// Returns the value of an already existing binding from an environment record.
- /// </summary>
- /// <param name="name">The identifier of the binding</param>
- /// <param name="strict">The identify strict mode references.</param>
- /// <return>The value of an already existing binding from an environment record.</return>
- internal abstract JsValue GetBindingValue(Key name, bool strict);
- /// <summary>
- /// 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.
- /// </summary>
- /// <param name="name">The identifier of the binding</param>
- /// <returns><true>true</true> if the deletion is successfull.</returns>
- internal abstract bool DeleteBinding(Key name);
- internal abstract bool HasThisBinding();
- internal abstract bool HasSuperBinding();
- internal abstract JsValue WithBaseObject();
- internal abstract bool HasBindings();
- /// <summary>
- /// Returns an array of all the defined binding names
- /// </summary>
- /// <returns>The array of all defined bindings</returns>
- internal abstract string[] GetAllBindingNames();
- public override object ToObject()
- {
- Throw.NotSupportedException();
- return null;
- }
- public override bool Equals(JsValue? other)
- {
- Throw.NotSupportedException();
- return false;
- }
- internal abstract JsValue GetThisBinding();
- internal JsValue? NewTarget { get; set; }
- internal virtual Completion DisposeResources(Completion c) => c;
- /// <summary>
- /// Helper to cache JsString/Key when environments use different lookups.
- /// </summary>
- [DebuggerDisplay("\"{Key.Name}\"")]
- internal sealed class BindingName
- {
- public readonly Key Key;
- public readonly JsString Value;
- public readonly JsValue? CalculatedValue;
- public BindingName(string value)
- {
- var key = (Key) value;
- Key = key;
- Value = JsString.Create(value);
- if (key == KnownKeys.Undefined)
- {
- CalculatedValue = Undefined;
- }
- }
- public BindingName(JsString value)
- {
- var key = (Key) value.ToString();
- Key = key;
- Value = value;
- if (key == KnownKeys.Undefined)
- {
- CalculatedValue = Undefined;
- }
- }
- }
- private sealed class EnvironmentDebugView
- {
- private readonly Environment _record;
- public EnvironmentDebugView(Environment record)
- {
- _record = record;
- }
- [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
- public KeyValuePair<JsValue, JsValue>[] Entries
- {
- get
- {
- var bindingNames = _record.GetAllBindingNames();
- var bindings = new KeyValuePair<JsValue, JsValue>[bindingNames.Length];
- var i = 0;
- foreach (var key in bindingNames)
- {
- bindings[i++] = new KeyValuePair<JsValue, JsValue>(key, _record.GetBindingValue(key, false));
- }
- return bindings;
- }
- }
- }
- }
|