private Completion GlobalDeclarationInstantiation(LexicalEnvironment env) { var envRecAbstract = env.EnvironmentRecord; if (!(envRecAbstract is GlobalEnvironmentRecord envRec)) { throw new InvalidOperationException("Spec 15.1.11 step 2"); } var lexNames = scriptBody.LexicallyDeclaredNames(); var varNames = scriptBody.VarDeclaredNames(); foreach (var name in lexNames) { if (envRec.HasVarDeclaration(name)) { return(Completion.ThrowSyntaxError($"variable {name} is already declared")); } if (envRec.HasLexicalDeclaration(name)) { return(Completion.ThrowSyntaxError($"variable {name} is already declared")); } var hasRestrictedGlobal = envRec.HasRestrictedGlobalProperty(name); if (hasRestrictedGlobal.IsAbrupt()) { return(hasRestrictedGlobal); } if (hasRestrictedGlobal.Other == true) { return(Completion.ThrowSyntaxError($"variable {name} is already a restricted global")); } } foreach (var name in varNames) { if (envRec.HasLexicalDeclaration(name)) { return(Completion.ThrowSyntaxError($"variable {name} is already declared")); } } var varDeclarations = scriptBody.VarScopedDeclarations(); var functionsToInitialize = new List <FunctionDeclaration>(); var declaredFunctionNames = new List <string>(); foreach (var d in varDeclarations.Reverse()) { if (d is FunctionDeclaration f) { var fn = f.BoundNames()[0]; if (!declaredFunctionNames.Contains(fn)) { var fnDefinable = envRec.CanDeclareGlobalFunction(fn); if (fnDefinable.IsAbrupt()) { return(fnDefinable); } if (!fnDefinable.Other) { return(Completion.ThrowTypeError($"function {fn} cannot be declared.")); } declaredFunctionNames.Add(fn); functionsToInitialize.Insert(0, f); } } } var declaredVarNames = new List <string>(); foreach (var d in varDeclarations) { string vn; if (d is VariableDeclaration v) { vn = v.name; } else if (d is ForBinding f) { vn = f.name; } else { continue; } if (!declaredVarNames.Contains(vn)) { var vnDefinable = envRec.CanDeclareGlobalVar(vn); if (vnDefinable.IsAbrupt()) { return(vnDefinable); } if (!vnDefinable.Other) { return(Completion.ThrowTypeError($"variable {vn} cannot be declared.")); } declaredVarNames.Add(vn); } } //TODO Annex B.3.3.2 var lexDeclarations = scriptBody.LexicallyScopedDeclarations(); foreach (var d in lexDeclarations) { foreach (var dn in d.BoundNames()) { Completion comp; if (d.IsConstantDeclaration()) { comp = envRec.CreateImmutableBinding(dn, true); } else { comp = envRec.CreateMutableBinding(dn, false); } if (comp.IsAbrupt()) { return(comp); } } } foreach (var f in functionsToInitialize) { var fn = f.BoundNames()[0]; var fo = f.InstantiateFunctionObject(env); var comp = envRec.CreateGlobalFunctionBinding(fn, fo, false); if (comp.IsAbrupt()) { return(comp); } } foreach (var vn in declaredVarNames) { var comp = envRec.CreateGlobalVarBinding(vn, false); if (comp.IsAbrupt()) { return(comp); } } return(Completion.NormalCompletion()); }