LoadArgument() 공개 추상적인 메소드

Pushes the value of the method argument with the given index onto the stack.
public abstract LoadArgument ( int argumentIndex ) : void
argumentIndex int The index of the argument to push onto the stack.
리턴 void
예제 #1
0
 /// <summary>
 /// Generates a method that does type conversion and calls the bound method.
 /// </summary>
 /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
 /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
 /// <returns> A delegate that does type conversion and calls the method represented by this
 /// object. </returns>
 protected override void GenerateStub(ILGenerator generator, int argumentCount)
 {
     // Check for the correct number of arguments.
     if (argumentCount != 1)
     {
         EmitHelpers.EmitThrow(generator, ErrorType.TypeError, "Wrong number of arguments");
         EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
         generator.Complete();
         return;
     }
     if (this.field.IsStatic == false)
     {
         generator.LoadArgument(1);
         ClrBinder.EmitConversionToType(generator, this.field.DeclaringType, convertToAddress: true);
     }
     generator.LoadArgument(2);
     generator.LoadInt32(0);
     generator.LoadArrayElement(typeof(object));
     ClrBinder.EmitConversionToType(generator, this.field.FieldType, convertToAddress: false);
     generator.StoreField(this.field);
     EmitHelpers.EmitUndefined(generator);
     generator.Complete();
 }
예제 #2
0
        /// <summary>
        /// Generates a method that does type conversion and calls the bound method.
        /// </summary>
        /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
        /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
        /// <returns> A delegate that does type conversion and calls the method represented by this
        /// object. </returns>
        protected override void GenerateStub(ILGenerator generator, int argumentCount)
        {
            // Check for the correct number of arguments.
            if (argumentCount != 0)
            {
                EmitHelpers.EmitThrow(generator, "TypeError", "Wrong number of arguments");
                EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
                generator.Complete();
                return;
            }

            if (this.field.IsStatic == false)
            {
                generator.LoadArgument(1);
                ClrBinder.EmitConversionToType(generator, this.field.DeclaringType, convertToAddress: true);
            }
            generator.LoadField(this.field);
            ClrBinder.EmitConversionToObject(generator, this.field.FieldType);
            generator.Complete();
        }
예제 #3
0
 /// <summary>
 /// Pushes a reference to the current scope onto the stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadScope(ILGenerator generator)
 {
     generator.LoadArgument(1);
 }
예제 #4
0
        //     LOAD METHOD PARAMETERS
        //_________________________________________________________________________________________

        /// <summary>
        /// Pushes a reference to the script engine onto the stack.
        /// </summary>
        /// <param name="generator"> The IL generator. </param>
        public static void LoadScriptEngine(ILGenerator generator)
        {
            generator.LoadArgument(0);
        }
예제 #5
0
 /// <summary>
 /// Pushes a reference to the array of argument values for the current function onto the
 /// stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadArgumentsArray(ILGenerator generator)
 {
     generator.LoadArgument(1);
 }
예제 #6
0
 /// <summary>
 /// Pushes a reference to the current function onto the stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadFunction(ILGenerator generator)
 {
     generator.LoadArgument(0);
     generator.Call(ReflectionHelpers.ExecutionContext_GetExecutingFunction);
 }
예제 #7
0
 /// <summary>
 /// Pushes a reference to the script engine onto the stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadScriptEngine(ILGenerator generator)
 {
     generator.LoadArgument(0);
     generator.Call(ReflectionHelpers.ExecutionContext_GetEngine);
 }
예제 #8
0
 /// <summary>
 /// Pushes a reference to the array of argument values for the current function onto the
 /// stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadArgumentsArray(ILGenerator generator)
 {
     generator.LoadArgument(4);
 }
