Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internalize Environment services and use Key as name #1735

Merged
merged 3 commits into from
Jan 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 1 addition & 3 deletions Jint.Tests.PublicInterface/RavenApiUsageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,7 @@ public void CanBuildCustomScriptFunctionInstance()
var functionObject = new ScriptFunction(
engine,
functionExp,
engine.Advanced.CreateDeclarativeEnvironment(),
strict: false
);
strict: false);

Assert.NotNull(functionObject);
}
Expand Down
1 change: 0 additions & 1 deletion Jint.Tests/Runtime/InteropTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using Jint.Native;
using Jint.Native.Object;
using Jint.Native.Symbol;
using Jint.Runtime;
using Jint.Runtime.Interop;
Expand Down
10 changes: 0 additions & 10 deletions Jint/Engine.Advanced.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Jint.Native.Promise;
using Jint.Runtime.Environments;
using Environment = Jint.Runtime.Environments.Environment;

namespace Jint;

Expand Down Expand Up @@ -51,14 +49,6 @@ public void ProcessTasks()
_engine.RunAvailableContinuations();
}

/// <summary>
/// Creates a new declarative environment that has current lexical environment as outer scope.
/// </summary>
public Environment CreateDeclarativeEnvironment()
{
return JintEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment);
}

/// <summary>
/// EXPERIMENTAL! Subject to change.
///
Expand Down
4 changes: 3 additions & 1 deletion Jint/Engine.Ast.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Runtime.InteropServices;
using Esprima;
using Esprima.Ast;
using Jint.Native;
Expand Down Expand Up @@ -126,7 +127,8 @@ internal static void GatherLexNames(HoistingScope scope, List<CachedLexicalName>
}
}

internal readonly record struct CachedLexicalName(string Name, bool Constant);
[StructLayout(LayoutKind.Auto)]
internal readonly record struct CachedLexicalName(Key Name, bool Constant);

