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;
        }
Beispiel #2
0
        //  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);
                }
            }
        }