예제 #9
0
        /// <summary>
        /// Generates a method that does type conversion and calls the bound method.
        /// </summary>
        /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
        /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
        /// <returns> A delegate that does type conversion and calls the method represented by this
        /// object. </returns>
        protected override void GenerateStub(ILGenerator generator, int argumentCount)
        {
            // Determine the methods that have the correct number of arguments.
            var candidateMethods = new List<BinderMethod>();
            foreach (var candidateMethod in this.targetMethods)
            {
                if (candidateMethod.IsArgumentCountCompatible(argumentCount) == true)
                    candidateMethods.Add(candidateMethod);
            }

            // Zero candidates means no overload had the correct number of arguments.
            if (candidateMethods.Count == 0)
            {
                EmitHelpers.EmitThrow(generator, "TypeError", string.Format("No overload for method '{0}' takes {1} arguments", this.Name, argumentCount));
                EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
                generator.Complete();
                return;
            }

            // Select the method to call at run time.
            generator.LoadInt32(candidateMethods.Count);
            generator.NewArray(typeof(RuntimeMethodHandle));
            for (int i = 0; i < candidateMethods.Count; i ++)
            {
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadToken(candidateMethods[i]);
                generator.StoreArrayElement(typeof(RuntimeMethodHandle));
            }
            generator.LoadArgument(0);
            generator.LoadArgument(1);
            generator.LoadArgument(2);
            generator.Call(ReflectionHelpers.BinderUtilities_ResolveOverloads);

            var endOfMethod = generator.CreateLabel();
            for (int i = 0; i < candidateMethods.Count; i++)
            {
                // Check if this is the selected method.
                ILLabel endOfIf = null;
                if (i < candidateMethods.Count - 1)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i);
                    endOfIf = generator.CreateLabel();
                    generator.BranchIfNotEqual(endOfIf);
                }
                generator.Pop();

                var targetMethod = candidateMethods[i];

                // Convert the arguments.
                foreach (var argument in targetMethod.GenerateArguments(generator, argumentCount))
                {
                    // Load the input parameter value.
                    switch (argument.Source)
                    {
                        case BinderArgumentSource.ScriptEngine:
                            generator.LoadArgument(0);
                            break;
                        case BinderArgumentSource.ThisValue:
                            generator.LoadArgument(1);
                            break;
                        case BinderArgumentSource.InputParameter:
                            generator.LoadArgument(2);
                            generator.LoadInt32(argument.InputParameterIndex);
                            generator.LoadArrayElement(typeof(object));
                            break;
                    }

                    // Convert to the target type.
                    EmitConversionToType(generator, argument.Type, convertToAddress: argument.Source == BinderArgumentSource.ThisValue);
                }

                // Call the target method.
                targetMethod.GenerateCall(generator);

                // Convert the return value.
                if (targetMethod.ReturnType == typeof(void))
                    EmitHelpers.EmitUndefined(generator);
                else
                    EmitConversionToObject(generator, targetMethod.ReturnType);

                // Branch to the end of the method if this was the selected method.
                if (endOfIf != null)
                {
                    generator.Branch(endOfMethod);
                    generator.DefineLabelPosition(endOfIf);
                }
            }

            generator.DefineLabelPosition(endOfMethod);
            generator.Complete();
        }
예제 #10
0
        /// <summary>
        /// Pops the value on the stack, converts it to an object, then pushes the result onto the
        /// stack.
        /// </summary>
        /// <param name="generator"> The IL generator. </param>
        /// <param name="fromType"> The type to convert from. </param>
        internal static void EmitConversionToObject(ILGenerator generator, Type fromType)
        {
            // If the from type is a reference type, check for null.
            ILLabel endOfNullCheck = null;
            if (fromType.IsValueType == false)
            {
                var startOfElse = generator.CreateLabel();
                endOfNullCheck = generator.CreateLabel();
                generator.Duplicate();
                generator.BranchIfNotNull(startOfElse);
                generator.Pop();
                EmitHelpers.EmitNull(generator);
                generator.Branch(endOfNullCheck);
                generator.DefineLabelPosition(startOfElse);
            }

            switch (Type.GetTypeCode(fromType))
            {
                case TypeCode.Boolean:
                    generator.Box(typeof(bool));
                    break;
                case TypeCode.Byte:
                    generator.Box(typeof(int));
                    break;
                case TypeCode.Char:
                    generator.LoadInt32(1);
                    generator.NewObject(ReflectionHelpers.String_Constructor_Char_Int);
                    break;
                
                case TypeCode.DBNull:
                    throw new NotSupportedException("DBNull is not a supported return type.");
                case TypeCode.Decimal:
                    generator.Call(ReflectionHelpers.Decimal_ToDouble);
                    generator.Box(typeof(double));
                    break;
                case TypeCode.Double:
                    generator.Box(typeof(double));
                    break;
                case TypeCode.Empty:
                    throw new NotSupportedException("Empty is not a supported return type.");
                case TypeCode.Int16:
                    generator.Box(typeof(int));
                    break;
                case TypeCode.Int32:
                    generator.Box(typeof(int));
                    break;
                case TypeCode.Int64:
                    generator.ConvertToDouble();
                    generator.Box(typeof(double));
                    break;

                case TypeCode.DateTime:
                case TypeCode.Object:
                    // Check if the type must be wrapped with a ClrInstanceWrapper.
                    // Note: if the type is a value type it cannot be a primitive or it would
                    // have been handled elsewhere in the switch.
                    ILLabel endOfWrapCheck = null;
                    if (fromType.IsValueType == false)
                    {
                        generator.Duplicate();
                        generator.Call(ReflectionHelpers.TypeUtilities_IsPrimitiveOrObject);
                        endOfWrapCheck = generator.CreateLabel();
                        generator.BranchIfTrue(endOfWrapCheck);
                    }

                    // The type must be wrapped.
                    var temp = generator.CreateTemporaryVariable(fromType);
                    generator.StoreVariable(temp);
                    generator.LoadArgument(0);
                    generator.LoadVariable(temp);
                    if (fromType.IsValueType == true)
                        generator.Box(fromType);
                    generator.ReleaseTemporaryVariable(temp);
                    generator.NewObject(ReflectionHelpers.ClrInstanceWrapper_Constructor);
                    
                    // End of wrap check.
                    if (fromType.IsValueType == false)
                        generator.DefineLabelPosition(endOfWrapCheck);
                    break;

                case TypeCode.SByte:
                    generator.Box(typeof(int));
                    break;
                case TypeCode.Single:
                    generator.Box(typeof(double));
                    break;
                case TypeCode.String:
                    break;
                case TypeCode.UInt16:
                    generator.Box(typeof(int));
                    break;
                case TypeCode.UInt32:
                    generator.Box(typeof(uint));
                    break;
                case TypeCode.UInt64:
                    generator.ConvertUnsignedToDouble();
                    generator.Box(typeof(double));
                    break;
            }

            // Label the end of the null check.
            if (fromType.IsValueType == false)
                generator.DefineLabelPosition(endOfNullCheck);
        }
