Exemple #1
0
        private static JsFunction WrapSetFieldCore(FieldInfo field)
        {
            if (field == null)
                throw new ArgumentNullException("field");

            var builder = new Builder();

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

            var local = builder.AddLocal(typeof(object), "value");

            builder.AddStatement(Expression.Assign(
                local,
                Expression.ArrayAccess(
                    argumentsParameter,
                    Expression.Constant(0)
                )
            ));

            // Can't assign to constants.

            if (!field.IsLiteral && !field.IsInitOnly)
            {
                builder.AddStatement(Expression.Assign(
                    Expression.Field(
                        builder.MarshalThis(field.DeclaringType, field.IsStatic),
                        field
                    ),
                    builder.Marshal(local, field.FieldType)
                ));
            }

            builder.AddStatement(local);

            return builder.Compile<JsFunction>();
        }
Exemple #2
0
        private static JsFunction WrapSetPropertyCore(PropertyInfo property)
        {
            var builder = new Builder();

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

            var method = property.GetSetMethod();

            var local = builder.AddLocal(typeof(object), "value");

            builder.AddStatement(Expression.Assign(
                local,
                Expression.ArrayAccess(
                    argumentsParameter,
                    Expression.Constant(0)
                )
            ));

            builder.AddStatement(Expression.Assign(
                Expression.Property(
                    builder.MarshalThis(method.DeclaringType, method.IsStatic),
                    property
                ),
                builder.Marshal(
                    local,
                    property.PropertyType
                )
            ));

            builder.AddStatement(local);

            return builder.Compile<JsFunction>();
        }
Exemple #3
0
        private static JsFunction WrapMethodCore(MethodInfo method)
        {
            var builder = new Builder();

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

            var methodThis = builder.MarshalThis(method.DeclaringType, method.IsStatic);

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

            var outParameters = new List<Tuple<ParameterInfo, ParameterExpression, int>>();
            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)
                );

                // If this is a ref or out parameter, we need to create a local.

                if (parameter.ParameterType.IsByRef)
                {
                    var parameterType = parameter.ParameterType.GetElementType();

                    argument = builder.Marshal(argument, parameterType);

                    // Create a local to hold the value.

                    var tmpLocal = builder.AddLocal(
                        parameterType,
                        "tmp"
                    );

                    // Add the assignment to the statements.

                    builder.AddStatement(Expression.Assign(tmpLocal, argument));

                    // And use the temp local as the parameter.

                    argument = tmpLocal;

                    // Register it so that we do a write-back later on.

                    outParameters.Add(Tuple.Create(parameter, tmpLocal, index));
                }
                else
                {
                    argument = builder.Marshal(argument, parameter.ParameterType);
                }

                // Add the argument to the list.

                arguments.Add(argument);

                // Move on to the next argument.

                index++;
            }

            // Call the method.

            Expression methodCall = Expression.Call(
                methodThis,
                method,
                arguments
            );

            // Are we returning a value?

            ParameterExpression returnLocal = null;

            if (method.ReturnType != typeof(void))
            {
                returnLocal = builder.AddLocal(method.ReturnType, "return");

                methodCall = Expression.Assign(
                    returnLocal,
                    methodCall
                );
            }

            // Add the method call to the statements.

            builder.AddStatement(methodCall);

            // Process any out parameters.

            foreach (var outParameter in outParameters)
            {
                // Put the result back into the arguments array if the array
                // is long enough.

                builder.AddStatement(Expression.IfThen(
                    Expression.GreaterThan(
                        Expression.ArrayLength(argumentsParameter),
                        Expression.Constant(outParameter.Item3)
                    ),
                    Expression.Assign(
                        Expression.ArrayAccess(
                            argumentsParameter,
                            Expression.Constant(outParameter.Item3)
                        ),
                        Expression.Call(
                            builder.Marshaller,
                            _marshalClr.MakeGenericMethod(outParameter.Item1.ParameterType.GetElementType()),
                            outParameter.Item2
                        )
                    )
                ));
            }

            // Create the result.

            builder.AddStatement(
                returnLocal != null
                ? builder.UnMarshal(returnLocal, method.ReturnType)
                : Expression.Field(null, typeof(JsUndefined).GetField("Instance"))
            );

            return builder.Compile<JsFunction>();
        }