private static JToken JObjectToWrappedJToken(CefV8Value cefV8Value)
        {
            var jObjectWrapper = new JObject();
            var jObjectPayload = new JObject();
            var adapter        = V8PluginAdapter.FromCefObject(cefV8Value);

            if (adapter != null)
            {
                // Send JObject that defines a reference to the plugin
                jObjectWrapper.Add("__type__", "reference");
                jObjectPayload.Add("id", adapter.Plugin.Descriptor.PluginId);
                jObjectWrapper.Add("__payload__", jObjectPayload);
            }
            else
            {
                // Not a plugin, serialize all fields to a structure in json
                var keys = cefV8Value.GetKeys();
                foreach (var fieldKey in keys)
                {
                    var value = cefV8Value.GetValue(fieldKey);
                    if (!value.IsFunction)
                    {
                        var fieldToken = ToJToken(value);
                        jObjectWrapper.Add(fieldKey, fieldToken);
                    }
                }
            }

            return(jObjectWrapper);
        }
        public static object ToNative(CefV8Value obj, Type targetType)
        {
            if (obj == null)
            {
                throw new ArgumentNullException("obj");
            }
            if (targetType == null)
            {
                throw new ArgumentNullException("targetType");
            }

            object retVal = null;

            if ((targetType == typeof(JObject) && obj.IsObject) ||
                (targetType == typeof(JArray) && obj.IsArray) ||
                targetType == typeof(JValue) ||
                targetType == typeof(JToken))
            {
                retVal = CefJsonValueConverter.ToJToken(obj);
            }
            else if (!obj.IsNull && !obj.IsUndefined)
            {
                if (obj.IsBool)
                {
                    retVal = obj.GetBoolValue();
                }
                else if (obj.IsDouble || obj.IsInt || obj.IsUInt)
                {
                    // CEF doesn't have a long data type so they are treated as doubles
                    // To avoid overflow scenarios, IsDouble must be checked before IsInt because flags will be true
                    retVal = obj.GetDoubleValue();
                }
                else if (obj.IsString)
                {
                    retVal = obj.GetStringValue();
                }
                else if (obj.IsDate)
                {
                    retVal = obj.GetDateValue();
                }
                else if (obj.IsArray)
                {
                    if (targetType.IsArray)
                    {
                        if (targetType.GetArrayRank() != 1)
                        {
                            throw new Exception("Cannot handle multidimensional arrays");
                        }

                        var v8ArrayLength = obj.GetArrayLength();
                        var elementType   = targetType.GetElementType();
                        var array         = Array.CreateInstance(elementType, v8ArrayLength);
                        for (var v8ArrayIndex = 0; v8ArrayIndex < v8ArrayLength; ++v8ArrayIndex)
                        {
                            var elementToken = ToNative(obj.GetValue(v8ArrayIndex), elementType);
                            array.SetValue(elementToken, v8ArrayIndex);
                        }

                        retVal = array;
                    }
                }
                else if (obj.IsObject)
                {
                    var pluginAdapter = V8PluginAdapter.FromCefObject(obj);
                    if (pluginAdapter != null)
                    {
                        throw new Exception("Passing plugins as parameters not yet supported");
                    }

                    var converter = GetTypeConverter(targetType);
                    if (converter != null)
                    {
                        retVal = converter.ToNative(obj);
                    }
                }
                else if (obj.IsFunction)
                {
                    // TODO : Throw an exception?
                }

                if (retVal != null && !targetType.IsInstanceOfType(retVal))
                {
                    retVal = Convert.ChangeType(retVal, targetType);
                }
            }

            return(retVal);
        }