예제 #11
0
        /// <summary>
        /// Generates a method that does type conversion and calls the bound method.
        /// </summary>
        /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
        /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
        /// <returns> A delegate that does type conversion and calls the method represented by this
        /// object. </returns>
        protected override void GenerateStub(ILGenerator generator, int argumentCount)
        {
            // Determine the methods that have the correct number of arguments.
            var candidateMethods = new List <BinderMethod>();

            foreach (var candidateMethod in this.targetMethods)
            {
                if (candidateMethod.IsArgumentCountCompatible(argumentCount) == true)
                {
                    candidateMethods.Add(candidateMethod);
                }
            }

            // Zero candidates means no overload had the correct number of arguments.
            if (candidateMethods.Count == 0)
            {
                EmitHelpers.EmitThrow(generator, ErrorType.TypeError, string.Format("No overload for method '{0}' takes {1} arguments", this.Name, argumentCount));
                EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
                generator.Complete();
                return;
            }

            // Select the method to call at run time.
            generator.LoadInt32(candidateMethods.Count);
            generator.NewArray(typeof(RuntimeMethodHandle));
            for (int i = 0; i < candidateMethods.Count; i++)
            {
                generator.Duplicate();
                generator.LoadInt32(i);
                generator.LoadToken(candidateMethods[i]);
                generator.StoreArrayElement(typeof(RuntimeMethodHandle));
            }
            generator.LoadArgument(0);
            generator.LoadArgument(1);
            generator.LoadArgument(2);
            generator.Call(ReflectionHelpers.BinderUtilities_ResolveOverloads);

            var endOfMethod = generator.CreateLabel();

            for (int i = 0; i < candidateMethods.Count; i++)
            {
                // Check if this is the selected method.
                ILLabel endOfIf = null;
                if (i < candidateMethods.Count - 1)
                {
                    generator.Duplicate();
                    generator.LoadInt32(i);
                    endOfIf = generator.CreateLabel();
                    generator.BranchIfNotEqual(endOfIf);
                }
                generator.Pop();

                var targetMethod = candidateMethods[i];

                // Convert the arguments.
                foreach (var argument in targetMethod.GenerateArguments(generator, argumentCount))
                {
                    // Load the input parameter value.
                    switch (argument.Source)
                    {
                    case BinderArgumentSource.ScriptEngine:
                        generator.LoadArgument(0);
                        break;

                    case BinderArgumentSource.ThisValue:
                        generator.LoadArgument(1);
                        break;

                    case BinderArgumentSource.InputParameter:
                        generator.LoadArgument(2);
                        generator.LoadInt32(argument.InputParameterIndex);
                        generator.LoadArrayElement(typeof(object));
                        break;
                    }

                    // Convert to the target type.
                    EmitConversionToType(generator, argument.Type, convertToAddress: argument.Source == BinderArgumentSource.ThisValue);
                }

                // Call the target method.
                targetMethod.GenerateCall(generator);

                // Convert the return value.
                if (targetMethod.ReturnType == typeof(void))
                {
                    EmitHelpers.EmitUndefined(generator);
                }
                else
                {
                    EmitConversionToObject(generator, targetMethod.ReturnType);
                }

                // Branch to the end of the method if this was the selected method.
                if (endOfIf != null)
                {
                    generator.Branch(endOfMethod);
                    generator.DefineLabelPosition(endOfIf);
                }
            }

            generator.DefineLabelPosition(endOfMethod);
            generator.Complete();
        }
