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);
}
}