using Jint.Native; using Jint.Native.Object; using Jint.Runtime.Environments; using Environment = Jint.Runtime.Environments.Environment; namespace Jint.Runtime.Debugger; /// /// Scope information, bindings, and values for a single scope in the scope chain /// public sealed class DebugScope { private readonly Environment _record; private string[]? _bindingNames; internal DebugScope(DebugScopeType type, Environment record, bool isTopLevel) { ScopeType = type; _record = record; BindingObject = record is ObjectEnvironment objEnv ? objEnv._bindingObject : null; IsTopLevel = isTopLevel; } /// /// The type of scope. Scope types are the same as defined by Chrome devtools protocol. /// public DebugScopeType ScopeType { get; } /// /// For block scopes, indicates whether this scope is at the top level of a containing function. /// /// /// Block scopes at the top level of a function are combined with Local scope in Chromium. /// This property facilitates implementing the same "flattening" in e.g. a UI. Because empty scopes are excluded in the scope chain, /// top level cannot be determined from the scope chain order alone. /// public bool IsTopLevel { get; } /// /// Names of all bindings in the scope. /// public IReadOnlyList BindingNames => _bindingNames ??= _record.GetAllBindingNames(); /// /// Binding object for ObjectEnvironmentRecords - that is, Global scope and With scope. Null for other scopes. /// /// /// This is mainly useful as an optimization for devtools, allowing the BindingObject to be serialized directly rather than /// building a new transient object in response to e.g. Runtime.getProperties. /// public ObjectInstance? BindingObject { get; } /// /// Retrieves the value of a specific binding. Note that some bindings (e.g. uninitialized let/const) may return null. /// /// Binding name /// Value of the binding public JsValue? GetBindingValue(string name) { _record.TryGetBinding(new Environment.BindingName(name), strict: false, out var result); return result; } /// /// Sets the value of an existing binding. /// /// Binding name /// New value of the binding public void SetBindingValue(string name, JsValue value) { _record.SetMutableBinding(name, value, strict: true); } }