예제 #12
0
        /// <summary>
        /// Pops the value on the stack, converts it to an object, then pushes the result onto the
        /// stack.
        /// </summary>
        /// <param name="generator"> The IL generator. </param>
        /// <param name="fromType"> The type to convert from. </param>
        internal static void EmitConversionToObject(ILGenerator generator, Type fromType)
        {
            // If the from type is a reference type, check for null.
            ILLabel endOfNullCheck = null;

            if (fromType.IsValueType == false)
            {
                var startOfElse = generator.CreateLabel();
                endOfNullCheck = generator.CreateLabel();
                generator.Duplicate();
                generator.BranchIfNotNull(startOfElse);
                generator.Pop();
                EmitHelpers.EmitNull(generator);
                generator.Branch(endOfNullCheck);
                generator.DefineLabelPosition(startOfElse);
            }

            // Handle Nullable<>.
            var isNullable = fromType.IsGenericType && fromType.GetGenericTypeDefinition() == typeof(Nullable <>);

            if (isNullable)
            {
                endOfNullCheck = generator.CreateLabel();

                var v = generator.CreateTemporaryVariable(fromType);
                generator.StoreVariable(v);
                generator.LoadAddressOfVariable(v);

                var hasValue = ReflectionHelpers.GetInstanceMethod(fromType, "get_HasValue");
                generator.Call(hasValue);
                generator.BranchIfTrue(endOfNullCheck);

                // Return null.
                generator.LoadNull();
                generator.Return();

                // Jump here if it was NOT null.
                generator.DefineLabelPosition(endOfNullCheck);

                // Get the underlying value.
                generator.LoadAddressOfVariable(v);
                var getValue = ReflectionHelpers.GetInstanceMethod(fromType, "get_Value");
                generator.Call(getValue);

                // Now let the normal conversion work.
                fromType = fromType.GenericTypeArguments[0];
            }

            switch (Type.GetTypeCode(fromType))
            {
            case TypeCode.Boolean:
                generator.Box(typeof(bool));
                break;

            case TypeCode.Byte:
                generator.Box(typeof(int));
                break;

            case TypeCode.Char:
                generator.LoadInt32(1);
                generator.NewObject(ReflectionHelpers.String_Constructor_Char_Int);
                break;

            case TypeCode.DBNull:
                throw new NotSupportedException("DBNull is not a supported return type.");

            case TypeCode.Decimal:
                generator.Call(ReflectionHelpers.Decimal_ToDouble);
                generator.Box(typeof(double));
                break;

            case TypeCode.Double:
                generator.Box(typeof(double));
                break;

            case TypeCode.Empty:
                throw new NotSupportedException("Empty is not a supported return type.");

            case TypeCode.Int16:
                generator.Box(typeof(int));
                break;

            case TypeCode.Int32:
                generator.Box(typeof(int));
                break;

            case TypeCode.Int64:
                generator.ConvertToDouble();
                generator.Box(typeof(double));
                break;

            case TypeCode.DateTime:
            case TypeCode.Object:
                // Check if the type must be wrapped with a ClrInstanceWrapper.
                // Note: if the type is a value type it cannot be a primitive or it would
                // have been handled elsewhere in the switch.
                ILLabel endOfWrapCheck = null;
                if (fromType.IsValueType == false)
                {
                    generator.Duplicate();
                    generator.Call(ReflectionHelpers.TypeUtilities_IsPrimitiveOrObject);
                    endOfWrapCheck = generator.CreateLabel();
                    generator.BranchIfTrue(endOfWrapCheck);
                }

                // The type must be wrapped.
                var temp = generator.CreateTemporaryVariable(fromType);
                generator.StoreVariable(temp);
                generator.LoadArgument(0);
                generator.LoadVariable(temp);
                if (fromType.IsValueType == true)
                {
                    generator.Box(fromType);
                }
                generator.ReleaseTemporaryVariable(temp);
                generator.CallStatic(ReflectionHelpers.ClrInstanceWrapper_Create);

                // End of wrap check.
                if (fromType.IsValueType == false)
                {
                    generator.DefineLabelPosition(endOfWrapCheck);
                }
                break;

            case TypeCode.SByte:
                generator.Box(typeof(int));
                break;

            case TypeCode.Single:
                generator.Box(typeof(double));
                break;

            case TypeCode.String:
                break;

            case TypeCode.UInt16:
                generator.Box(typeof(int));
                break;

            case TypeCode.UInt32:
                generator.Box(typeof(uint));
                break;

            case TypeCode.UInt64:
                generator.ConvertUnsignedToDouble();
                generator.Box(typeof(double));
                break;
            }

            // Label the end of the null check.
            if (fromType.IsValueType == false)
            {
                generator.DefineLabelPosition(endOfNullCheck);
            }
        }
