예제 #1
0
        private static JsFunction WrapDelegate(Delegate @delegate)
        {
            var builder = new Builder();

            builder.AddRuntimeParameter();
            builder.AddThisParameter(typeof(object));
            builder.AddParameter(typeof(JsObject), "callee");
            var argumentsParameter = builder.AddParameter(typeof(object[]), "arguments");

            var method = @delegate.Method;

            var arguments = new List<Expression>();

            var parameters = method.GetParameters();
            bool skipFirst = false;

            if (parameters.Length > 0 && typeof(JsGlobal).IsAssignableFrom(parameters[0].ParameterType))
            {
                skipFirst = true;
                arguments.Add(builder.Global);
            }

            int index = 0;

            foreach (var parameter in parameters)
            {
                // Skip over the global parameter.

                if (skipFirst)
                {
                    skipFirst = false;
                    continue;
                }

                // Get the argument from the array, or undefined there is none.

                Expression argument = Expression.Condition(
                    Expression.GreaterThan(
                        Expression.ArrayLength(argumentsParameter),
                        Expression.Constant(index)
                    ),
                    Expression.ArrayAccess(
                        argumentsParameter,
                        Expression.Constant(index)
                    ),
                    Expression.Field(null, typeof(JsUndefined).GetField("Instance")),
                    typeof(object)
                );

                // Add the argument to the list.

                arguments.Add(builder.Marshal(argument, parameter.ParameterType));

                // Move on to the next argument.

                index++;
            }

            // Call the delegate.

            builder.AddStatement(builder.UnMarshalReturn(
                Expression.Invoke(
                    Expression.Constant(@delegate),
                    arguments
                ),
                method.ReturnType
            ));

            return builder.Compile<JsFunction>();
        }