コード例 #1
0
        private static void EmitInvoker(EmitHelper emit, MethodInfo method, int?argc, bool setter)
        {
            var parameters = method.GetParameters();
            var methodArgC = parameters.Length;

            if (!argc.HasValue)
            {
                EmitThrowIfArgumentCountMismatch(emit, methodArgC);
                argc = methodArgC;
            }

            emit.LdArg(retvalArgIndex);

            // instance method
            if (!method.IsStatic)
            {
                emit.LdArg(objArgIndex);
            }

            // prepare arguments
            for (var i = 0; i < parameters.Length; i++)
            {
                var parameter = parameters[i];

                if (i < argc.Value)
                {
                    var changeTypeMethod = CefConvert.GetChangeTypeMethod(typeof(cef_v8value_t *), parameter.ParameterType);

                    EmitLdV8Argument(emit, i);
                    emit.Call(changeTypeMethod);
                }
                else
                {
                    // push default arg
                    if (!parameter.IsOptional)
                    {
                        throw new JSBindingException("MethodInvoker compilation error.");
                    }

                    EmitLdRawDefaultValue(emit, parameter.RawDefaultValue);
                }
            }

            // call target method
            if (method.IsStatic)
            {
                emit.Call(method);
            }
            else
            {
                emit.CallVirt(method);
            }


            if (method.ReturnType == typeof(void))
            {
                // If method is setter, then it can be called with retval == null from V8Accessor.
                if (setter)
                {
                    var returnValueLabel = emit.DefineLabel();

                    emit.Dup()
                    .BrTrueS(returnValueLabel)
                    .Pop()
                    .Ret()
                    .MarkLabel(returnValueLabel);
                    ;
                }

                if (ForceVoidToUndefined)
                {
                    emit.Call(createUndefinedNativeV8ValueMethod);
                }
                else
                {
                    emit.LdNull();
                }
            }
            else
            {
                // convert return value
                var retValchangeTypeMethod = CefConvert.GetChangeTypeMethod(method.ReturnType, typeof(cef_v8value_t *));
                emit.Call(retValchangeTypeMethod);
            }

            // store result at retval
            emit.StIndI();

            // return
            emit.Ret();
        }
コード例 #2
0
        private static object InvokeScript(CefV8Context context, string memberName, params object[] args)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (!context.Enter())
            {
                throw new CefException("Failed to enter V8 context.");
            }
            try
            {
                // TODO: this list can be private list of context, 'cause we can invoke only one function at one time
                List <CefV8Value> proxies = new List <CefV8Value>(16);

                // javascript 'this' object
                CefV8Value obj = null;

                CefV8Value target = context.GetGlobal();
                proxies.Add(target);
                if (!memberName.Contains('.'))
                {
                    obj    = target;
                    target = obj.GetValue(memberName);
                    proxies.Add(target);
                }
                else
                {
                    foreach (var member in memberName.Split('.'))
                    {
                        obj    = target;
                        target = obj.GetValue(member); // TODO: do analysis of target - if it is not an object - throw
                        if (!target.IsObject)
                        {
                            throw new CefException("Argument 'memberName' must be member access expression to a function. Invalid object in path.");
                        }
                        proxies.Add(target);
                    }
                }
                if (!target.IsFunction)
                {
                    throw new ArgumentException("Argument 'memberName' must be member access expression to a function.");
                }

                CefV8Value[] v8Args;

                if (args.Length == 0)
                {
                    v8Args = null;
                }
                else
                {
                    v8Args = new CefV8Value[args.Length]; // TODO: InvokeScript core can be optimized by prevent recreating arrays
                    for (var i = 0; i < args.Length; i++)
                    {
                        var value = CefConvert.ToV8Value(args[i]);
                        v8Args[i] = value;
                    }
                }

                var v8RetVal = target.ExecuteFunctionWithContext(context, obj, v8Args);

                // force destroing of proxies, to avoid unneccessary GC load (CLR and V8)
                foreach (var proxy in proxies)
                {
                    proxy.Dispose();
                }

                proxies.Clear();

                // FIXME: not sure if exception CAN be null, this need to be checked
                if (v8RetVal.HasException)
                {
                    var exception = v8RetVal.GetException();
                    throw new JavaScriptException(exception.GetMessage());
                }

                //if (!string.IsNullOrEmpty(exception))


                var result = CefConvert.ToObject(v8RetVal);
                v8RetVal.Dispose();
                return(result);
            }
            finally
            {
                if (!context.Exit())
                {
                    throw new CefException("Failed to exit V8 context.");
                }
            }
        }