예제 #13
0
        /// <summary>
        /// Generates a method that does type conversion and calls the bound method.
        /// </summary>
        /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
        /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
        /// <returns> A delegate that does type conversion and calls the method represented by this
        /// object. </returns>
        protected override void GenerateStub(ILGenerator generator, int argumentCount)
        {
            // Here is what we are going to generate.
            //private static object SampleBinder(ScriptEngine engine, object thisObject, object[] arguments)
            //{
            //    // Target function signature: int (bool, int, string, object).
            //    bool param1;
            //    int param2;
            //    string param3;
            //    object param4;
            //    param1 = arguments[0] != 0;
            //    param2 = TypeConverter.ToInt32(arguments[1]);
            //    param3 = TypeConverter.ToString(arguments[2]);
            //    param4 = Undefined.Value;
            //    return thisObject.targetMethod(param1, param2, param3, param4);
            //}

            // Find the target method.
            var binderMethod = this.buckets[Math.Min(argumentCount, this.buckets.Length - 1)];

            // Constrain the number of apparent arguments to within the required bounds.
            int minArgumentCount = binderMethod.RequiredParameterCount;
            int maxArgumentCount = binderMethod.RequiredParameterCount + binderMethod.OptionalParameterCount;

            if (binderMethod.HasParamArray == true)
            {
                maxArgumentCount = int.MaxValue;
            }

            foreach (var argument in binderMethod.GenerateArguments(generator, Math.Min(Math.Max(argumentCount, minArgumentCount), maxArgumentCount)))
            {
                switch (argument.Source)
                {
                case BinderArgumentSource.ScriptEngine:
                    // Load the "engine" parameter passed by the client.
                    generator.LoadArgument(0);
                    break;

                case BinderArgumentSource.ThisValue:
                    // Load the "this" parameter passed by the client.
                    generator.LoadArgument(1);

                    bool inheritsFromObjectInstance = typeof(ObjectInstance).IsAssignableFrom(argument.Type);
                    if (argument.Type.IsClass == true && inheritsFromObjectInstance == false &&
                        argument.Type != typeof(string) && argument.Type != typeof(object))
                    {
                        // If the "this" object is an unsupported class, pass it through unmodified.
                        generator.CastClass(argument.Type);
                    }
                    else
                    {
                        if (argument.Type != typeof(object))
                        {
                            // If the target "this" object type is not of type object, throw an error if
                            // the value is undefined or null.
                            generator.Duplicate();
                            var temp = generator.CreateTemporaryVariable(typeof(object));
                            generator.StoreVariable(temp);
                            generator.LoadArgument(0);
                            generator.LoadVariable(temp);
                            generator.LoadString(binderMethod.Name);
                            generator.Call(ReflectionHelpers.TypeUtilities_VerifyThisObject);
                            generator.ReleaseTemporaryVariable(temp);
                        }

                        // Convert to the target type.
                        EmitTypeConversion(generator, typeof(object), argument.Type);

                        if (argument.Type != typeof(ObjectInstance) && inheritsFromObjectInstance == true)
                        {
                            // EmitConversionToObjectInstance can emit null if the toType is derived from ObjectInstance.
                            // Therefore, if the value emitted is null it means that the "thisObject" is a type derived
                            // from ObjectInstance (e.g. FunctionInstance) and the value provided is a different type
                            // (e.g. ArrayInstance).  In this case, throw an exception explaining that the function is
                            // not generic.
                            var endOfThrowLabel = generator.CreateLabel();
                            generator.Duplicate();
                            generator.BranchIfNotNull(endOfThrowLabel);
                            generator.LoadArgument(0);
                            EmitHelpers.EmitThrow(generator, "TypeError", string.Format("The method '{0}' is not generic", binderMethod.Name));
                            generator.DefineLabelPosition(endOfThrowLabel);
                        }
                    }
                    break;

                case BinderArgumentSource.InputParameter:
                    if (argument.InputParameterIndex < argumentCount)
                    {
                        // Load the argument onto the stack.
                        generator.LoadArgument(2);
                        generator.LoadInt32(argument.InputParameterIndex);
                        generator.LoadArrayElement(typeof(object));

                        // Get some flags that apply to the parameter.
                        var parameterFlags     = JSParameterFlags.None;
                        var parameterAttribute = argument.GetCustomAttribute <JSParameterAttribute>();
                        if (parameterAttribute != null)
                        {
                            if (argument.Type != typeof(ObjectInstance))
                            {
                                throw new NotImplementedException("[JSParameter] is only supported for arguments of type ObjectInstance.");
                            }
                            parameterFlags = parameterAttribute.Flags;
                        }

                        if ((parameterFlags & JSParameterFlags.DoNotConvert) == 0)
                        {
                            // Convert the input parameter to the correct type.
                            EmitTypeConversion(generator, typeof(object), argument);
                        }
                        else
                        {
                            // Don't do argument conversion.

                            /*var endOfThrowLabel = generator.CreateLabel();
                             * generator.IsInstance(typeof(ObjectInstance));
                             * generator.Duplicate();
                             * generator.BranchIfNotNull(endOfThrowLabel);
                             * EmitHelpers.EmitThrow(generator, "TypeError", string.Format("Parameter {1} parameter of '{0}' must be an object", binderMethod.Name, argument.InputParameterIndex));
                             * generator.DefineLabelPosition(endOfThrowLabel);*/
                        }
                    }
                    else
                    {
                        // The target method has more parameters than we have input values.
                        EmitUndefined(generator, argument);
                    }
                    break;
                }
            }

            // Emit the call.
            binderMethod.GenerateCall(generator);

            // Convert the return value.
            if (binderMethod.ReturnType == typeof(void))
            {
                EmitHelpers.EmitUndefined(generator);
            }
            else
            {
                EmitTypeConversion(generator, binderMethod.ReturnType, typeof(object));

                // Convert a null return value to Null.Value or Undefined.Value.
                var endOfSpecialCaseLabel = generator.CreateLabel();
                generator.Duplicate();
                generator.BranchIfNotNull(endOfSpecialCaseLabel);
                generator.Pop();
                if ((binderMethod.Flags & JSFunctionFlags.ConvertNullReturnValueToUndefined) != 0)
                {
                    EmitHelpers.EmitUndefined(generator);
                }
                else
                {
                    EmitHelpers.EmitNull(generator);
                }
                generator.DefineLabelPosition(endOfSpecialCaseLabel);
            }

            // End the IL.
            generator.Complete();
        }
