Exemplo n.º 1
0
        /// <summary>
        /// Logs method invocation information
        /// </summary>
        private void LogMethodInvocationInfo(HostMethod method, object instance)
        {
            var parameters = method.Parameters;

            var str = new StringBuilder();

            str.Append($"Exception Invoking: [Method: {method.Method.Name}]");
            str.Append("\n[Parameters]\n");
            for (var ii = 0; ii < parameters.Length; ++ii)
            {
                var p = parameters[ii];
                str.Append($"  [Name: {p.Name}, Type: {p.ParameterType}, Optional: {p.IsOptional}");

                if (p.IsOptional)
                {
                    str.Append($", Default: {p.DefaultValue}");
                }

                str.Append("]\n");
            }

            str.Append("[Object Instance: ").Append(instance).Append("]");

            Log.Info(this, str.ToString());
        }
Exemplo n.º 2
0
        /// <summary>
        /// Regular serial parameter passing.
        /// </summary>
        private object[] ToSerialParameters(HostMethod method, JavaScriptValue[] args, ushort argCount)
        {
            var totalParameters = argCount - 1;
            var parameters      = method.Parameters;
            var realParams      = new object[parameters.Length];

            var argIndex = 1;

            for (int j = 0; j < parameters.Length; ++j)
            {
                var param = parameters[j];

                // If we run out of JS parameters passed in compared to the total number of host parameters,
                // we have either picked the wrong method or the host method has optional parameters with defaults.
                if (argIndex >= argCount)
                {
                    if (!param.IsOptional)
                    {
                        Log.Warning(this, "Interop chose the wrong method to execute. Too few JS parameters, no optional C# parameters.");
                        break;
                    }

                    realParams[j] = param.DefaultValue;
                }
                else
                {
                    var arg = args[argIndex++];
                    realParams[j] = _interop.ToHostObject(arg, param.ParameterType);
                }
            }

            return(realParams);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Generates a parameter array based on the target method parameters.
        /// </summary>
        private object[] ToParameters(HostMethod method, JavaScriptValue[] args, ushort argCount)
        {
            // Build the parameters up to params, then build params
            if (method.IsVarArgs)
            {
                return(ToVarArgParams(method, args, argCount));
            }

            return(ToSerialParameters(method, args, argCount));
        }
Exemplo n.º 4
0
 /// <inheritdoc/>
 public bool TryGetInvocation(string invokeKey, out HostMethod method) => _methodInvocations.TryGetValue(invokeKey, out method);
Exemplo n.º 5
0
 /// <inheritdoc/>
 public void CacheInvocation(string invokeKey, HostMethod method) => _methodInvocations[invokeKey] = method;
Exemplo n.º 6
0
        /// <summary>
        /// Handles the scenario with variable arguments in the host method via <c>params</c>.
        /// </summary>
        private object[] ToVarArgParams(HostMethod method, JavaScriptValue[] args, ushort argCount)
        {
            if (!method.IsVarArgs)
            {
                throw new Exception("Not a variable argument parameter set");
            }

            var totalParameters = argCount - 1;
            var parameters      = method.Parameters;
            var realParams      = new object[parameters.Length];

            var vaIndex = method.VarArgIndex;
            var vaType  = method.VarArgType;

            // Non VarArg Parameters
            var argIndex   = 1;
            var paramIndex = 0;

            for (int j = 0; j < vaIndex; ++j)
            {
                var param = parameters[j];

                // If we run out of JS parameters passed in compared to the total number of host parameters,
                // we have either picked the wrong method or the host method has optional parameters with defaults.
                if (argIndex >= argCount)
                {
                    if (!param.IsOptional)
                    {
                        Log.Warning(this, "Interop chose the wrong method to execute. Too few JS parameters, no optional C# parameters.");
                        break;
                    }

                    realParams[paramIndex++] = param.DefaultValue;
                }
                else
                {
                    var arg = args[argIndex++];
                    realParams[paramIndex++] = _interop.ToHostObject(arg, param.ParameterType);
                }
            }

            // Determine if we have enough JS parameters to put into var args
            if (vaIndex > totalParameters)
            {
                realParams[paramIndex++] = Array.CreateInstance(vaType, 0);

                return(realParams);
            }

            // Put remaining JS args into var args
            var remainingLength = totalParameters - vaIndex;
            var paramsArray     = Array.CreateInstance(vaType, remainingLength);

            for (var j = 0; j < remainingLength; ++j)
            {
                var arg = args[argIndex++];
                paramsArray.SetValue(_interop.ToHostObject(arg, vaType), j);
            }

            // Set last parameter to var arg array
            realParams[paramIndex++] = paramsArray;

            return(realParams);
        }
Exemplo n.º 7
0
        /// <summary>
        /// This method type checks each parameter passed by javascript to determine if the method is a suitable
        /// match for execution. At this point, we can assume that the provided arguments qualify for the method
        /// signature in terms of number of parameters, accounting for optional parameters and var args.
        /// </summary>
        private bool IsCompatibleMethod(HostMethod method, JavaScriptValue[] args, ushort argLength)
        {
            var parameters = method.Parameters;
            var isVarArg   = method.IsVarArgs;

            // Parameter Index Pointers - JS parameters include the callee at the first index, so we start after that
            var argIndex = 1;
            var pIndex   = 0;

            // The maximum number of iterations we'll have to run to complete type checking each parameter
            // This is typically parameters.Length unless there are optional parameters or var args
            var iterations = Math.Max(parameters.Length, argLength - 1);

            // Loop Max Argument Count
            while (iterations-- > 0)
            {
                // Case 1. We've Type Checked All JS Parameters Against C# Parameters
                if (argIndex >= argLength)
                {
                    // For a Var Arg C# Parameter Method, ensure we've indexed into the var arg index
                    if (isVarArg)
                    {
                        // If we haven't, then we ensure that we have an optional parameter. Otherwise,
                        // we're short JS parameters, so we can't call this method.
                        if (pIndex != method.VarArgIndex)
                        {
                            return(parameters[pIndex].IsOptional);
                        }

                        return(true);
                    }

                    // For methods without var args, we simply ensure we've typed checked against all required
                    // parameters.
                    if (pIndex < parameters.Length)
                    {
                        return(parameters[pIndex].IsOptional);
                    }

                    return(true);
                }

                // Case 2. We reach the end of C# Method Parameters, but still have JS Parameters left to check
                if (pIndex >= parameters.Length)
                {
                    // This case is only possible with var args (since the params []) counts as a single index
                    if (!method.IsVarArgs)
                    {
                        return(false);
                    }

                    // Ensure that pIndex stays at the var arg index for type checking the element type
                    pIndex = method.VarArgIndex;
                }

                // Case 3. TypeCheck JS Argument Against C# Parameter
                var arg       = args[argIndex];
                var parameter = parameters[pIndex];

                // For Var Args, we need to ensure that we use the var arg type to check against the JS arg.
                var paramType = (isVarArg && pIndex >= method.VarArgIndex)
                    ? method.VarArgType
                    : parameter.ParameterType;

                // Increment index pointers
                argIndex++;
                pIndex++;

                // Run type conversion checking, early return on failure
                if (!JsConversions.IsAssignable(arg, _binder, paramType))
                {
                    return(false);
                }
            }
            return(true);
        }