public static ArgumentsInstance CreateArgumentsObject(Engine engine, FunctionInstance func, string[] names, JsValue[] args, EnvironmentRecord env, bool strict) { var len = args.Length; var obj = new ArgumentsInstance(engine); obj.Prototype = engine.Object.PrototypeObject; obj.Extensible = true; obj.FastAddProperty("length", len, true, false, true); obj.Strict = strict; var map = engine.Object.Construct(Arguments.Empty); var mappedNamed = new List<string>(); var indx = 0; while (indx <= len - 1) { var indxStr = TypeConverter.ToString(indx); var val = args[indx]; obj.FastAddProperty(indxStr, val, true, true, true); if (indx < names.Length) { var name = names[indx]; if (!strict && !mappedNamed.Contains(name)) { mappedNamed.Add(name); Func<JsValue, JsValue> g = n => env.GetBindingValue(name, false); var p = new Action<JsValue, JsValue>((n, o) => env.SetMutableBinding(name, o, true)); map.DefineOwnProperty(indxStr, new ClrAccessDescriptor(engine, g, p) { Configurable = true }, false); } } indx++; } // step 12 if (mappedNamed.Count > 0) { obj.ParameterMap = map; } // step 13 if (!strict) { obj.FastAddProperty("callee",func, true, false, true); } // step 14 else { var thrower = engine.Function.ThrowTypeError; obj.DefineOwnProperty("caller", new PropertyDescriptor(get: thrower, set: thrower, enumerable:false, configurable:false), false); obj.DefineOwnProperty("callee", new PropertyDescriptor(get: thrower, set: thrower, enumerable: false, configurable: false), false); } return obj; }
// http://www.ecma-international.org/ecma-262/5.1/#sec-10.5 public void DeclarationBindingInstantiation(DeclarationBindingType declarationBindingType, IList<FunctionDeclaration> functionDeclarations, IList<VariableDeclaration> variableDeclarations, FunctionInstance functionInstance, JsValue[] arguments) { var env = ExecutionContext.VariableEnvironment.Record; bool configurableBindings = declarationBindingType == DeclarationBindingType.EvalCode; var strict = StrictModeScope.IsStrictModeCode; if (declarationBindingType == DeclarationBindingType.FunctionCode) { var argCount = arguments.Length; var n = 0; foreach (var argName in functionInstance.FormalParameters) { n++; var v = n > argCount ? Undefined.Instance : arguments[n - 1]; var argAlreadyDeclared = env.HasBinding(argName); if (!argAlreadyDeclared) { env.CreateMutableBinding(argName); } env.SetMutableBinding(argName, v, strict); } } foreach (var f in functionDeclarations) { var fn = f.Id.Name; var fo = Function.CreateFunctionObject(f); var funcAlreadyDeclared = env.HasBinding(fn); if (!funcAlreadyDeclared) { env.CreateMutableBinding(fn, configurableBindings); } else { if (env == GlobalEnvironment.Record) { var go = Global; var existingProp = go.GetProperty(fn); if (existingProp.Configurable.Value.AsBoolean()) { go.DefineOwnProperty(fn, new PropertyDescriptor( value: Undefined.Instance, writable: true, enumerable: true, configurable: configurableBindings ), true); } else { if (existingProp.IsAccessorDescriptor() || (!existingProp.Enumerable.Value.AsBoolean())) { throw new JavaScriptException(TypeError); } } } } env.SetMutableBinding(fn, fo, strict); } var argumentsAlreadyDeclared = env.HasBinding("arguments"); if (declarationBindingType == DeclarationBindingType.FunctionCode && !argumentsAlreadyDeclared) { var argsObj = ArgumentsInstance.CreateArgumentsObject(this, functionInstance, functionInstance.FormalParameters, arguments, env, strict); if (strict) { var declEnv = env as DeclarativeEnvironmentRecord; if (declEnv == null) { throw new ArgumentException(); } declEnv.CreateImmutableBinding("arguments"); declEnv.InitializeImmutableBinding("arguments", argsObj); } else { env.CreateMutableBinding("arguments"); env.SetMutableBinding("arguments", argsObj, false); } } // process all variable declarations in the current parser scope foreach (var d in variableDeclarations.SelectMany(x => x.Declarations)) { var dn = d.Id.Name; var varAlreadyDeclared = env.HasBinding(dn); if (!varAlreadyDeclared) { env.CreateMutableBinding(dn, configurableBindings); env.SetMutableBinding(dn, Undefined.Instance, strict); } } }