public static FunctionObject FunctionInitialize(FunctionObject f, FunctionCreateKind kind, FormalParameters parameters, FunctionStatementList body, LexicalEnvironment scope) { var len = parameters.ExpectedArgumentCount(); f.DefinePropertyOrThrow("length", new PropertyDescriptor(new NumberValue(len), false, false, true)); f.Environment = scope; f.FormalParameters = parameters; f.Code = body; if (kind == FunctionCreateKind.Arrow) { f.ThisMode = ThisMode.Lexical; } else if (f.Strict) { f.ThisMode = ThisMode.Strict; } else { f.ThisMode = ThisMode.Global; } return(f); }
private static Completion EvalDeclarationInstantiation(ScriptStatementList body, LexicalEnvironment varEnv, LexicalEnvironment lexEnv, bool strict) { var varNames = body.VarDeclaredNames(); var varDeclarations = body.VarScopedDeclarations(); var lexEnvRec = lexEnv.EnvironmentRecord; var varEnvRec = varEnv.EnvironmentRecord; if (!strict) { if (varEnvRec is GlobalEnvironmentRecord g) { foreach (var name in varNames) { if (g.HasLexicalDeclaration(name)) { return(Completion.ThrowSyntaxError("Spec 18.2.1.3 step 5ai1")); } } } LexicalEnvironment?thisLex = lexEnv; while (thisLex != varEnv) { var thisEnvRec = thisLex.EnvironmentRecord; if (!(thisEnvRec is ObjectEnvironmentRecord)) { foreach (var name in varNames) { if (thisEnvRec.HasBinding(name).Other) { return(Completion.ThrowSyntaxError("Spec 18.2.1.3 step 5dii2ai")); } } } thisLex = thisLex.Outer; if (thisLex == null) { throw new InvalidOperationException("thisLex and varEnv never matched"); } } } var functionsToInitialize = new List <FunctionDeclaration>(); var declaredFunctionNames = new List <string>(); foreach (var d in varDeclarations.Reverse()) { if (!(d is VariableDeclaration) && !(d is ForBinding)) { if (!(d is FunctionDeclaration f)) { throw new InvalidOperationException("Spec 18.2.1.3 step 8ai"); } var fn = f.BoundNames()[0]; if (!declaredFunctionNames.Contains(fn)) { if (varEnvRec is GlobalEnvironmentRecord g) { var fnDefinable = g.CanDeclareGlobalFunction(fn); if (fnDefinable.IsAbrupt()) { return(fnDefinable); } if (!fnDefinable.Other) { return(Completion.ThrowTypeError($"Function {fn} is not definable in global scope")); } } declaredFunctionNames.Add(fn); functionsToInitialize.Insert(0, f); } } } var declaredVarNames = new List <string>(); foreach (var d in varDeclarations) { IReadOnlyList <string>?boundNames = null; if (d is VariableDeclaration v) { boundNames = v.BoundNames(); } if (d is ForBinding f) { boundNames = f.BoundNames(); } if (boundNames != null) { foreach (var vn in boundNames) { if (!declaredFunctionNames.Contains(vn)) { if (varEnvRec is GlobalEnvironmentRecord g) { var fnDefinable = g.CanDeclareGlobalVar(vn); if (fnDefinable.IsAbrupt()) { return(fnDefinable); } if (!fnDefinable.Other) { return(Completion.ThrowTypeError($"Variable {vn} is not definable in global scope")); } } if (!declaredVarNames.Contains(vn)) { declaredVarNames.Add(vn); } } } } } var lexDeclarations = body.LexicallyScopedDeclarations(); foreach (var d in lexDeclarations) { foreach (var dn in d.BoundNames()) { Completion comp; if (d.IsConstantDeclaration()) { comp = lexEnvRec.CreateImmutableBinding(dn, true); } else { comp = lexEnvRec.CreateMutableBinding(dn, false); } if (comp.IsAbrupt()) { return(comp); } } } foreach (var f in functionsToInitialize) { var fn = f.BoundNames()[0]; var fo = f.InstantiateFunctionObject(lexEnv); if (varEnvRec is GlobalEnvironmentRecord g) { var comp = g.CreateGlobalFunctionBinding(fn, fo, true); if (comp.IsAbrupt()) { return(comp); } } else { var bindingExists = varEnvRec.HasBinding(fn); if (!bindingExists.Other) { var status = varEnvRec.CreateMutableBinding(fn, true); if (status.IsAbrupt()) { throw new InvalidOperationException("Spec 18.2.1.3 Step 15dii2"); } varEnvRec.InitializeBinding(fn, fo); } else { varEnvRec.SetMutableBinding(fn, fo, false); } } } foreach (var vn in declaredVarNames) { if (varEnvRec is GlobalEnvironmentRecord g) { var comp = g.CreateGlobalVarBinding(vn, true); if (comp.IsAbrupt()) { return(comp); } } else { var bindingExists = varEnvRec.HasBinding(vn); if (!bindingExists.Other) { var status = varEnvRec.CreateMutableBinding(vn, true); if (status.IsAbrupt()) { throw new InvalidOperationException("Spec 18.2.1.3 Step 16bii2"); } varEnvRec.InitializeBinding(vn, UndefinedValue.Instance); } } } return(Completion.NormalCompletion()); }
public static FunctionObject FunctionCreate(FunctionCreateKind kind, FormalParameters parameters, FunctionStatementList body, LexicalEnvironment scope, bool strict, IValue?prototype = null) { if (prototype == null) { prototype = Interpreter.Instance().CurrentRealm().Intrinsics.FunctionPrototype; } var functionKind = kind == FunctionCreateKind.Normal ? FunctionKind.Normal : FunctionKind.NonConstructor; FunctionObject F = FunctionAllocate(prototype, strict, functionKind); return(FunctionInitialize(F, kind, parameters, body, scope)); }