According to the ECMAScript [1] standard, we need enter an execution context before execute any script code.
JSContext is a sandboxed execution context with its own set of built-in objects and functions.
You could create a JSContext instance, enter it with JSContext.enter(), and use it to execute code with JSContext.eval(). The best practice is to leave the context with JSContext.leave() if you never need it.
>>> ctxt = JSContext() # create a context with an implicit global object
>>> ctxt.enter() # enter the context (also support with statement)
>>> ctxt.eval("1+2") # evalute the javascript expression and return a native python int
3
>>> ctxt.leave() # leave the context and release the related resources
Note
To ensure the context could be enter/leave at the right time, we suggest to use the with statement (Python 2.5 or later).
with JSContext() as ctxt: print ctxt.eval("1+2") # 3
You could also check the current or calling context with the static properties.
Property | Description |
---|---|
JSContext.current | The context that is on the top of the stack. |
JSContext.entered | The last entered context. |
JSContext.calling | The context of the calling JavaScript code. |
JSContext.inContext | Returns true if V8 has a current context. |
The execution context has a global object, which could be access from the Python side with JSContext.locals, or access from the Javascript side with the global namespace. The Python and Javascript code could use it to do seamless interoperable logic, PyV8 will automatic do the Type Conversion, Function Call and Exception Translation.
with JSContext() as ctxt:
ctxt.eval("a = 1")
print ctxt.locals.a # 1
ctxt.locals.a = 2
print ctxt.eval("a") # 2
If you want to provide more complicated properties and methods to the Javascript code, you could pass a customized global object instance when create the JSContext.
class Global(JSClass):
version = "1.0"
def hello(self, name):
return "Hello " + name
with JSContext(Global()) as ctxt:
print ctxt.eval("version") # 1.0
print ctxt.eval("hello('World')") # Hello World
print ctxt.eval("hello.toString()") # function () { [native code] }
Note
If you want your global object more like a real Javascript object, you should inherit from the JSClass which provides a lot of helper methods such as JSClass.toString(), JSClass.watch() etc.
Besides the customized Global Object, there is a more powerful mechanism JSExtension which could encapsulate the related Javascript or Python script in a reusable module, and define it when create a JSContext instance.
src = 'function hello(name) { return "Hello " + name + " from Javascript"; }'
ext = JSExtension("hello/javascript", src)
with JSContext(extensions=['hello/javascript']) as ctxt:
print ctxt.eval("hello('World')") # Hello World from Javascript
The extension also could be implement with the Python code, just like the JNI [3] for the Java.
src = "native function hello();"
ext = JSExtension("hello/python", src, lambda func: lambda name: "Hello " + name + " from Python")
with JSContext(extensions=['hello/python']) as ctxt:
print ctxt.eval("hello('World')") # Hello World from Python
If your extensions has dependencies extensions, you could define it in JSExtension.__init__(), and check it later with the JSExtension.dependencies property. The v8 engine will load the extensions one by one base on its dependencies.
JSContext is an execution context.
Parameters: | ctxt (JSContext) – an exists JSContext instance |
---|---|
Return type: | a cloned JSContext instance |
eval( (JSContext)arg1, (str)source [, (str)name=’’ [, (int)line=-1 [, (int)col=-1 [, (object)precompiled=None]]]]) -> object :
- C++ signature :
- class boost::python::api::object eval(class CContext {lvalue},class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > [,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >=’’ [,int=-1 [,int=-1 [,class boost::python::api::object=None]]]])
eval( (JSContext)arg1, (unicode)source [, (unicode)name=u’’ [, (int)line=-1 [, (int)col=-1 [, (object)precompiled=None]]]]) -> object :
- C++ signature :
- class boost::python::api::object eval(class CContext {lvalue},class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> > [,class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> >=u’’ [,int=-1 [,int=-1 [,class boost::python::api::object=None]]]])
Execute the Javascript code in source and return the result
Parameters: | |
---|---|
Return type: | the result |
The context that is on the top of the stack.
The last entered context.
The context of the calling JavaScript code.
Returns true if V8 has a current context.
Enter this context. After entering a context, all code compiled and run is compiled and run in this context.
Exit this context. Exiting the current context restores the context that was in place when entering the current context.
Local variables within context
JSExtension is a reusable script module.
__init__( (object)arg1, (str)name, (str)source [, (object)callback=None [, (list)dependencies=[] [, (bool)register=True]]]) -> None :
- C++ signature :
- void __init__(struct _object *,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > [,class boost::python::api::object=None [,class boost::python::list=[] [,bool=True]]])
Parameters: | |
---|---|
Return type: | A reusable JSExtension module |
Register the extension
Enable the extension by default.
The extension dependencies which will be load before this extension
The name of extension
The extension has been registerd
The source code of extension
Footnotes
[1] | ECMAScript is the scripting language standardized by Ecma International in the ECMA-262 specification and ISO/IEC 16262. The language is widely used for client-side scripting on the web, in the form of several well-known dialects such as JavaScript, JScript, and ActionScript. |
[2] | There are three types of ECMAScript executable code:
|
[3] | Java Native Interface (JNI) is a programming framework that enables Java code running in a Java Virtual Machine (JVM) to call and to be called[1] by native applications (programs specific to a hardware and operating system platform) and libraries written in other languages such as C, C++ and assembly. |