예제 #14
0
 /// <summary>
 /// Pushes the value of the <c>this</c> keyword onto the stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadThis(ILGenerator generator)
 {
     generator.LoadArgument(2);
 }
예제 #15
0
        /// <summary>
        /// Generates a method that does type conversion and calls the bound method.
        /// </summary>
        /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
        /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
        /// <returns> A delegate that does type conversion and calls the method represented by this
        /// object. </returns>
        protected override void GenerateStub(ILGenerator generator, int argumentCount)
        {
            // Here is what we are going to generate.
            //private static object SampleBinder(ScriptEngine engine, object thisObject, object[] arguments)
            //{
            //    // Target function signature: int (bool, int, string, object).
            //    bool param1;
            //    int param2;
            //    string param3;
            //    object param4;
            //    param1 = arguments[0] != 0;
            //    param2 = TypeConverter.ToInt32(arguments[1]);
            //    param3 = TypeConverter.ToString(arguments[2]);
            //    param4 = Undefined.Value;
            //    return thisObject.targetMethod(param1, param2, param3, param4);
            //}

            // Find the target method.
            var binderMethod = this.buckets[Math.Min(argumentCount, this.buckets.Length - 1)];

            // Constrain the number of apparent arguments to within the required bounds.
            int minArgumentCount = binderMethod.RequiredParameterCount;
            int maxArgumentCount = binderMethod.RequiredParameterCount + binderMethod.OptionalParameterCount;
            if (binderMethod.HasParamArray == true)
                maxArgumentCount = int.MaxValue;

            foreach (var argument in binderMethod.GenerateArguments(generator, Math.Min(Math.Max(argumentCount, minArgumentCount), maxArgumentCount)))
            {
                switch (argument.Source)
                {
                    case BinderArgumentSource.ScriptEngine:
                        // Load the "engine" parameter passed by the client.
                        generator.LoadArgument(0);
                        break;

                    case BinderArgumentSource.ThisValue:
                        // Load the "this" parameter passed by the client.
                        generator.LoadArgument(1);

                        bool inheritsFromObjectInstance = typeof(ObjectInstance).IsAssignableFrom(argument.Type);
                        if (argument.Type.IsClass == true && inheritsFromObjectInstance == false &&
                            argument.Type != typeof(string) && argument.Type != typeof(object))
                        {
                            // If the "this" object is an unsupported class, pass it through unmodified.
                            generator.CastClass(argument.Type);
                        }
                        else
                        {
                            if (argument.Type != typeof(object))
                            {
                                // If the target "this" object type is not of type object, throw an error if
                                // the value is undefined or null.
                                generator.Duplicate();
                                var temp = generator.CreateTemporaryVariable(typeof(object));
                                generator.StoreVariable(temp);
                                generator.LoadArgument(0);
                                generator.LoadVariable(temp);
                                generator.LoadString(binderMethod.Name);
                                generator.Call(ReflectionHelpers.TypeUtilities_VerifyThisObject);
                                generator.ReleaseTemporaryVariable(temp);
                            }

                            // Convert to the target type.
                            EmitTypeConversion(generator, typeof(object), argument.Type);

                            if (argument.Type != typeof(ObjectInstance) && inheritsFromObjectInstance == true)
                            {
                                // EmitConversionToObjectInstance can emit null if the toType is derived from ObjectInstance.
                                // Therefore, if the value emitted is null it means that the "thisObject" is a type derived
                                // from ObjectInstance (e.g. FunctionInstance) and the value provided is a different type
                                // (e.g. ArrayInstance).  In this case, throw an exception explaining that the function is
                                // not generic.
                                var endOfThrowLabel = generator.CreateLabel();
                                generator.Duplicate();
                                generator.BranchIfNotNull(endOfThrowLabel);
                                generator.LoadArgument(0);
                                EmitHelpers.EmitThrow(generator, "TypeError", string.Format("The method '{0}' is not generic", binderMethod.Name));
                                generator.DefineLabelPosition(endOfThrowLabel);
                            }
                        }
                        break;

                    case BinderArgumentSource.InputParameter:
                        if (argument.InputParameterIndex < argumentCount)
                        {
                            // Load the argument onto the stack.
                            generator.LoadArgument(2);
                            generator.LoadInt32(argument.InputParameterIndex);
                            generator.LoadArrayElement(typeof(object));

                            // Get some flags that apply to the parameter.
                            var parameterFlags = JSParameterFlags.None;
                            var parameterAttribute = argument.GetCustomAttribute<JSParameterAttribute>();
                            if (parameterAttribute != null)
                            {
                                if (argument.Type != typeof(ObjectInstance))
                                    throw new NotImplementedException("[JSParameter] is only supported for arguments of type ObjectInstance.");
                                parameterFlags = parameterAttribute.Flags;
                            }

                            if ((parameterFlags & JSParameterFlags.DoNotConvert) == 0)
                            {
                                // Convert the input parameter to the correct type.
                                EmitTypeConversion(generator, typeof(object), argument);
                            }
                            else
                            {
                                // Don't do argument conversion.
                                /*var endOfThrowLabel = generator.CreateLabel();
                                generator.IsInstance(typeof(ObjectInstance));
                                generator.Duplicate();
                                generator.BranchIfNotNull(endOfThrowLabel);
                                EmitHelpers.EmitThrow(generator, "TypeError", string.Format("Parameter {1} parameter of '{0}' must be an object", binderMethod.Name, argument.InputParameterIndex));
                                generator.DefineLabelPosition(endOfThrowLabel);*/
                            }
                        }
                        else
                        {
                            // The target method has more parameters than we have input values.
                            EmitUndefined(generator, argument);
                        }
                        break;
                }
            }

            // Emit the call.
            binderMethod.GenerateCall(generator);

            // Convert the return value.
            if (binderMethod.ReturnType == typeof(void))
                EmitHelpers.EmitUndefined(generator);
            else
            {
                EmitTypeConversion(generator, binderMethod.ReturnType, typeof(object));

                // Convert a null return value to Null.Value or Undefined.Value.
                var endOfSpecialCaseLabel = generator.CreateLabel();
                generator.Duplicate();
                generator.BranchIfNotNull(endOfSpecialCaseLabel);
                generator.Pop();
                if ((binderMethod.Flags & JSFunctionFlags.ConvertNullReturnValueToUndefined) != 0)
                    EmitHelpers.EmitUndefined(generator);
                else
                    EmitHelpers.EmitNull(generator);
                generator.DefineLabelPosition(endOfSpecialCaseLabel);
            }

            // End the IL.
            generator.Complete();
        }
