forked from cztomczak/cefpython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjavascript_callback_cef1.pyx
More file actions
123 lines (101 loc) · 5.13 KB
/
javascript_callback_cef1.pyx
File metadata and controls
123 lines (101 loc) · 5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# Copyright (c) 2012-2014 The CEF Python authors. All rights reserved.
# License: New BSD License.
# Website: http://code.google.com/p/cefpython/
cdef cpp_map[int, CefRefPtr[CefV8Value]] g_v8JavascriptCallbacks
cdef cpp_map[int, CefRefPtr[CefV8Context]] g_v8JavascriptCallbackContexts
# Next callbackId.
cdef int g_v8JavascriptCallbackCount = 0
cdef int PutV8JavascriptCallback(
CefRefPtr[CefV8Value] v8Value,
CefRefPtr[CefV8Context] v8Context) except *:
global g_v8JavascriptCallbacks
global g_v8JavascriptCallbackContexts
global g_v8JavascriptCallbackCount
g_v8JavascriptCallbackCount += 1
cdef int callbackId = g_v8JavascriptCallbackCount
g_v8JavascriptCallbacks[callbackId] = v8Value
g_v8JavascriptCallbackContexts[callbackId] = v8Context
return callbackId
cdef CefRefPtr[CefV8Value] GetV8JavascriptCallback(
int callbackId) except *:
global g_v8JavascriptCallbacks
if g_v8JavascriptCallbacks.find(callbackId) == g_v8JavascriptCallbacks.end():
raise Exception("GetV8JavascriptCallback() failed: invalid callbackId: %s"
% callbackId)
return g_v8JavascriptCallbacks[callbackId]
cdef CefRefPtr[CefV8Context] GetV8JavascriptCallbackContext(
int callbackId) except *:
global g_v8JavascriptCallbackContexts
if g_v8JavascriptCallbackContexts.find(callbackId) == g_v8JavascriptCallbackContexts.end():
raise Exception("GetV8JavascriptCallbackContext() failed: invalid callbackId: %s"
% callbackId)
return g_v8JavascriptCallbackContexts[callbackId]
cdef void DelV8JavascriptCallback(
int callbackId) except *:
global g_v8JavascriptCallbacks
global g_v8JavascriptCallbackContexts
g_v8JavascriptCallbacks.erase(callbackId)
g_v8JavascriptCallbackContexts.erase(callbackId)
cdef class JavascriptCallback:
cdef int callbackId
def __init__(self, int callbackId):
assert callbackId, "JavascriptCallback.__init__() failed: callbackId is empty"
self.callbackId = callbackId
def __dealloc__(self):
DelV8JavascriptCallback(self.callbackId)
def Call(self, *args):
cdef CefRefPtr[CefV8Value] v8Value = GetV8JavascriptCallback(self.callbackId)
cdef CefRefPtr[CefV8Context] v8Context = GetV8JavascriptCallbackContext(self.callbackId)
cdef CefV8ValueList v8Arguments
cdef CefRefPtr[CefV8Value] v8Retval
cdef CefRefPtr[CefV8Exception] v8Exception
cdef CefV8Exception* v8ExceptionPtr
cdef int i
# Javascript callback may be kept somewhere and later called from
# a different v8 frame context. Need to enter js v8 context before
# calling PyToV8Value().
cdef cpp_bool sameContext = v8Context.get().IsSame(cef_v8_static.GetCurrentContext())
if not sameContext:
Debug("JavascriptCallback.Call(): inside a different context, calling v8Context.Enter()")
assert v8Context.get().Enter(), "v8Context.Enter() failed"
for i in range(0, len(args)):
v8Arguments.push_back(PyToV8Value(args[i], v8Context))
if not sameContext:
assert v8Context.get().Exit(), "v8Context.Exit() failed"
v8Retval = v8Value.get().ExecuteFunctionWithContext(
v8Context,
<CefRefPtr[CefV8Value]>NULL,
v8Arguments)
cdef int lineNumber
cdef str message
cdef str scriptResourceName
cdef str sourceLine
cdef str stackTrace
# This exception should be first caught by V8ContextHandler::OnUncaughtException().
if v8Value.get().HasException():
v8Exception = v8Value.get().GetException()
v8ExceptionPtr = v8Exception.get()
lineNumber = v8ExceptionPtr.GetLineNumber()
message = CefToPyString(v8ExceptionPtr.GetMessage())
scriptResourceName = CefToPyString(v8ExceptionPtr.GetScriptResourceName())
sourceLine = CefToPyString(v8ExceptionPtr.GetSourceLine())
stackTrace = FormatJavascriptStackTrace(GetJavascriptStackTrace(100))
# TODO: throw exceptions according to execution context (Issue 11),
# TODO: should we call v8ExceptionPtr.ClearException()? What if python
# code does try: except: to catch the exception below, if it's catched then
# js should execute further, like it never happened, and is ClearException()
# for that?
raise Exception("JavascriptCallback.Call() failed: javascript exception:\n"
"%s.\nOn line %s in %s.\n"
"Source of that line: %s\n\n%s"
% (message, lineNumber, scriptResourceName, sourceLine, stackTrace))
if <void*>v8Retval == NULL:
raise Exception("JavascriptCallback.Call() failed: ExecuteFunctionWithContext() "
"called incorrectly")
pyRet = V8ToPyValue(v8Retval, v8Context)
return pyRet
def GetName(self):
cdef CefRefPtr[CefV8Value] v8Value = GetV8JavascriptCallback(self.callbackId)
cdef CefString cefFuncName
cefFuncName = v8Value.get().GetFunctionName()
return CefToPyString(cefFuncName)