[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/cleverphp/cefpython/cefpython31/cefpython/v8utils_cef1.pyx [Back]  [Original]

# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved.
# License: New BSD License.
# Website: http://code.google.com/p/cefpython/

# CefV8 Objects, Arrays and Functions can be created or modified only 
# inside V8 context, you need to call CefV8Context::Enter() and 
# CefV8Context::Exit(), see:
# http://code.google.com/p/chromiumembedded/issues/detail?id=203

cdef list CefV8StackTraceToPython(CefRefPtr[CefV8StackTrace] cefTrace):
    cdef int frameNumber
    cdef int frameCount = cefTrace.get().GetFrameCount()
    cdef CefRefPtr[CefV8StackFrame] cefFrame
    cdef CefV8StackFrame* framePtr
    cdef list pyTrace = []

    for frameNumber in range(0, frameCount):
        cefFrame = cefTrace.get().GetFrame(frameNumber)
        framePtr = cefFrame.get()
        pyFrame = {}
        pyFrame["script"] = CefToPyString(framePtr.GetScriptName())
        pyFrame["scriptOrSourceUrl"] = CefToPyString(
                framePtr.GetScriptNameOrSourceURL())
        pyFrame["function"] = CefToPyString(framePtr.GetFunctionName())
        pyFrame["line"] = framePtr.GetLineNumber()
        pyFrame["column"] = framePtr.GetColumn()
        pyFrame["isEval"] = framePtr.IsEval()
        pyFrame["isConstructor"] = framePtr.IsConstructor()
        pyTrace.append(pyFrame)

    return pyTrace

cpdef list GetJavascriptStackTrace(int frameLimit=100):
    assert IsThread(TID_UI), (
            "cefpython.GetJavascriptStackTrace() may only be called on the UI thread")
    cdef CefRefPtr[CefV8StackTrace] cefTrace = (
            cef_v8_stack_trace.GetCurrent(frameLimit))
    return CefV8StackTraceToPython(cefTrace)

cpdef str FormatJavascriptStackTrace(list stackTrace):
    cdef str formatted = ""
    cdef dict frame
    for frameNumber, frame in enumerate(stackTrace):
        formatted += "\t[%s] %s() in %s on line %s (col:%s)\n" % (
                frameNumber,
                frame["function"],
                frame["scriptOrSourceUrl"],
                frame["line"],
                frame["column"])
    return formatted

cdef object V8ToPyValue(
        CefRefPtr[CefV8Value] v8Value,
        CefRefPtr[CefV8Context] v8Context,
        int nestingLevel=0):

    # With nestingLevel > 10 we get system exceptions.
    if nestingLevel > 8:
        raise Exception("V8ToPyValue() failed: data passed from Javascript to "
                "Python has more than 8 levels of nesting, this is probably an infinite "
                "recursion, stopping.")

    cdef CefV8Value* v8ValuePtr = v8Value.get()
    cdef CefString cefString
    cdef CefString cefFuncName
    cdef cpp_vector[CefString] keys
    cdef cpp_vector[CefString].iterator iterator

    cdef list pyArray
    cdef int callbackId
    cdef dict pyDict

    # A test against IsArray should be done before IsObject().
    if v8ValuePtr.IsArray():
        pyArray = []
        for key in range(0, v8ValuePtr.GetArrayLength()):
            pyArray.append(V8ToPyValue(
                    v8ValuePtr.GetValue(int(key)),
                    v8Context,
                    nestingLevel+1))
        return pyArray
    elif v8ValuePtr.IsBool():
        return v8ValuePtr.GetBoolValue()
    elif v8ValuePtr.IsDate():
        # TODO: convert it to string with no error.
        raise Exception("V8ToPyValue() failed: Date object is not supported, "
                "you are not allowed to pass it from Javascript to Python.")
    elif v8ValuePtr.IsInt():
        # A check against IsInt() must be done before IsDouble(), as any js integer
        # returns true when calling IsDouble().
        return v8ValuePtr.GetIntValue()
    elif v8ValuePtr.IsUInt():
        return v8ValuePtr.GetUIntValue()
    elif v8ValuePtr.IsDouble():
        return v8ValuePtr.GetDoubleValue()
    elif v8ValuePtr.IsFunction():
        callbackId = PutV8JavascriptCallback(v8Value, v8Context)
        return JavascriptCallback(callbackId)
    elif v8ValuePtr.IsNull():
        return None
    elif v8ValuePtr.IsObject():
        # A test against IsObject() should be done after IsArray().
        # Remember about increasing the nestingLevel.
        v8ValuePtr.GetKeys(keys)
        iterator = keys.begin()
        pyDict = {}
        while iterator != keys.end():
            cefString = deref(iterator)
            key = CefToPyString(cefString)
            value = V8ToPyValue(
                    v8ValuePtr.GetValue(cefString),
                    v8Context,
                    nestingLevel+1)
            pyDict[key] = value
            preinc(iterator)
        return pyDict
    elif v8ValuePtr.IsString():
        return CefToPyString(v8ValuePtr.GetStringValue())
    elif v8ValuePtr.IsUndefined():
        return None
    else:
        raise Exception("V8ToPyValue() failed: unknown type of CefV8Value.")

# Any function calling PyToV8Value must be inside that v8Context,
# check current context and call Enter if required otherwise exception is
# thrown while trying to create an array, object or function.

cdef CefRefPtr[CefV8Value] PyToV8Value(
        object pyValue,
        CefRefPtr[CefV8Context] v8Context,
        int nestingLevel=0) except *:

    # With nestingLevel > 10 we get system exceptions.
    if nestingLevel > 8:
        raise Exception("PyToV8Value() failed: data passed from Python "
                "to Javascript has more than 8 levels of nesting, this is probably "
                "an infinite recursion, stopping.")

    cdef cpp_bool sameContext
    if g_debug:
        sameContext = v8Context.get().IsSame(cef_v8_static.GetCurrentContext())
        if not sameContext:
            raise Exception("PyToV8Value() called in wrong v8 context")

    cdef CefString cefString
    cdef CefRefPtr[CefV8Value] v8Value
    cdef CefString cefFuncName
    cdef type pyValueType = type(pyValue)

    if pyValueType == tuple:
        pyValue = list(pyValue)

    # Check type again, as code above may have changed it.
    pyValueType = type(pyValue)

    cdef int index
    cdef object value
    cdef CefRefPtr[V8FunctionHandler] v8FunctionHandler
    cdef CefRefPtr[CefV8Handler] v8Handler
    cdef int callbackId
    cdef object key

    if pyValueType == list:
        v8Value = cef_v8_static.CreateArray(len(pyValue))
        for index,value in enumerate(pyValue):
            v8Value.get().SetValue(
                    index,
                    PyToV8Value(value, v8Context, nestingLevel+1))
        return v8Value
    elif pyValueType == bool:
        return cef_v8_static.CreateBool(bool(pyValue))
    elif pyValueType == int:
        return cef_v8_static.CreateInt(int(pyValue))
    elif pyValueType == long:
        # Int32 range is -2147483648..2147483647, we've increased the
        # minimum size by one as Cython was throwing a warning:
        # "unary minus operator applied to unsigned type, result still 
        # unsigned".
        if pyValue = -2147483647:
            return cef_v8_static.CreateInt(int(pyValue))
        else:
            PyToCefString(str(pyValue), cefString)
            return cef_v8_static.CreateString(cefString)
    elif pyValueType == float:
        return cef_v8_static.CreateDouble(float(pyValue))
    elif pyValueType == types.FunctionType or pyValueType == types.MethodType:
        v8FunctionHandler = new V8FunctionHandler()
        v8FunctionHandler.get().SetContext(v8Context)
        v8Handler = v8FunctionHandler.get()
        PyToCefString(pyValue.__name__, cefFuncName)
         # V8PythonCallback.
        v8Value = cef_v8_static.CreateFunction(cefFuncName, v8Handler)
        callbackId = PutPythonCallback(pyValue)
        v8FunctionHandler.get().SetCallback_RemovePythonCallback(
                RemovePythonCallback)
        v8FunctionHandler.get().SetPythonCallbackID(callbackId)
        return v8Value
    elif pyValueType == type(None):
        return cef_v8_static.CreateNull()
    elif pyValueType == dict:
        v8Value = cef_v8_static.CreateObject(NULL)
        for key, value in pyValue.items():
            # A dict may have an int key, a string key or even a tuple key:
            # {0: 12, '0': 12, (0, 1): 123}
            # Remember about increasing nestingLevel.
            PyToCefString(str(key), cefString)
            v8Value.get().SetValue(
                    cefString,
                    PyToV8Value(value, v8Context, nestingLevel+1),
                    V8_PROPERTY_ATTRIBUTE_NONE)
        return v8Value
    elif pyValueType == bytes or pyValueType == str \
            or (PY_MAJOR_VERSION < 3 and pyValueType == unicode):
        # The unicode type is not defined in Python 3.
        PyToCefString(pyValue, cefString)
        return cef_v8_static.CreateString(cefString)
    elif pyValueType == type:
        PyToCefString(str(pyValue), cefString)
        return cef_v8_static.CreateString(cefString)
    else:
        raise Exception("PyToV8Value() failed: an unsupported python type "
                "was passed from python to javascript: %s, value: %s"
                % (pyValueType.__name__, pyValue))

Web Proxy Viewer  |  New URL  |  Original Page