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>(); }