예제 #16
0
 /// <summary>
 /// Pushes a reference to the current function onto the stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadFunction(ILGenerator generator)
 {
     generator.LoadArgument(3);
 }
예제 #17
0
        //     LOAD METHOD PARAMETERS
        //_________________________________________________________________________________________

        /// <summary>
        /// Pushes a reference to the script engine onto the stack.
        /// </summary>
        /// <param name="generator"> The IL generator. </param>
        public static void LoadScriptEngine(ILGenerator generator)
        {
            generator.LoadArgument(0);
        }
예제 #18
0
        //     LOAD METHOD PARAMETERS
        //_________________________________________________________________________________________

        /// <summary>
        /// Pushes the value of the execution context onto the stack.
        /// </summary>
        /// <param name="generator"> The IL generator. </param>
        public static void LoadExecutionContext(ILGenerator generator)
        {
            generator.LoadArgument(0);
        }
예제 #19
0
 /// <summary>
 /// Pushes a reference to the current scope onto the stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadScope(ILGenerator generator)
 {
     generator.LoadArgument(1);
 }
예제 #20
0
 /// <summary>
 /// Pushes the value of the <c>this</c> keyword onto the stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadThis(ILGenerator generator)
 {
     generator.LoadArgument(0);
     generator.Call(ReflectionHelpers.ExecutionContext_GetThisValue);
 }
