private Object CreateMappedArgumentsObject(FormalParameters formalParameters, IReadOnlyList <IValue> arguments, EnvironmentRecord env) { var map = Utils.ObjectCreate(null); var obj = new MappedArguments(map); var parameterNames = formalParameters.BoundNames(); int index; for (index = 0; index < arguments.Count; index++) { Utils.CreateDataProperty(obj, index.ToString(System.Globalization.CultureInfo.InvariantCulture), arguments[index]); } obj.DefinePropertyOrThrow("length", new PropertyDescriptor(new NumberValue(arguments.Count), true, false, true)); var mappedNames = new List <string>(); for (index = parameterNames.Count - 1; index >= 0; index--) { var name = parameterNames[index]; if (!mappedNames.Contains(name)) { mappedNames.Add(name); if (index < arguments.Count) { var g = MakeArgGetter(name, env); var p = MakeArgSetter(name, env); map.DefineOwnProperty(index.ToString(System.Globalization.CultureInfo.InvariantCulture), new PropertyDescriptor(p, g, false, true)); } } } DefinePropertyOrThrow("@@iterator", new PropertyDescriptor(Utils.CreateBuiltinFunction(ArrayPrototype.values), true, false, true)); DefinePropertyOrThrow("callee", new PropertyDescriptor(this, true, false, true)); return(obj); }
public Completion FunctionDeclarationInstantiation(IReadOnlyList <IValue> arguments) { var calleeContext = Interpreter.Instance().RunningExecutionContext(); var env = calleeContext.LexicalEnvironment; var envRec = env.EnvironmentRecord; var parameterNames = FormalParameters.BoundNames(); var hasDuplicates = parameterNames.Distinct().Count() < parameterNames.Count; var simpleParameterList = FormalParameters.IsSimpleParameterList(); var hasParameterExpressions = FormalParameters.formalParameters.Any(p => p.hasInitializer); var varNames = Code.VarDeclaredNames(); var varDeclarations = Code.VarScopedDeclarations(); var functionNames = new LinkedList <string>(); var functionsToInitialize = new LinkedList <FunctionDeclaration>(); foreach (var d in varDeclarations.Reverse()) { if (d is FunctionDeclaration functionDeclaration) { var fn = functionDeclaration.BoundNames()[0]; if (!functionNames.Contains(fn)) { functionNames.AddFirst(fn); functionsToInitialize.AddFirst(functionDeclaration); } } } var argumentsObjectNeeded = true; if (ThisMode == ThisMode.Lexical) { argumentsObjectNeeded = false; } else if (parameterNames.Contains("arguments")) { argumentsObjectNeeded = false; } else if (!hasParameterExpressions) { if (functionNames.Contains("arguments")) { argumentsObjectNeeded = false; } } foreach (var paramName in parameterNames) { var alreadyDeclared = envRec.HasBinding(paramName).Other == true; if (!alreadyDeclared) { envRec.CreateMutableBinding(paramName, false); if (hasDuplicates) { envRec.InitializeBinding(paramName, UndefinedValue.Instance); } } } IReadOnlyList <string> parameterBindings; if (argumentsObjectNeeded) { Object ao; if (Strict || !simpleParameterList) { ao = CreateUnmappedArgumentsObject(arguments); } else { ao = CreateMappedArgumentsObject(FormalParameters, arguments, envRec); } if (Strict) { envRec.CreateImmutableBinding("arguments", false); } else { envRec.CreateMutableBinding("arguments", false); } envRec.InitializeBinding("arguments", ao); parameterBindings = parameterNames.Concat(new[] { "arguments" }).ToList(); } else { parameterBindings = parameterNames; } var iterator = new ArgumentIterator(arguments); Completion comp; if (hasDuplicates) { comp = FormalParameters.IteratorBindingInitialization(null, iterator); } else { comp = FormalParameters.IteratorBindingInitialization(env, iterator); } if (comp.IsAbrupt()) { return(comp); } LexicalEnvironment varEnv; EnvironmentRecord varEnvRec; if (!hasParameterExpressions) { var instantiatedVarNames = new List <string>(parameterNames); foreach (var n in varNames) { if (!instantiatedVarNames.Contains(n)) { instantiatedVarNames.Add(n); envRec.CreateMutableBinding(n, false); envRec.InitializeBinding(n, UndefinedValue.Instance); } } varEnv = env; varEnvRec = envRec; } else { varEnv = env.NewDeclarativeEnvironment(); varEnvRec = varEnv.EnvironmentRecord; calleeContext.VariableEnvironment = varEnv; var instantiatedVarNames = new List <string>(); foreach (var n in varNames) { if (!instantiatedVarNames.Contains(n)) { instantiatedVarNames.Add(n); varEnvRec.CreateMutableBinding(n, false); IValue initialValue; if (!parameterBindings.Contains(n) || functionNames.Contains(n)) { initialValue = UndefinedValue.Instance; } else { initialValue = envRec.GetBindingValue(n, false).value !; } varEnvRec.InitializeBinding(n, initialValue); } } } var lexEnv = !Strict?varEnv.NewDeclarativeEnvironment() : varEnv; var lexEnvRec = lexEnv.EnvironmentRecord; calleeContext.LexicalEnvironment = lexEnv; var lexDeclarations = Code.LexicallyScopedDeclarations(); foreach (var d in lexDeclarations) { foreach (var dn in d.BoundNames()) { if (d.IsConstantDeclaration()) { lexEnvRec.CreateImmutableBinding(dn, true); } else { lexEnvRec.CreateMutableBinding(dn, false); } } } foreach (var f in functionsToInitialize) { var fn = f.BoundNames()[0]; FunctionObject fo = f.InstantiateFunctionObject(lexEnv); varEnvRec.SetMutableBinding(fn, fo, false); } return(Completion.NormalCompletion()); }