Skip to content

Commit

Permalink
Remove LexicalEnvironment (#901)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma committed May 19, 2021
1 parent b29573b commit 978d319
Show file tree
Hide file tree
Showing 34 changed files with 242 additions and 227 deletions.
84 changes: 44 additions & 40 deletions Jint/Engine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ public Engine(Action<Engine, Options> options)
Object._prototype = Function.PrototypeObject;

// create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
GlobalEnvironment = LexicalEnvironment.NewGlobalEnvironment(this, Global);
GlobalEnvironment = JintEnvironment.NewGlobalEnvironment(this, Global, Global);

// create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
EnterExecutionContext(GlobalEnvironment, GlobalEnvironment);
Expand All @@ -213,7 +213,7 @@ public Engine(Action<Engine, Options> options)
Options.Apply(this);
}

internal LexicalEnvironment GlobalEnvironment { get; }
internal GlobalEnvironmentRecord GlobalEnvironment { get; }
public GlobalObject Global { get; }
public ObjectConstructor Object { get; }
public FunctionConstructor Function { get; }
Expand Down Expand Up @@ -274,8 +274,8 @@ internal Options Options
public DebugHandler DebugHandler => _debugHandler ??= new DebugHandler(this);

public ExecutionContext EnterExecutionContext(
LexicalEnvironment lexicalEnvironment,
LexicalEnvironment variableEnvironment)
EnvironmentRecord lexicalEnvironment,
EnvironmentRecord variableEnvironment)
{
var context = new ExecutionContext(
lexicalEnvironment,
Expand All @@ -285,6 +285,12 @@ internal Options Options
return context;
}

internal ExecutionContext EnterExecutionContext(ExecutionContext context)
{
_executionContexts.Push(context);
return context;
}

public Engine SetValue(JsValue name, Delegate value)
{
Global.FastAddProperty(name, new DelegateWrapper(this, value), true, false, true);
Expand Down Expand Up @@ -791,26 +797,26 @@ public JsValue GetValue(JsValue scope, JsValue property)
/// <summary>
/// https://tc39.es/ecma262/#sec-resolvebinding
/// </summary>
internal Reference ResolveBinding(string name, LexicalEnvironment env = null)
internal Reference ResolveBinding(string name, EnvironmentRecord env = null)
{
env ??= ExecutionContext.LexicalEnvironment;
return GetIdentifierReference(env, name, StrictModeScope.IsStrictModeCode);
}

private Reference GetIdentifierReference(LexicalEnvironment env, string name, bool strict)
private Reference GetIdentifierReference(EnvironmentRecord env, string name, bool strict)
{
if (env is null)
{
return new Reference(JsValue.Undefined, name, strict);
}

var envRec = env._record;
var envRec = env;
if (envRec.HasBinding(name))
{
return new Reference(envRec, name, strict);
}

return GetIdentifierReference(env._outer, name, strict);
return GetIdentifierReference(env._outerEnv, name, strict);
}

/// <summary>
Expand All @@ -837,10 +843,8 @@ internal JsValue ResolveThisBinding()
/// </summary>
private void GlobalDeclarationInstantiation(
Script script,
LexicalEnvironment env)
GlobalEnvironmentRecord env)
{
var envRec = (GlobalEnvironmentRecord) env._record;

var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
var functionDeclarations = hoistingScope._functionDeclarations;
var varDeclarations = hoistingScope._variablesDeclarations;
Expand All @@ -858,7 +862,7 @@ internal JsValue ResolveThisBinding()
var fn = d.Id.Name;
if (!declaredFunctionNames.Contains(fn))
{
var fnDefinable = envRec.CanDeclareGlobalFunction(fn);
var fnDefinable = env.CanDeclareGlobalFunction(fn);
if (!fnDefinable)
{
ExceptionHelper.ThrowTypeError(this);
Expand All @@ -882,14 +886,14 @@ internal JsValue ResolveThisBinding()
{
var vn = boundNames[j];

if (envRec.HasLexicalDeclaration(vn))
if (env.HasLexicalDeclaration(vn))
{
ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{vn}' has already been declared");
}

if (!declaredFunctionNames.Contains(vn))
{
var vnDefinable = envRec.CanDeclareGlobalVar(vn);
var vnDefinable = env.CanDeclareGlobalVar(vn);
if (!vnDefinable)
{
ExceptionHelper.ThrowTypeError(this);
Expand All @@ -911,20 +915,20 @@ internal JsValue ResolveThisBinding()
for (var j = 0; j < boundNames.Count; j++)
{
var dn = boundNames[j];
if (envRec.HasVarDeclaration(dn)
|| envRec.HasLexicalDeclaration(dn)
|| envRec.HasRestrictedGlobalProperty(dn))
if (env.HasVarDeclaration(dn)
|| env.HasLexicalDeclaration(dn)
|| env.HasRestrictedGlobalProperty(dn))
{
ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{dn}' has already been declared");
}

if (d.Kind == VariableDeclarationKind.Const)
{
envRec.CreateImmutableBinding(dn, strict: true);
env.CreateImmutableBinding(dn, strict: true);
}
else
{
envRec.CreateMutableBinding(dn, canBeDeleted: false);
env.CreateMutableBinding(dn, canBeDeleted: false);
}
}
}
Expand All @@ -934,19 +938,19 @@ internal JsValue ResolveThisBinding()
{
var fn = f.Id!.Name;

if (envRec.HasLexicalDeclaration(fn))
if (env.HasLexicalDeclaration(fn))
{
ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{fn}' has already been declared");
}

var fo = Function.InstantiateFunctionObject(f, env);
envRec.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: false);
env.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: false);
}

for (var i = 0; i < declaredVarNames.Count; i++)
{
var vn = declaredVarNames[i];
envRec.CreateGlobalVarBinding(vn, canBeDeleted: false);
env.CreateGlobalVarBinding(vn, canBeDeleted: false);
}
}

Expand All @@ -956,11 +960,11 @@ internal JsValue ResolveThisBinding()
internal ArgumentsInstance FunctionDeclarationInstantiation(
FunctionInstance functionInstance,
JsValue[] argumentsList,
LexicalEnvironment env)
EnvironmentRecord env)
{
var func = functionInstance._functionDefinition;

var envRec = (FunctionEnvironmentRecord) env._record;
var envRec = (FunctionEnvironmentRecord) env;
var strict = StrictModeScope.IsStrictModeCode;

var configuration = func.Initialize(this, functionInstance);
Expand Down Expand Up @@ -1010,7 +1014,7 @@ internal JsValue ResolveThisBinding()
// Else,
// Perform ? IteratorBindingInitialization for formals with iteratorRecord and env as arguments.

LexicalEnvironment varEnv;
EnvironmentRecord varEnv;
DeclarativeEnvironmentRecord varEnvRec;
if (!hasParameterExpressions)
{
Expand All @@ -1028,8 +1032,8 @@ internal JsValue ResolveThisBinding()
{
// NOTE: A separate Environment Record is needed to ensure that closures created by expressions
// in the formal parameter list do not have visibility of declarations in the function body.
varEnv = LexicalEnvironment.NewDeclarativeEnvironment(this, env);
varEnvRec = (DeclarativeEnvironmentRecord) varEnv._record;
varEnv = JintEnvironment.NewDeclarativeEnvironment(this, env);
varEnvRec = (DeclarativeEnvironmentRecord) varEnv;

UpdateVariableEnvironment(varEnv);

Expand All @@ -1044,10 +1048,10 @@ internal JsValue ResolveThisBinding()
// NOTE: Annex B.3.3.1 adds additional steps at this point.
// A https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation

LexicalEnvironment lexEnv;
EnvironmentRecord lexEnv;
if (!strict)
{
lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(this, varEnv);
lexEnv = JintEnvironment.NewDeclarativeEnvironment(this, varEnv);
// NOTE: Non-strict functions use a separate lexical Environment Record for top-level lexical declarations
// so that a direct eval can determine whether any var scoped declarations introduced by the eval code conflict
// with pre-existing top-level lexically scoped declarations. This is not needed for strict functions
Expand All @@ -1058,7 +1062,7 @@ internal JsValue ResolveThisBinding()
lexEnv = varEnv;
}

var lexEnvRec = lexEnv._record;
var lexEnvRec = lexEnv;

UpdateLexicalEnvironment(lexEnv);

Expand All @@ -1077,7 +1081,7 @@ internal JsValue ResolveThisBinding()

private void InitializeFunctions(
LinkedList<FunctionDeclaration> functionsToInitialize,
LexicalEnvironment lexEnv,
EnvironmentRecord lexEnv,
DeclarativeEnvironmentRecord varEnvRec)
{
foreach (var f in functionsToInitialize)
Expand Down Expand Up @@ -1129,14 +1133,14 @@ private ArgumentsInstance CreateUnmappedArgumentsObject(JsValue[] argumentsList)
/// </summary>
internal void EvalDeclarationInstantiation(
Script script,
LexicalEnvironment varEnv,
LexicalEnvironment lexEnv,
EnvironmentRecord varEnv,
EnvironmentRecord lexEnv,
bool strict)
{
var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);

var lexEnvRec = (DeclarativeEnvironmentRecord) lexEnv._record;
var varEnvRec = varEnv._record;
var lexEnvRec = (DeclarativeEnvironmentRecord) lexEnv;
var varEnvRec = varEnv;

if (!strict && hoistingScope._variablesDeclarations != null)
{
Expand All @@ -1156,9 +1160,9 @@ private ArgumentsInstance CreateUnmappedArgumentsObject(JsValue[] argumentsList)
}

var thisLex = lexEnv;
while (thisLex != varEnv)
while (!ReferenceEquals(thisLex, varEnv))
{
var thisEnvRec = thisLex._record;
var thisEnvRec = thisLex;
if (!(thisEnvRec is ObjectEnvironmentRecord))
{
ref readonly var nodes = ref hoistingScope._variablesDeclarations;
Expand All @@ -1173,7 +1177,7 @@ private ArgumentsInstance CreateUnmappedArgumentsObject(JsValue[] argumentsList)
}
}

thisLex = thisLex._outer;
thisLex = thisLex._outerEnv;
}
}

Expand Down Expand Up @@ -1295,13 +1299,13 @@ private ArgumentsInstance CreateUnmappedArgumentsObject(JsValue[] argumentsList)
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void UpdateLexicalEnvironment(LexicalEnvironment newEnv)
internal void UpdateLexicalEnvironment(EnvironmentRecord newEnv)
{
_executionContexts.ReplaceTopLexicalEnvironment(newEnv);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal void UpdateVariableEnvironment(LexicalEnvironment newEnv)
internal void UpdateVariableEnvironment(EnvironmentRecord newEnv)
{
_executionContexts.ReplaceTopVariableEnvironment(newEnv);
}
Expand Down
4 changes: 2 additions & 2 deletions Jint/EsprimaExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,11 +179,11 @@ internal static void GetBoundNames(this Node? parameter, List<string> target)
this Expression? expression,
Engine engine,
JsValue value,
LexicalEnvironment env)
EnvironmentRecord env)
{
if (expression is Identifier identifier)
{
var catchEnvRecord = (DeclarativeEnvironmentRecord) env._record;
var catchEnvRecord = (DeclarativeEnvironmentRecord) env;
catchEnvRecord.CreateMutableBindingAndInitialize(identifier.Name, canBeDeleted: false, value);
}
else if (expression is BindingPattern bindingPattern)
Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Array/ArrayInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,7 @@ internal void CopyValues(ArrayInstance source, uint sourceStartIndex, uint targe
? sourceDense[i]
: source.GetProperty(i);

dense[targetStartIndex + j] = sourcePropertyDescriptor?._value != null
dense[targetStartIndex + j] = sourcePropertyDescriptor?._value is not null
? new PropertyDescriptor(sourcePropertyDescriptor._value, PropertyFlag.ConfigurableEnumerableWritable)
: null;
}
Expand Down
8 changes: 4 additions & 4 deletions Jint/Native/Function/ClassDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,16 @@ static MethodDefinition CreateConstructorMethodDefinition(string source)
/// </summary>
public ScriptFunctionInstance BuildConstructor(
Engine engine,
LexicalEnvironment env)
EnvironmentRecord env)
{
// A class definition is always strict mode code.
using var _ = (new StrictModeScope(true, true));

var classScope = LexicalEnvironment.NewDeclarativeEnvironment(engine, env);
var classScope = JintEnvironment.NewDeclarativeEnvironment(engine, env);

if (_className is not null)
{
classScope._record.CreateImmutableBinding(_className, true);
classScope.CreateImmutableBinding(_className, true);
}

ObjectInstance? protoParent = null;
Expand Down Expand Up @@ -158,7 +158,7 @@ static MethodDefinition CreateConstructorMethodDefinition(string source)

if (_className is not null)
{
classScope._record.InitializeBinding(_className, F);
classScope.InitializeBinding(_className, F);
}

return F;
Expand Down
8 changes: 4 additions & 4 deletions Jint/Native/Function/EvalFunctionInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,16 @@ public JsValue PerformEval(JsValue x, object callerRealm, bool strictCaller, boo

using (new StrictModeScope(strictEval))
{
LexicalEnvironment lexEnv;
LexicalEnvironment varEnv;
EnvironmentRecord lexEnv;
EnvironmentRecord varEnv;
if (direct)
{
lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
varEnv = ctx.VariableEnvironment;
}
else
{
lexEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, Engine.GlobalEnvironment);
lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, Engine.GlobalEnvironment);
varEnv = Engine.GlobalEnvironment;
}

Expand Down
2 changes: 1 addition & 1 deletion Jint/Native/Function/FunctionConstructor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
/// <summary>
/// https://tc39.es/ecma262/#sec-runtime-semantics-instantiatefunctionobject
/// </summary>
internal FunctionInstance InstantiateFunctionObject(FunctionDeclaration functionDeclaration, LexicalEnvironment env)
internal FunctionInstance InstantiateFunctionObject(FunctionDeclaration functionDeclaration, EnvironmentRecord env)
{
var functionObject = new ScriptFunctionInstance(
Engine,
Expand Down

0 comments on commit 978d319

Please sign in to comment.