예제 #21
0
 /// <summary>
 /// Pushes the value of the <c>this</c> keyword onto the stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadThis(ILGenerator generator)
 {
     generator.LoadArgument(2);
 }
예제 #22
0
 /// <summary>
 /// Pushes a reference to the 'new.target' value for the current function onto the stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadNewTarget(ILGenerator generator)
 {
     generator.LoadArgument(0);
     generator.Call(ReflectionHelpers.ExecutionContext_GetNewTargetObject);
 }
예제 #23
0
 /// <summary>
 /// Pushes a reference to the current function onto the stack.
 /// </summary>
 /// <param name="generator"> The IL generator. </param>
 public static void LoadFunction(ILGenerator generator)
 {
     generator.LoadArgument(3);
 }
예제 #24
0
        /// <summary>
        /// Generates a method that does type conversion and calls the bound method.
        /// </summary>
        /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
        /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
        /// <returns> A delegate that does type conversion and calls the method represented by this
        /// object. </returns>
        protected override void GenerateStub(ILGenerator generator, int argumentCount)
        {
            // Check for the correct number of arguments.
            if (argumentCount != 0)
            {
                EmitHelpers.EmitThrow(generator, "TypeError", "Wrong number of arguments");
                EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
                generator.Complete();
                return;
            }

            if (this.field.IsStatic == false)
            {
                generator.LoadArgument(1);
                ClrBinder.EmitConversionToType(generator, this.field.DeclaringType, convertToAddress: true);
            }
            generator.LoadField(this.field);
            ClrBinder.EmitConversionToObject(generator, this.field.FieldType);
            generator.Complete();
        }
예제 #25
0
 /// <summary>
 /// Generates a method that does type conversion and calls the bound method.
 /// </summary>
 /// <param name="generator"> The ILGenerator used to output the body of the method. </param>
 /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param>
 /// <returns> A delegate that does type conversion and calls the method represented by this
 /// object. </returns>
 protected override void GenerateStub(ILGenerator generator, int argumentCount)
 {
     // Check for the correct number of arguments.
     if (argumentCount != 1)
     {
         EmitHelpers.EmitThrow(generator, ErrorType.TypeError, "Wrong number of arguments");
         EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any);
         generator.Complete();
         return;
     }
     if (this.field.IsStatic == false)
     {
         generator.LoadArgument(1);
         ClrBinder.EmitConversionToType(generator, this.field.DeclaringType, convertToAddress: true);
     }
     generator.LoadArgument(2);
     generator.LoadInt32(0);
     generator.LoadArrayElement(typeof(object));
     ClrBinder.EmitConversionToType(generator, this.field.FieldType, convertToAddress: false);
     generator.StoreField(this.field);
     EmitHelpers.EmitUndefined(generator);
     generator.Complete();
 }