public HoistingScope Scope { get; }
public List<string> VarNames { get; }
Expand Down
19 changes: 9 additions & 10 deletions Jint/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -942,10 +942,9 @@ internal JsValue ResolveThisBinding()
{
var hoistingScope = script.GetHoistingScope();
var functionDeclarations = hoistingScope._functionDeclarations;
var lexDeclarations = hoistingScope._lexicalDeclarations;

var functionToInitialize = new List<JintFunctionDefinition>();
var declaredFunctionNames = new HashSet<string>(StringComparer.Ordinal);
var declaredFunctionNames = new HashSet<Key>();
var declaredVarNames = new List<string>();

var realm = Realm;
Expand All @@ -955,7 +954,7 @@ internal JsValue ResolveThisBinding()
for (var i = functionDeclarations.Count - 1; i >= 0; i--)
{
var d = functionDeclarations[i];
var fn = d.Id!.Name;
var fn = (Key) d.Id!.Name;
if (!declaredFunctionNames.Contains(fn))
{
var fnDefinable = env.CanDeclareGlobalFunction(fn);
Expand All @@ -973,7 +972,7 @@ internal JsValue ResolveThisBinding()
var varNames = script.GetVarNames(hoistingScope);
for (var j = 0; j < varNames.Count; j++)
{
var vn = varNames[j];
Key vn = varNames[j];
if (env.HasLexicalDeclaration(vn))
{
ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{vn}' has already been declared");
Expand Down Expand Up @@ -1144,7 +1143,7 @@ internal JsValue ResolveThisBinding()
{
for (var j = 0; j < d.BoundNames.Count; j++)
{
var dn = d.BoundNames[j];
Key dn = d.BoundNames[j];
if (d.IsConstantDeclaration)
{
lexEnv.CreateImmutableBinding(dn, strict: true);
Expand Down Expand Up @@ -1260,14 +1259,14 @@ private JsArguments CreateUnmappedArgumentsObject(JsValue[] argumentsList)

var functionDeclarations = hoistingScope._functionDeclarations;
var functionsToInitialize = new LinkedList<JintFunctionDefinition>();
var declaredFunctionNames = new HashSet<string>(StringComparer.Ordinal);
var declaredFunctionNames = new HashSet<Key>();

if (functionDeclarations != null)
{
for (var i = functionDeclarations.Count - 1; i >= 0; i--)
{
var d = functionDeclarations[i];
var fn = d.Id!.Name;
Key fn = d.Id!.Name;
if (!declaredFunctionNames.Contains(fn))
{
if (varEnvRec is GlobalEnvironment ger)
Expand All @@ -1286,7 +1285,7 @@ private JsArguments CreateUnmappedArgumentsObject(JsValue[] argumentsList)
}

var boundNames = new List<string>();
var declaredVarNames = new List<string>();
var declaredVarNames = new List<Key>();
var variableDeclarations = hoistingScope._variablesDeclarations;
var variableDeclarationsCount = variableDeclarations?.Count;
for (var i = 0; i < variableDeclarationsCount; i++)
Expand Down Expand Up @@ -1322,7 +1321,7 @@ private JsArguments CreateUnmappedArgumentsObject(JsValue[] argumentsList)
d.GetBoundNames(boundNames);
for (var j = 0; j < boundNames.Count; j++)
{
var dn = boundNames[j];
Key dn = boundNames[j];
if (d.IsConstantDeclaration())
{
lexEnvRec.CreateImmutableBinding(dn, strict: true);
Expand All @@ -1336,7 +1335,7 @@ private JsArguments CreateUnmappedArgumentsObject(JsValue[] argumentsList)

foreach (var f in functionsToInitialize)
{
var fn = f.Name!;
Key fn = f.Name!;
var fo = realm.Intrinsics.Function.InstantiateFunctionObject(f, lexEnv, privateEnv);
if (varEnvRec is GlobalEnvironment ger)
{
Expand Down
8 changes: 4 additions & 4 deletions Jint/Key.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace Jint
[DebuggerDisplay("{" + nameof(Name) + "}")]
internal readonly struct Key : IEquatable<Key>
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private Key(string name)
{
Name = name;
Expand All @@ -19,11 +20,10 @@ private Key(string name)
internal readonly string Name;
internal readonly int HashCode;

public static implicit operator Key(string name)
{
return new Key(name);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator Key(string name) => new(name);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator string(Key key) => key.Name;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Argument/JsArguments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Jint.Native.Argument
public sealed class JsArguments : ObjectInstance
{
// cache property container for array iteration for less allocations
private static readonly ThreadLocal<HashSet<string>> _mappedNamed = new(() => new HashSet<string>(StringComparer.Ordinal));
private static readonly ThreadLocal<HashSet<Key>> _mappedNamed = new(() => []);

private Function.Function _func = null!;
private Key[] _names = null!;
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Function/Function.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public abstract partial class Function : ObjectInstance, ICallable
protected internal PropertyDescriptor? _length;
internal PropertyDescriptor? _nameDescriptor;

protected internal Environment? _environment;
internal Environment? _environment;
internal readonly JintFunctionDefinition _functionDefinition = null!;
internal readonly FunctionThisMode _thisMode;
internal JsValue _homeObject = Undefined;
Expand Down
3 changes: 1 addition & 2 deletions Jint/Native/Function/ScriptFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ public sealed class ScriptFunction : Function, IConstructor
public ScriptFunction(
Engine engine,
IFunction functionDeclaration,
Environment env,
bool strict,
ObjectInstance? proto = null)
: this(
engine,
new JintFunctionDefinition(functionDeclaration),
env,
JintEnvironment.NewDeclarativeEnvironment(engine, engine.ExecutionContext.LexicalEnvironment),
strict ? FunctionThisMode.Strict : FunctionThisMode.Global,
proto)
{
Expand Down
20 changes: 1 addition & 19 deletions Jint/Native/Global/GlobalObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -673,19 +673,7 @@ internal bool HasProperty(Key property)
return GetOwnProperty(property) != PropertyDescriptor.Undefined;
}

internal PropertyDescriptor GetProperty(Key property) => GetOwnProperty(property);

internal bool DefinePropertyOrThrow(Key property, PropertyDescriptor desc)
{
if (!DefineOwnProperty(property, desc))
{
ExceptionHelper.ThrowTypeError(_realm);
}

return true;
}

internal bool DefineOwnProperty(Key property, PropertyDescriptor desc)
private bool DefineOwnProperty(Key property, PropertyDescriptor desc)
{
var current = GetOwnProperty(property);
if (current == desc)
Expand Down Expand Up @@ -752,11 +740,5 @@ internal bool SetFromMutableBinding(Key property, JsValue value, bool strict)

return true;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void SetOwnProperty(Key property, PropertyDescriptor desc)
{
SetProperty(property, desc);
}
}
}
1 change: 0 additions & 1 deletion Jint/Native/Promise/JsPromise.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Jint.Native.Function;
using Jint.Native.Object;
using Jint.Runtime;
using Jint.Runtime.Descriptors;
Expand Down
1 change: 0 additions & 1 deletion Jint/Native/ShadowRealm/ShadowRealm.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Esprima;
using Esprima.Ast;
using Esprima.Utils;
using Jint.Native.Function;
using Jint.Native.Object;
using Jint.Native.Promise;
using Jint.Runtime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ private JsValue DoGet(JsValue n)

private void DoSet(JsValue n, JsValue o)
{
_env.SetMutableBinding(_name.Key.Name, o, true);
_env.SetMutableBinding(_name.Key, o, true);
}
}
}
44 changes: 17 additions & 27 deletions Jint/Runtime/Environments/DeclarativeEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,9 @@ public DeclarativeEnvironment(Engine engine, bool catchEnvironment = false) : ba
_catchEnvironment = catchEnvironment;
}

public sealed override bool HasBinding(string name)
{
return _dictionary is not null && _dictionary.ContainsKey(name);
}
internal sealed override bool HasBinding(BindingName name) => HasBinding(name.Key);

internal sealed override bool HasBinding(BindingName name)
{
return _dictionary is not null &&_dictionary.ContainsKey(name.Key);
}
internal sealed override bool HasBinding(Key name) => _dictionary is not null && _dictionary.ContainsKey(name);

internal override bool TryGetBinding(
BindingName name,
Expand All @@ -53,39 +47,35 @@ internal void CreateImmutableBindingAndInitialize(Key name, bool strict, JsValue
_dictionary[name] = new Binding(value, canBeDeleted: false, mutable: false, strict);
}

public sealed override void CreateMutableBinding(string name, bool canBeDeleted = false)
internal sealed override void CreateMutableBinding(Key name, bool canBeDeleted = false)
{
_dictionary ??= new HybridDictionary<Binding>();
_dictionary[name] = new Binding(null!, canBeDeleted, mutable: true, strict: false);
}

public sealed override void CreateImmutableBinding(string name, bool strict = true)
internal sealed override void CreateImmutableBinding(Key name, bool strict = true)
{
_dictionary ??= new HybridDictionary<Binding>();
_dictionary[name] = new Binding(null!, canBeDeleted: false, mutable: false, strict);
}

public sealed override void InitializeBinding(string name, JsValue value)
internal sealed override void InitializeBinding(Key name, JsValue value)
{
_dictionary ??= new HybridDictionary<Binding>();
_dictionary.SetOrUpdateValue(name, static (current, value) => current.ChangeValue(value), value);
}

internal sealed override void SetMutableBinding(BindingName name, JsValue value, bool strict)
{
SetMutableBinding(name.Key.Name, value, strict);
}
internal sealed override void SetMutableBinding(BindingName name, JsValue value, bool strict) => SetMutableBinding(name.Key, value, strict);

public sealed override void SetMutableBinding(string name, JsValue value, bool strict)
internal sealed override void SetMutableBinding(Key name, JsValue value, bool strict)
{
var key = (Key) name;
if (_dictionary is null || !_dictionary.TryGetValue(key, out var binding))
if (_dictionary is null || !_dictionary.TryGetValue(name, out var binding))
{
if (strict)
{
ExceptionHelper.ThrowReferenceNameError(_engine.Realm, name);
}
CreateMutableBindingAndInitialize(key, canBeDeleted: true, value);
CreateMutableBindingAndInitialize(name, canBeDeleted: true, value);
return;
}

Expand All @@ -102,7 +92,7 @@ public sealed override void SetMutableBinding(string name, JsValue value, bool s

if (binding.Mutable)
{
_dictionary[key] = binding.ChangeValue(value);
_dictionary[name] = binding.ChangeValue(value);
}
else
{
Expand All @@ -113,7 +103,7 @@ public sealed override void SetMutableBinding(string name, JsValue value, bool s
}
}

public override JsValue GetBindingValue(string name, bool strict)
internal override JsValue GetBindingValue(Key name, bool strict)
{
if (_dictionary is not null && _dictionary.TryGetValue(name, out var binding) && binding.IsInitialized())
{
Expand All @@ -130,7 +120,7 @@ private void ThrowUninitializedBindingError(string name)
ExceptionHelper.ThrowReferenceError(_engine.Realm, $"Cannot access '{name}' before initialization");
}

public sealed override bool DeleteBinding(string name)
internal sealed override bool DeleteBinding(Key name)
{
if (_dictionary is null || !_dictionary.TryGetValue(name, out var binding))
{
Expand All @@ -147,13 +137,13 @@ public sealed override bool DeleteBinding(string name)
return true;
}

public override bool HasThisBinding() => false;
internal override bool HasThisBinding() => false;

public override bool HasSuperBinding() => false;
internal override bool HasSuperBinding() => false;

public sealed override JsValue WithBaseObject() => Undefined;
internal sealed override JsValue WithBaseObject() => Undefined;

public sealed override bool HasBindings()
internal sealed override bool HasBindings()
{
return _dictionary?.Count > 0;
}
Expand All @@ -176,7 +166,7 @@ internal sealed override string[] GetAllBindingNames()
return keys;
}

public override JsValue GetThisBinding()
internal override JsValue GetThisBinding()
{
return Undefined;
}
Expand Down