├── go.comm ├── go ├── .gitignore ├── MANIFEST.in ├── old-sm ├── jsvoid.pxi ├── spidermonkey.dep ├── jsint.pxi ├── jsruntime.pxi ├── jsdouble.pxi ├── jsbool.pxi ├── spidermonkey.pyx ├── jsstring.pxi ├── jsgc.pxi ├── jserror.pxi ├── jsarray.pxi ├── jsobject.pxi ├── jsvalue.pxi ├── jshash.pxi ├── jshelpers.c ├── jscontext.pxi └── jsfunction.pxi ├── spidermonkey ├── double.h ├── pyobject.h ├── integer.h ├── convert.h ├── pyiter.h ├── string.h ├── libjs │ ├── resource.h │ ├── jsmath.h │ ├── jsfile.h │ ├── jscompat.h │ ├── jsshell.msg │ ├── jsbool.h │ ├── jsstddef.h │ ├── jslog2.c │ ├── jsosdep.h │ ├── jsarray.h │ ├── prmjtime.h │ ├── jsutil.h │ ├── jsexn.h │ ├── jsdate.h │ ├── jsiter.h │ ├── jsclist.h │ ├── jsproto.tbl │ ├── jsdtoa.h │ ├── jshash.h │ ├── jsfun.h │ ├── jsprf.h │ └── jsutil.c ├── runtime.h ├── jsarray.h ├── jsfunction.h ├── jsiterator.h ├── error.h ├── jsobject.h ├── hashcobj.h ├── double.c ├── spidermonkey.h ├── context.h ├── integer.c ├── Darwin-i386 │ └── jsautocfg.h ├── Linux-i686 │ └── jsautocfg.h ├── Linux-x86_64 │ └── jsautocfg.h ├── string.c ├── spidermonkey.c ├── error.c ├── convert.c ├── hashcobj.c ├── runtime.c ├── jsarray.c ├── jsiterator.c └── jsfunction.c ├── tests ├── test-utf16.py ├── test-errors.py ├── test-syntax-error.py ├── test-python-ctor.py ├── test-roundtrip.py ├── test-runtime.py ├── test-iterate.py ├── test-to-python.py ├── test-py-lookup.py ├── test-context.py ├── test-object.py ├── t.py ├── test-function.py ├── test-global.py └── test-access.py ├── bin └── pymonkey ├── update-libjs.sh ├── THANKS ├── LICENSE ├── old-t └── class_test.py ├── README.md └── setup.py /go.comm: -------------------------------------------------------------------------------- 1 | run setup.py --debug test 2 | bt 3 | continue 4 | bt 5 | -------------------------------------------------------------------------------- /go: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | #python setup.py build 3 | gdb --command=go.comm --batch python 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gdb_history 2 | *.pyc 3 | *.so 4 | *.egg 5 | build/* 6 | dist/* 7 | tmp/* 8 | python_spidermonkey.egg-info/* 9 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include MANIFEST.in 2 | include LICENSE 3 | include README 4 | include ez_setup.py 5 | include go 6 | include go.comm 7 | include setup.py 8 | include spidermonkey/*.* 9 | include spidermonkey/libjs/*.* 10 | include tests/*.py 11 | -------------------------------------------------------------------------------- /old-sm/jsvoid.pxi: -------------------------------------------------------------------------------- 1 | 2 | def js_is_void(Context cx, jsval jsv): 3 | return JSVAL_IS_VOID(jsv) or jsv == 0 4 | 5 | def py_is_void(Context cx, object py_obj): 6 | return isinstance(py_obj, (types.NoneType)) 7 | 8 | cdef object js2py_void(Context cx, jsval jsv): 9 | return None 10 | 11 | cdef jsval py2js_void(Context cx, object py_obj, JSObject* parent): 12 | return JSVAL_VOID 13 | -------------------------------------------------------------------------------- /spidermonkey/double.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_DOUBLE_H 10 | #define PYSM_DOUBLE_H 11 | 12 | jsval py2js_double(Context* cx, PyObject* obj); 13 | PyObject* js2py_double(Context* cx, jsval val); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /old-sm/spidermonkey.dep: -------------------------------------------------------------------------------- 1 | include jsapi.pxi 2 | include jsarray.pxi 3 | include jsbool.pxi 4 | include jsclass.pxi 5 | include jscontext.pxi 6 | include jsdouble.pxi 7 | include jserror.pxi 8 | include jsfunction.pxi 9 | include jsgc.pxi 10 | include jshash.pxi 11 | include jsint.pxi 12 | include jsobject.pxi 13 | include jsruntime.pxi 14 | include jsstring.pxi 15 | include jsvalue.pxi 16 | include jsvoid.pxi 17 | -------------------------------------------------------------------------------- /old-sm/jsint.pxi: -------------------------------------------------------------------------------- 1 | 2 | def js_is_int(Context cx, jsval jsv): 3 | return JSVAL_IS_INT(jsv) 4 | 5 | def py_is_int(Context cx, object py_obj): 6 | return isinstance(py_obj, (types.IntType, types.LongType)) 7 | 8 | cdef object js2py_int(Context cx, jsval jsv): 9 | return JSVAL_TO_INT(jsv) 10 | 11 | cdef jsval py2js_int(Context cx, jsint py_obj, JSObject* parent): 12 | return INT_TO_JSVAL(py_obj) 13 | 14 | -------------------------------------------------------------------------------- /old-sm/jsruntime.pxi: -------------------------------------------------------------------------------- 1 | 2 | cdef class Runtime: 3 | cdef JSRuntime* rt 4 | 5 | def __cinit__(self): 6 | self.rt = JS_NewRuntime(1000000) 7 | if self.rt == NULL: 8 | raise JSError("Failed to create JavaScript Runtime.") 9 | 10 | def __dealloc__(self): 11 | JS_DestroyRuntime(self.rt) 12 | 13 | def create_context(self, root=None): 14 | cx = Context(self, root) 15 | return cx 16 | -------------------------------------------------------------------------------- /spidermonkey/pyobject.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_PYOBJECT_H 10 | #define PYSM_PYOBJECT_H 11 | 12 | /* 13 | This represents a Python object in the 14 | JavaScript VM. 15 | */ 16 | 17 | jsval py2js_object(Context* cx, PyObject* obj); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /tests/test-utf16.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | 7 | @t.cx() 8 | def test_empty_string_script(cx): 9 | cx.execute("") 10 | 11 | @t.cx() 12 | def test_unicode_string(cx): 13 | t.eq(cx.execute(u"5"), 5) 14 | 15 | @t.cx() 16 | def test_non_unicode_string(cx): 17 | t.eq(cx.execute("5"), 5) 18 | -------------------------------------------------------------------------------- /spidermonkey/integer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_INTEGER_H 10 | #define PYSM_INTEGER_H 11 | 12 | jsval py2js_integer(Context* cx, PyObject* obj); 13 | jsval long2js_integer(Context* cx, long val); 14 | PyObject* js2py_integer(Context* cx, jsval val); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /spidermonkey/convert.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_CONVERT_H 10 | #define PYSM_CONVERT_H 11 | 12 | jsval py2js(Context* cx, PyObject* obj); 13 | PyObject* js2py(Context* cx, jsval val); 14 | PyObject* js2py_with_parent(Context* cx, jsval val, jsval parent); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /spidermonkey/pyiter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_PYITER_H 10 | #define PYSM_PYITER_H 11 | 12 | /* 13 | This is a bit of glue between Python and JavaScript 14 | iterators. 15 | */ 16 | 17 | JSBool new_py_iter(Context* cx, PyObject* obj, jsval* rval); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /spidermonkey/string.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_STRING_H 10 | #define PYSM_STRING_H 11 | 12 | JSString* py2js_string_obj(Context* cx, PyObject* str); 13 | jsval py2js_string(Context* cx, PyObject* str); 14 | PyObject* js2py_string(Context* cx, jsval val); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /spidermonkey/libjs/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Developer Studio generated include file. 3 | // Used by js3240.rc 4 | // 5 | 6 | // Next default values for new objects 7 | // 8 | #ifdef APSTUDIO_INVOKED 9 | #ifndef APSTUDIO_READONLY_SYMBOLS 10 | #define _APS_NEXT_RESOURCE_VALUE 101 11 | #define _APS_NEXT_COMMAND_VALUE 40001 12 | #define _APS_NEXT_CONTROL_VALUE 1000 13 | #define _APS_NEXT_SYMED_VALUE 101 14 | #endif 15 | #endif 16 | -------------------------------------------------------------------------------- /bin/pymonkey: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Provides a command line REPL for python-spidermonkey.""" 4 | 5 | import sys 6 | import readline 7 | import spidermonkey 8 | 9 | PROMPT = 'js> ' 10 | 11 | def main(): 12 | rt = spidermonkey.Runtime() 13 | cx = rt.new_context() 14 | 15 | while True: 16 | cli = str(raw_input(PROMPT)) 17 | print '=>',cx.execute(cli) 18 | 19 | if __name__ == '__main__': 20 | try: 21 | main() 22 | except: 23 | sys.exit(0) 24 | -------------------------------------------------------------------------------- /spidermonkey/runtime.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_RUNTIME 10 | #define PYSM_RUNTIME 11 | 12 | #include 13 | #include "structmember.h" 14 | 15 | #include 16 | 17 | typedef struct { 18 | PyObject_HEAD 19 | JSRuntime* rt; 20 | } Runtime; 21 | 22 | extern PyTypeObject _RuntimeType; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /old-sm/jsdouble.pxi: -------------------------------------------------------------------------------- 1 | 2 | def js_is_double(Context cx, jsval jsv): 3 | return JSVAL_IS_DOUBLE(jsv) 4 | 5 | def py_is_double(Context cx, object py_obj): 6 | return isinstance(py_obj, types.FloatType) 7 | 8 | cdef object js2py_double(Context cx, jsval jsv): 9 | return JSVAL_TO_DOUBLE(jsv)[0] 10 | 11 | cdef jsval py2js_double(Context cx, double py_obj, JSObject* parent): 12 | cdef jsval ret 13 | if not JS_NewNumberValue(cx.cx, py_obj, &ret): 14 | raise JSError("Failed to convert double.") 15 | return ret 16 | -------------------------------------------------------------------------------- /old-sm/jsbool.pxi: -------------------------------------------------------------------------------- 1 | def js_is_bool(Context cx, jsval jsv): 2 | return JSVAL_IS_BOOLEAN(jsv) 3 | 4 | def py_is_bool(Context cx, object py_obj): 5 | return isinstance(py_obj, types.BooleanType) 6 | 7 | cdef object js2py_bool(Context cx, jsval jsv): 8 | if JSVAL_TO_BOOLEAN(jsv): 9 | return True 10 | else: 11 | return False 12 | 13 | cdef jsval py2js_bool(Context cx, object py_obj, JSObject* parent): 14 | if py_obj: 15 | return BOOLEAN_TO_JSVAL(JS_TRUE) 16 | else: 17 | return BOOLEAN_TO_JSVAL(JS_FALSE) 18 | -------------------------------------------------------------------------------- /old-sm/spidermonkey.pyx: -------------------------------------------------------------------------------- 1 | 2 | # Import API 3 | include "jsapi.pxi" 4 | 5 | # Basic Necessities 6 | include "jserror.pxi" 7 | include "jsgc.pxi" 8 | 9 | # Core Classes 10 | include "jsruntime.pxi" 11 | include "jscontext.pxi" 12 | 13 | # Adapters 14 | include "jsclass.pxi" 15 | include "jsobject.pxi" 16 | include "jsfunction.pxi" 17 | 18 | # Type Conversions 19 | include "jsarray.pxi" 20 | include "jsbool.pxi" 21 | include "jsdouble.pxi" 22 | include "jshash.pxi" 23 | include "jsint.pxi" 24 | include "jsstring.pxi" 25 | include "jsvoid.pxi" 26 | 27 | include "jsvalue.pxi" 28 | -------------------------------------------------------------------------------- /spidermonkey/jsarray.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_JSARRAY_H 10 | #define PYSM_JSARRAY_H 11 | 12 | /* 13 | This is a representation of a JavaScript 14 | Array in Python land. 15 | */ 16 | 17 | #include 18 | #include "structmember.h" 19 | 20 | #include "spidermonkey.h" 21 | 22 | extern PyTypeObject _ArrayType; 23 | 24 | PyObject* js2py_array(Context* cx, jsval val); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /spidermonkey/jsfunction.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_JSFUNCTION_H 10 | #define PYSM_JSFUNCTION_H 11 | 12 | /* 13 | This is a representation of a JavaScript 14 | Function in Python land. 15 | */ 16 | 17 | typedef struct { 18 | Object obj; 19 | jsval parent; 20 | } Function; 21 | 22 | extern PyTypeObject _FunctionType; 23 | 24 | PyObject* js2py_function(Context* cx, jsval val, jsval parent); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /spidermonkey/jsiterator.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_JSITERATOR_H 10 | #define PYSM_JSITERATOR_H 11 | 12 | /* 13 | This is a representation of a JavaScript 14 | object in Python land. 15 | */ 16 | 17 | typedef struct { 18 | PyObject_HEAD 19 | Context* cx; 20 | JSObject* iter; 21 | jsval root; 22 | } Iterator; 23 | 24 | extern PyTypeObject _IteratorType; 25 | 26 | PyObject* Iterator_Wrap(Context* cx, JSObject* obj); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /spidermonkey/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_ERROR_H 10 | #define PYSM_ERROR_H 11 | 12 | /* 13 | I'm dropping the second parameter. As it's 14 | only used so that we can see what function 15 | caused the call to the error frame. 16 | */ 17 | #define ERROR(f) add_frame(__FILE__, (f), __LINE__) 18 | void add_frame(const char* srcfile, const char* funcname, int linenum); 19 | void report_error_cb(JSContext* cx, const char* message, JSErrorReport* report); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /tests/test-errors.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | 7 | @t.cx() 8 | def test_raise_js_error(cx): 9 | t.raises(Exception, cx.execute, 'throw("foo");') 10 | 11 | @t.cx() 12 | def test_raise_js_error_in_function(cx): 13 | func = cx.execute("function(doc) {throw(\"error\");};") 14 | t.raises(Exception, func) 15 | 16 | @t.cx() 17 | def test_propogate_from_py(cx): 18 | def do_raise(): 19 | raise SystemExit() 20 | cx.add_global("do_raise", do_raise) 21 | t.raises(SystemExit, cx.execute, "do_raise();") 22 | -------------------------------------------------------------------------------- /tests/test-syntax-error.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | import traceback 7 | 8 | ERROR = 'File "", line 1, in ' \ 9 | 'SyntaxError: missing ) after formal parameters' 10 | 11 | @t.cx() 12 | def test_syntax_error(cx): 13 | try: 14 | cx.execute("function(asdf;") 15 | t.eq(1, 0) 16 | except: 17 | line = traceback.format_exc().split("\n")[-3].strip() 18 | t.eq(line, ERROR) 19 | 20 | @t.cx() 21 | def test_invalid_octal(cx): 22 | t.raises(t.JSError, cx.execute, "09;") 23 | 24 | -------------------------------------------------------------------------------- /spidermonkey/jsobject.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_JSOBJECT_H 10 | #define PYSM_JSOBJECT_H 11 | 12 | /* 13 | This is a representation of a JavaScript 14 | object in Python land. 15 | */ 16 | 17 | typedef struct { 18 | PyObject_HEAD 19 | Context* cx; 20 | jsval val; 21 | JSObject* obj; 22 | } Object; 23 | 24 | extern PyTypeObject _ObjectType; 25 | 26 | PyObject* make_object(PyTypeObject* type, Context* cx, jsval val); 27 | PyObject* js2py_object(Context* cx, jsval val); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /old-sm/jsstring.pxi: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | def js_is_string(Context cx, jsval jsv): 5 | return JSVAL_IS_STRING(jsv) 6 | 7 | def py_is_string(Context cx, object py_obj): 8 | if isinstance(py_obj, types.StringTypes): 9 | if not isinstance(py_obj, types.UnicodeType): 10 | raise UnicodeError("Non unicode strings not allowed in spidermonkey.") 11 | return True 12 | return False 13 | 14 | cdef jsval py2js_string(Context cx, object py_obj, JSObject* parent): 15 | cdef PyJSString js_str 16 | js_str = py2js_jsstring(cx.cx, py_obj) 17 | return STRING_TO_JSVAL(js_str.data) 18 | 19 | cdef object js2py_string(Context cx, jsval jsv): 20 | return js2py_jsstring(JSVAL_TO_STRING(jsv)) 21 | -------------------------------------------------------------------------------- /spidermonkey/hashcobj.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_HASHCOBJ_H 10 | #define PYSM_HASHCOBJ_H 11 | 12 | /* 13 | A class to implement Python hashing of C pointers. 14 | */ 15 | 16 | typedef struct { 17 | PyObject_HEAD 18 | void* cobj; 19 | } HashCObj; 20 | 21 | extern PyTypeObject _HashCObjType; 22 | 23 | 24 | /* 25 | BIG FUCKING NOTE: This constructor never 26 | Py_INCREF's the returned object. 27 | */ 28 | PyObject* HashCObj_FromVoidPtr(void *cobj); 29 | void* HashCObj_AsVoidPtr(PyObject* self); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /update-libjs.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash -e 2 | 3 | URL=http://ftp.mozilla.org/pub/mozilla.org/js/js-1.7.0.tar.gz 4 | 5 | CFG=spidermonkey/`uname -s`-`uname -m` 6 | DEST=spidermonkey/libjs 7 | CWD=`pwd` 8 | TMP=tmp 9 | 10 | if [ ! -d $TMP ]; then 11 | mkdir $TMP 12 | fi 13 | 14 | if [ ! -d $DEST ]; then 15 | mkdir $DEST 16 | fi 17 | 18 | if [ ! -d $CFG ]; then 19 | mkdir $CFG 20 | fi 21 | 22 | cd $TMP && wget -N $URL && tar -xvzf js-1.7.0.tar.gz && cd .. 23 | cd $TMP/js/src/ 24 | make -f Makefile.ref jscpucfg jskwgen 25 | cd $CWD 26 | 27 | for ext in `echo "c h msg tbl"`; do 28 | cp $TMP/js/src/*.$ext $DEST 29 | done 30 | 31 | rm $DEST/js.c 32 | rm $DEST/jscpucfg.* 33 | rm $DEST/jskwgen.* 34 | 35 | ./$TMP/js/src/jscpucfg > $CFG/jsautocfg.h 36 | ./$TMP/js/src/jskwgen > $CFG/jsautokw.h 37 | 38 | -------------------------------------------------------------------------------- /old-sm/jsgc.pxi: -------------------------------------------------------------------------------- 1 | 2 | cdef class GC: 3 | cdef Context cx 4 | 5 | def __cinit__(GC self, Context cx): 6 | self.cx = cx 7 | 8 | cdef void run(GC self): 9 | JS_GC(self.cx.cx) 10 | 11 | cdef void run_maybe(GC self): 12 | JS_MaybeGC(self.cx.cx) 13 | 14 | cdef void add_root(GC self, void* rp): 15 | if not JS_AddRoot(self.cx.cx, rp): 16 | raise JSError("Failed to add a GC root") 17 | 18 | cdef void add_named_root(GC self, void* rp, char* name): 19 | if not JS_AddNamedRoot(self.cx.cx, rp, name): 20 | raise JSError("Failed to add a named GC root: %s" % name) 21 | 22 | cdef void rem_root(GC self, void* rp): 23 | if not JS_RemoveRoot(self.cx.cx, rp): 24 | raise JSError("Failed to remove GC root") 25 | -------------------------------------------------------------------------------- /tests/test-python-ctor.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | 7 | touched = 0 8 | class Foo(object): 9 | def __init__(self): 10 | self.bar = 2 11 | def __del__(self): 12 | global touched 13 | touched = 1 14 | 15 | @t.glbl("Foo", Foo) 16 | def test_py_ctor_right_type(cx, glbl): 17 | t.eq(isinstance(cx.execute("var f = new Foo(); f;"), Foo), True) 18 | 19 | @t.glbl("Foo", Foo) 20 | def test_py_ctor_attribute_acc(cx, glbl): 21 | t.eq(cx.execute("var f = new Foo(); f;").bar, 2) 22 | 23 | @t.glbl("Foo", Foo) 24 | def test_py_dtor_called(cx, glbl): 25 | t.eq(cx.execute('var f = {"baz": new Foo()}; f;').baz.bar, 2) 26 | cx.execute("delete f.baz;") 27 | cx.gc() 28 | t.eq(touched, 1) 29 | -------------------------------------------------------------------------------- /THANKS: -------------------------------------------------------------------------------- 1 | 2 | Thanks For Patches and Pointers 3 | =============================== 4 | 5 | benoitc 6 | * build system tweaks, compiling on OpenBSD 7 | 8 | Mark Lee 9 | * Patch for iterating JS arrays in Python 10 | * Patch to allow linking against Xulrunner's libmozjs 11 | 12 | sk89q 13 | * Info for FreeBSD builds 14 | 15 | spahl 16 | * Heads up on the signal hack and fix for a compiler warning. 17 | * Bug #16 integer property lookup failure report and fix. 18 | * Bug #17 add_property segfault when value is null. 19 | 20 | Mike West 21 | * Reported bug in Context.max_time 22 | * Better test for test_exceeds_time 23 | * Reported missing pkg-config requirement 24 | 25 | Riccardo Pelizzi 26 | * Bug report for global handlers and "function foo() {}" syntax. 27 | 28 | Keiji Costantini 29 | * Bug report on the memory limit test. 30 | 31 | Richard Boulton 32 | * Initial patch for filtering Python access. 33 | -------------------------------------------------------------------------------- /tests/test-roundtrip.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | 7 | @t.echo() 8 | def test_roundtrip_int(echo): 9 | t.eq(echo(42), 42) 10 | 11 | @t.echo() 12 | def test_roundtrip_float(echo): 13 | t.eq(echo(42.5), 42.5) 14 | 15 | @t.echo() 16 | def test_roundtrip_str(echo): 17 | t.eq(echo("spam"), "spam") 18 | 19 | @t.echo() 20 | def test_round_trip_None(echo): 21 | t.eq(echo(None), None) 22 | 23 | @t.echo() 24 | def test_roundtrip_True(echo): 25 | t.eq(echo(True), True) 26 | 27 | @t.echo() 28 | def test_roundtrip_False(echo): 29 | t.eq(echo(False), False) 30 | 31 | @t.echo() 32 | def test_roundtrip_inf(echo): 33 | t.eq(echo(1E500*1E500), 1E500*1E500) 34 | 35 | @t.echo() 36 | def test_roundtrip_nan(echo): 37 | t.eq(type(echo(1E500/1E500)), float) 38 | t.ne(echo(1E500/1E500), 1E500/1E500) 39 | -------------------------------------------------------------------------------- /old-sm/jserror.pxi: -------------------------------------------------------------------------------- 1 | 2 | 3 | cdef JSBool report_python_error(JSContext* cx): 4 | tb = traceback.format_exc() 5 | JS_ReportError(cx, tb) 6 | return JS_FALSE 7 | 8 | cdef void __report_error_callback__(JSContext* cx, char* message, JSErrorReport* report): 9 | cdef Context pycx 10 | 11 | try: 12 | if not js_context_has_data(cx): 13 | sys.stderr.write("Attempting to report error for an unknown JSContext.\n") 14 | return 15 | pycx = js_context_fetch(cx) 16 | 17 | filename = "Unknown" 18 | lineno = "Unknown" 19 | msg = "Unknown" 20 | 21 | if report != NULL: 22 | if report.filename != NULL: 23 | filename = report.filename 24 | lineno = report.lineno 25 | if message != NULL: 26 | msg = message 27 | 28 | pycx.set_error("%s(%d): %s" % (filename, lineno, message)) 29 | except: 30 | traceback.print_exc() 31 | -------------------------------------------------------------------------------- /tests/test-runtime.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | 7 | @t.rt() 8 | def test_creating_runtime(rt): 9 | t.ne(rt, None) 10 | 11 | def test_create_no_memory(): 12 | rt = t.spidermonkey.Runtime(1) 13 | t.raises(RuntimeError, rt.new_context) 14 | 15 | def test_exceed_memory(): 16 | # This test actually tests nothing. I'm leaving it for a bit to 17 | # see if I hear about the bug noted below. 18 | rt = t.spidermonkey.Runtime(50000) 19 | cx = rt.new_context() 20 | script = "var b = []; var f = 1000; while(f-- > 0) b.push(2.456);" 21 | # I had this script below original and it triggers some sort of 22 | # bug in the JS VM. I even reduced the test case outside of 23 | # python-spidermonkey to show it. No word from the SM guys. 24 | # script = "var b = []; for(var f in 100000) b.push(2.456);" 25 | cx.execute(script) 26 | 27 | -------------------------------------------------------------------------------- /spidermonkey/double.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | 11 | jsval 12 | py2js_double(Context* cx, PyObject* obj) 13 | { 14 | jsval rval = JSVAL_VOID; 15 | double pyval = PyFloat_AsDouble(obj); 16 | if(PyErr_Occurred()) goto error; 17 | 18 | if(!JS_NewNumberValue(cx->cx, pyval, &rval)) 19 | { 20 | PyErr_SetString(PyExc_ValueError, "Failed to convert number."); 21 | goto error; 22 | } 23 | 24 | goto success; 25 | 26 | error: 27 | success: 28 | return rval; 29 | } 30 | 31 | PyObject* 32 | js2py_double(Context* cx, jsval val) 33 | { 34 | double rval; 35 | 36 | if(!JS_ValueToNumber(cx->cx, val, &rval)) 37 | { 38 | PyErr_SetString(PyExc_TypeError, "Invalid JS number value."); 39 | return NULL; 40 | } 41 | 42 | return PyFloat_FromDouble(rval); 43 | } 44 | -------------------------------------------------------------------------------- /spidermonkey/spidermonkey.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef SPIDERMONKEY_H 10 | #define SPIDERMONKEY_H 11 | 12 | #include 13 | #include "structmember.h" 14 | 15 | #include 16 | 17 | #include "runtime.h" 18 | #include "context.h" 19 | 20 | #include "string.h" 21 | #include "integer.h" 22 | #include "double.h" 23 | 24 | #include "pyobject.h" 25 | #include "pyiter.h" 26 | 27 | #include "jsobject.h" 28 | #include "jsarray.h" 29 | #include "jsfunction.h" 30 | #include "jsiterator.h" 31 | 32 | #include "convert.h" 33 | #include "error.h" 34 | 35 | #include "hashcobj.h" 36 | 37 | extern PyObject* SpidermonkeyModule; 38 | extern PyTypeObject* RuntimeType; 39 | extern PyTypeObject* ContextType; 40 | extern PyTypeObject* ClassType; 41 | extern PyTypeObject* ObjectType; 42 | extern PyTypeObject* ArrayType; 43 | extern PyTypeObject* FunctionType; 44 | extern PyTypeObject* IteratorType; 45 | extern PyTypeObject* HashCObjType; 46 | extern PyObject* JSError; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Paul J. Davis 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /spidermonkey/context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #ifndef PYSM_CONTEXT_H 10 | #define PYSM_CONTEXT_H 11 | 12 | #include 13 | #include "structmember.h" 14 | 15 | #include "spidermonkey.h" 16 | 17 | typedef struct { 18 | PyObject_HEAD 19 | Runtime* rt; 20 | PyObject* global; 21 | PyObject* access; 22 | JSContext* cx; 23 | JSObject* root; 24 | PyDictObject* classes; 25 | PySetObject* objects; 26 | uint32 branch_count; 27 | long max_heap; 28 | time_t max_time; 29 | time_t start_time; 30 | } Context; 31 | 32 | PyObject* Context_get_class(Context* cx, const char* key); 33 | int Context_add_class(Context* cx, const char* key, PyObject* val); 34 | 35 | int Context_has_access(Context*, JSContext*, PyObject*, PyObject*); 36 | 37 | int Context_has_object(Context* cx, PyObject* val); 38 | int Context_add_object(Context* cx, PyObject* val); 39 | int Context_rem_object(Context* cx, PyObject* val); 40 | 41 | extern PyTypeObject _ContextType; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /tests/test-iterate.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | 7 | js_for_script = """ 8 | var ret = []; 9 | for(var v in data) {ret.push(v);} 10 | ret; 11 | """ 12 | 13 | js_for_each_script = """ 14 | var ret = []; 15 | for each(var v in data) {ret.push(v);} 16 | ret; 17 | """ 18 | 19 | @t.glbl("data", {"foo": "bar", "baz": "bam"}) 20 | def test_iter_py_map(cx, glbl): 21 | t.eq(cx.execute(js_for_script), ["foo", "baz"]) 22 | t.eq(cx.execute(js_for_each_script), ["bar", "bam"]) 23 | 24 | @t.glbl("data", ["a", 2, "zing!"]) 25 | def test_iter_py_array(cx, glbl): 26 | t.eq(cx.execute(js_for_script), [0, 1, 2]) 27 | t.eq(cx.execute(js_for_each_script), ["a", 2, "zing!"]) 28 | 29 | @t.cx() 30 | def test_iter_js_object(cx): 31 | ret = cx.execute('var f = {"foo": 1, "domino": "daily"}; f;') 32 | items = set(["domino", "foo"]) 33 | for k in ret: 34 | t.isin(k, items) 35 | items.remove(k) 36 | 37 | @t.cx() 38 | def test_iter_js_array(cx): 39 | ret = cx.execute('["foo", 1, "bing", [3, 6]]') 40 | t.eq([k for k in ret], ["foo", 1, "bing", [3, 6]]) 41 | -------------------------------------------------------------------------------- /tests/test-to-python.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | 7 | @t.cx() 8 | def test_to_py_int(cx): 9 | t.eq(cx.execute("42;"), 42) 10 | 11 | @t.cx() 12 | def test_to_py_float(cx): 13 | t.eq(cx.execute("42.5;"), 42.5) 14 | 15 | @t.cx() 16 | def test_to_py_str(cx): 17 | t.eq(cx.execute('"spam";'), "spam") 18 | t.eq(isinstance(cx.execute('"spam";'), unicode), True) 19 | 20 | @t.cx() 21 | def test_to_py_unicode(cx): 22 | t.eq(cx.execute(u"\"\u0042\";"), u"\u0042") 23 | 24 | @t.cx() 25 | def test_undefined_to_py_None(cx): 26 | t.eq(cx.execute("undefined;"), None) 27 | 28 | @t.cx() 29 | def test_null_to_py_None(cx): 30 | t.eq(cx.execute("null;"), None) 31 | 32 | @t.cx() 33 | def test_true_to_py_True(cx): 34 | t.eq(cx.execute("true;"), True) 35 | 36 | @t.cx() 37 | def test_to_py_False(cx): 38 | t.eq(cx.execute("false;"), False) 39 | 40 | @t.cx() 41 | def test_NaN_to_py_nan(cx): 42 | nan = cx.execute("NaN;") 43 | t.eq(type(nan), float) 44 | t.ne(nan, nan) 45 | 46 | @t.cx() 47 | def test_Infinity_to_py_inf(cx): 48 | t.eq(cx.execute("Infinity;"), 1E500*1E500) 49 | -------------------------------------------------------------------------------- /tests/test-py-lookup.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | 7 | @t.cx() 8 | def test_str_property_as_item(cx): 9 | cx.add_global("zim", {"gir": "tacito!"}) 10 | t.eq(cx.execute('zim["gir"]'), "tacito!") 11 | 12 | @t.cx() 13 | def test_str_property_as_attr(cx): 14 | cx.add_global("protein", {"rna": "dna"}) 15 | t.eq(cx.execute("protein.rna;"), "dna") 16 | 17 | @t.cx() 18 | def test_unicode_key(cx): 19 | cx.add_global("unicode", {u"is": "complicated"}) 20 | t.eq(cx.execute("unicode.is;"), "complicated") 21 | 22 | @t.cx() 23 | def test_int_property(cx): 24 | cx.add_global("foo", [1, 8]) 25 | t.eq(cx.execute("foo[1];"), 8) 26 | 27 | 28 | # JavaScript property looks can only be integers and 29 | # strings. So even though foo[1.1] looks like it should 30 | # work, Spidermonkey is converting it to a string which 31 | # affects access in python land. 32 | 33 | @t.cx() 34 | def test_float_prop(cx): 35 | cx.add_global("foo", {1.1: "hidden!"}) 36 | t.eq(cx.execute("foo[1.1];"), None) 37 | 38 | @t.cx() 39 | def test_float_expected(cx): 40 | cx.add_global("whee", {"3.14": "mmmm food"}) 41 | t.eq(cx.execute("whee[3.14];"), "mmmm food") 42 | -------------------------------------------------------------------------------- /old-sm/jsarray.pxi: -------------------------------------------------------------------------------- 1 | 2 | def js_is_array(Context cx, jsval v): 3 | cdef JSObject* obj 4 | if not JSVAL_IS_OBJECT(v): 5 | return False 6 | obj = JSVAL_TO_OBJECT(v) 7 | return JS_IsArrayObject(cx.cx, obj) 8 | 9 | def py_is_array(Context cx, object py_obj): 10 | return isinstance(py_obj, (types.ListType, types.TupleType)) 11 | 12 | cdef object js2py_array(Context cx, jsval v): 13 | cdef jsuint nr_elems 14 | cdef jsval elem 15 | cdef JSObject *jsobj 16 | cdef int i 17 | cdef list ret 18 | 19 | jsobj = JSVAL_TO_OBJECT(v) 20 | JS_GetArrayLength(cx.cx, jsobj, &nr_elems) 21 | ret = [None] * nr_elems 22 | 23 | for i from 0 <= i < nr_elems: 24 | if not JS_GetElement(cx.cx, jsobj, i, &elem): 25 | raise JSError("Failed to convert JavaScript array to Python.") 26 | ret[i] = js2py(cx, elem) 27 | 28 | return ret 29 | 30 | cdef jsval py2js_array(Context cx, list py_obj, JSObject* parent): 31 | cdef int nr_elems, i 32 | cdef JSObject* ret 33 | cdef jsval elem 34 | 35 | nr_elems = len(py_obj) 36 | ret = JS_NewArrayObject(cx.cx, 0, NULL) 37 | 38 | for i from 0 <= i < nr_elems: 39 | elem = py2js(cx, py_obj[i], parent) 40 | if not JS_SetElement(cx.cx, ret, i, &elem): 41 | raise JSError("Failed to convert Python sequence type to JavaScript.") 42 | 43 | return OBJECT_TO_JSVAL(ret) -------------------------------------------------------------------------------- /spidermonkey/integer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | 11 | jsval 12 | py2js_integer(Context* cx, PyObject* obj) 13 | { 14 | long pyval; 15 | 16 | if(PyInt_Check(obj)) 17 | { 18 | pyval = PyInt_AsLong(obj); 19 | if(PyErr_Occurred()) return JSVAL_VOID; 20 | } 21 | else 22 | { 23 | pyval = PyLong_AsLong(obj); 24 | if(PyErr_Occurred()) return JSVAL_VOID; 25 | } 26 | 27 | return long2js_integer(cx, pyval); 28 | } 29 | 30 | jsval 31 | long2js_integer(Context* cx, long pyval) 32 | { 33 | jsval ret = JSVAL_VOID; 34 | 35 | if(INT_FITS_IN_JSVAL(pyval)) 36 | { 37 | ret = INT_TO_JSVAL(pyval); 38 | goto done; 39 | } 40 | 41 | if(!JS_NewNumberValue(cx->cx, pyval, &ret)) 42 | { 43 | PyErr_SetString(PyExc_ValueError, "Failed to convert number."); 44 | goto done; 45 | } 46 | 47 | done: 48 | return ret; 49 | } 50 | 51 | PyObject* 52 | js2py_integer(Context* cx, jsval val) 53 | { 54 | int32 rval; 55 | 56 | if(!JS_ValueToInt32(cx->cx, val, &rval)) 57 | { 58 | PyErr_SetString(PyExc_TypeError, "Invalid JS integer value."); 59 | return NULL; 60 | } 61 | 62 | return PyInt_FromLong(rval); 63 | } 64 | -------------------------------------------------------------------------------- /spidermonkey/Darwin-i386/jsautocfg.h: -------------------------------------------------------------------------------- 1 | #ifndef js_cpucfg___ 2 | #define js_cpucfg___ 3 | 4 | /* AUTOMATICALLY GENERATED - DO NOT EDIT */ 5 | 6 | #define IS_LITTLE_ENDIAN 1 7 | #undef IS_BIG_ENDIAN 8 | 9 | #define JS_BYTES_PER_BYTE 1L 10 | #define JS_BYTES_PER_SHORT 2L 11 | #define JS_BYTES_PER_INT 4L 12 | #define JS_BYTES_PER_INT64 8L 13 | #define JS_BYTES_PER_LONG 4L 14 | #define JS_BYTES_PER_FLOAT 4L 15 | #define JS_BYTES_PER_DOUBLE 8L 16 | #define JS_BYTES_PER_WORD 4L 17 | #define JS_BYTES_PER_DWORD 8L 18 | 19 | #define JS_BITS_PER_BYTE 8L 20 | #define JS_BITS_PER_SHORT 16L 21 | #define JS_BITS_PER_INT 32L 22 | #define JS_BITS_PER_INT64 64L 23 | #define JS_BITS_PER_LONG 32L 24 | #define JS_BITS_PER_FLOAT 32L 25 | #define JS_BITS_PER_DOUBLE 64L 26 | #define JS_BITS_PER_WORD 32L 27 | 28 | #define JS_BITS_PER_BYTE_LOG2 3L 29 | #define JS_BITS_PER_SHORT_LOG2 4L 30 | #define JS_BITS_PER_INT_LOG2 5L 31 | #define JS_BITS_PER_INT64_LOG2 6L 32 | #define JS_BITS_PER_LONG_LOG2 5L 33 | #define JS_BITS_PER_FLOAT_LOG2 5L 34 | #define JS_BITS_PER_DOUBLE_LOG2 6L 35 | #define JS_BITS_PER_WORD_LOG2 5L 36 | 37 | #define JS_ALIGN_OF_SHORT 2L 38 | #define JS_ALIGN_OF_INT 4L 39 | #define JS_ALIGN_OF_LONG 4L 40 | #define JS_ALIGN_OF_INT64 4L 41 | #define JS_ALIGN_OF_FLOAT 4L 42 | #define JS_ALIGN_OF_DOUBLE 4L 43 | #define JS_ALIGN_OF_POINTER 4L 44 | #define JS_ALIGN_OF_WORD 4L 45 | 46 | #define JS_BYTES_PER_WORD_LOG2 2L 47 | #define JS_BYTES_PER_DWORD_LOG2 3L 48 | #define JS_WORDS_PER_DWORD_LOG2 1L 49 | 50 | #define JS_STACK_GROWTH_DIRECTION (-1) 51 | 52 | #endif /* js_cpucfg___ */ 53 | -------------------------------------------------------------------------------- /spidermonkey/Linux-i686/jsautocfg.h: -------------------------------------------------------------------------------- 1 | #ifndef js_cpucfg___ 2 | #define js_cpucfg___ 3 | 4 | /* AUTOMATICALLY GENERATED - DO NOT EDIT */ 5 | 6 | #define IS_LITTLE_ENDIAN 1 7 | #undef IS_BIG_ENDIAN 8 | 9 | #define JS_BYTES_PER_BYTE 1L 10 | #define JS_BYTES_PER_SHORT 2L 11 | #define JS_BYTES_PER_INT 4L 12 | #define JS_BYTES_PER_INT64 8L 13 | #define JS_BYTES_PER_LONG 4L 14 | #define JS_BYTES_PER_FLOAT 4L 15 | #define JS_BYTES_PER_DOUBLE 8L 16 | #define JS_BYTES_PER_WORD 4L 17 | #define JS_BYTES_PER_DWORD 8L 18 | 19 | #define JS_BITS_PER_BYTE 8L 20 | #define JS_BITS_PER_SHORT 16L 21 | #define JS_BITS_PER_INT 32L 22 | #define JS_BITS_PER_INT64 64L 23 | #define JS_BITS_PER_LONG 32L 24 | #define JS_BITS_PER_FLOAT 32L 25 | #define JS_BITS_PER_DOUBLE 64L 26 | #define JS_BITS_PER_WORD 32L 27 | 28 | #define JS_BITS_PER_BYTE_LOG2 3L 29 | #define JS_BITS_PER_SHORT_LOG2 4L 30 | #define JS_BITS_PER_INT_LOG2 5L 31 | #define JS_BITS_PER_INT64_LOG2 6L 32 | #define JS_BITS_PER_LONG_LOG2 5L 33 | #define JS_BITS_PER_FLOAT_LOG2 5L 34 | #define JS_BITS_PER_DOUBLE_LOG2 6L 35 | #define JS_BITS_PER_WORD_LOG2 5L 36 | 37 | #define JS_ALIGN_OF_SHORT 2L 38 | #define JS_ALIGN_OF_INT 4L 39 | #define JS_ALIGN_OF_LONG 4L 40 | #define JS_ALIGN_OF_INT64 4L 41 | #define JS_ALIGN_OF_FLOAT 4L 42 | #define JS_ALIGN_OF_DOUBLE 4L 43 | #define JS_ALIGN_OF_POINTER 4L 44 | #define JS_ALIGN_OF_WORD 4L 45 | 46 | #define JS_BYTES_PER_WORD_LOG2 2L 47 | #define JS_BYTES_PER_DWORD_LOG2 3L 48 | #define JS_WORDS_PER_DWORD_LOG2 1L 49 | 50 | #define JS_STACK_GROWTH_DIRECTION (-1) 51 | 52 | #endif /* js_cpucfg___ */ 53 | -------------------------------------------------------------------------------- /spidermonkey/Linux-x86_64/jsautocfg.h: -------------------------------------------------------------------------------- 1 | #ifndef js_cpucfg___ 2 | #define js_cpucfg___ 3 | 4 | /* AUTOMATICALLY GENERATED - DO NOT EDIT */ 5 | 6 | #define IS_LITTLE_ENDIAN 1 7 | #undef IS_BIG_ENDIAN 8 | 9 | #define JS_BYTES_PER_BYTE 1L 10 | #define JS_BYTES_PER_SHORT 2L 11 | #define JS_BYTES_PER_INT 4L 12 | #define JS_BYTES_PER_INT64 8L 13 | #define JS_BYTES_PER_LONG 8L 14 | #define JS_BYTES_PER_FLOAT 4L 15 | #define JS_BYTES_PER_DOUBLE 8L 16 | #define JS_BYTES_PER_WORD 8L 17 | #define JS_BYTES_PER_DWORD 8L 18 | 19 | #define JS_BITS_PER_BYTE 8L 20 | #define JS_BITS_PER_SHORT 16L 21 | #define JS_BITS_PER_INT 32L 22 | #define JS_BITS_PER_INT64 64L 23 | #define JS_BITS_PER_LONG 64L 24 | #define JS_BITS_PER_FLOAT 32L 25 | #define JS_BITS_PER_DOUBLE 64L 26 | #define JS_BITS_PER_WORD 64L 27 | 28 | #define JS_BITS_PER_BYTE_LOG2 3L 29 | #define JS_BITS_PER_SHORT_LOG2 4L 30 | #define JS_BITS_PER_INT_LOG2 5L 31 | #define JS_BITS_PER_INT64_LOG2 6L 32 | #define JS_BITS_PER_LONG_LOG2 6L 33 | #define JS_BITS_PER_FLOAT_LOG2 5L 34 | #define JS_BITS_PER_DOUBLE_LOG2 6L 35 | #define JS_BITS_PER_WORD_LOG2 6L 36 | 37 | #define JS_ALIGN_OF_SHORT 2L 38 | #define JS_ALIGN_OF_INT 4L 39 | #define JS_ALIGN_OF_LONG 8L 40 | #define JS_ALIGN_OF_INT64 8L 41 | #define JS_ALIGN_OF_FLOAT 4L 42 | #define JS_ALIGN_OF_DOUBLE 8L 43 | #define JS_ALIGN_OF_POINTER 8L 44 | #define JS_ALIGN_OF_WORD 8L 45 | 46 | #define JS_BYTES_PER_WORD_LOG2 3L 47 | #define JS_BYTES_PER_DWORD_LOG2 3L 48 | #define JS_WORDS_PER_DWORD_LOG2 0L 49 | 50 | #define JS_STACK_GROWTH_DIRECTION (-1) 51 | 52 | #endif /* js_cpucfg___ */ 53 | -------------------------------------------------------------------------------- /old-sm/jsobject.pxi: -------------------------------------------------------------------------------- 1 | 2 | cdef class ObjectAdapter: 3 | cdef Context cx 4 | cdef ClassAdapter cl_adapter 5 | cdef ObjectAdapter parent 6 | cdef JSObject* js_obj 7 | cdef object py_obj 8 | 9 | def __cinit__(ObjectAdapter self, Context cx, ClassAdapter adapter, ObjectAdapter parent, object obj): 10 | self.cx = cx 11 | self.cl_adapter = adapter 12 | self.parent = parent 13 | self.js_obj = NULL 14 | self.py_obj = obj 15 | 16 | def __repr__(self): 17 | return "" % self.py_obj 18 | 19 | def js_is_object(Context cx, jsval jsv): 20 | if not JSVAL_IS_OBJECT(jsv): 21 | return False 22 | if not js_object_has_data(cx.cx, JSVAL_TO_OBJECT(jsv)): 23 | return False 24 | return True 25 | 26 | def py_is_object(Context cx, object py_obj): 27 | return not isinstance(py_obj, types.TypeType) 28 | 29 | cdef object js2py_object(Context cx, jsval jsv): 30 | cdef ClassAdapter ca 31 | cdef ObjectAdapter oa 32 | cdef FunctionAdapter fa 33 | 34 | tmp = js_object_fetch(cx.cx, JSVAL_TO_OBJECT(jsv)) 35 | if isinstance(tmp, ClassAdapter): 36 | ca = tmp 37 | return ca.py_obj 38 | elif isinstance(tmp, ObjectAdapter): 39 | oa = tmp 40 | return oa.py_obj 41 | elif isinstance(tmp, FunctionAdapter): 42 | fa = tmp 43 | return fa.py_obj 44 | else: 45 | raise JSError("Failed to unwrap Python object.") 46 | 47 | cdef jsval py2js_object(Context cx, object py_obj, JSObject* parent): 48 | cdef ClassAdapter ca 49 | cdef ObjectAdapter oa 50 | cdef JSObject* js_obj 51 | cdef jsval rval 52 | 53 | ca = cx.install_class(py_obj.__class__) 54 | js_obj = JS_NewObject(cx.cx, ca.js_class, NULL, NULL) 55 | if js_obj == NULL: 56 | raise JSError("Failed to create object.") 57 | oa = ObjectAdapter(cx, ca, None, py_obj) 58 | oa.js_obj = js_obj 59 | js_object_attach(cx.cx, oa.js_obj, oa) 60 | 61 | return OBJECT_TO_JSVAL(js_obj) 62 | -------------------------------------------------------------------------------- /old-sm/jsvalue.pxi: -------------------------------------------------------------------------------- 1 | 2 | cdef jsval py2js(Context cx, object py_obj, JSObject* parent) except 0: 3 | if py_is_void(cx, py_obj): 4 | return py2js_void(cx, py_obj, parent) 5 | elif py_is_bool(cx, py_obj): 6 | return py2js_bool(cx, py_obj, parent) 7 | elif py_is_int(cx, py_obj): 8 | return py2js_int(cx, py_obj, parent) 9 | elif py_is_double(cx, py_obj): 10 | return py2js_double(cx, py_obj, parent) 11 | elif py_is_string(cx, py_obj): 12 | return py2js_string(cx, py_obj, parent) 13 | elif py_is_array(cx, py_obj): 14 | return py2js_array(cx, py_obj, parent) 15 | elif py_is_hash(cx, py_obj): 16 | return py2js_hash(cx, py_obj, parent) 17 | elif py_is_bound_method(cx, py_obj): 18 | return py2js_bound_method(cx, py_obj, parent) 19 | elif py_is_function(cx, py_obj): 20 | return py2js_function(cx, py_obj, parent) 21 | elif py_is_object(cx, py_obj): 22 | return py2js_object(cx, py_obj, parent) 23 | #elif py_is_class(cx, py_obj): 24 | # return py2js_class(cx, py_obj, parent) 25 | else: 26 | raise TypeError("Unable to convert Python value to JavaScript: %r" % py_obj) 27 | 28 | cdef object js2py(Context cx, jsval jsv): 29 | if js_is_void(cx, jsv): 30 | return js2py_void(cx, jsv) 31 | elif js_is_bool(cx, jsv): 32 | return js2py_bool(cx, jsv) 33 | elif js_is_int(cx, jsv): 34 | return js2py_int(cx, jsv) 35 | elif js_is_double(cx, jsv): 36 | return js2py_double(cx, jsv) 37 | elif js_is_string(cx, jsv): 38 | return js2py_string(cx, jsv) 39 | elif js_is_array(cx, jsv): 40 | return js2py_array(cx, jsv) 41 | elif js_is_function(cx, jsv): 42 | return js2py_function(cx, jsv) 43 | elif js_is_object(cx, jsv): 44 | return js2py_object(cx, jsv) 45 | elif js_is_hash(cx, jsv): 46 | return js2py_hash(cx, jsv) 47 | else: 48 | raise TypeError("Unable to convert JavaScript value to Python: %r" % jsv) 49 | 50 | cdef class Value: 51 | cdef jsval jsv 52 | 53 | cdef Value js_create_value(jsval jsv): 54 | cdef Value v 55 | v = Value() 56 | v.jsv = jsv 57 | return v 58 | -------------------------------------------------------------------------------- /spidermonkey/string.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | 11 | JSString* 12 | py2js_string_obj(Context* cx, PyObject* str) 13 | { 14 | PyObject* conv = NULL; 15 | PyObject* encoded = NULL; 16 | JSString* ret = NULL; 17 | char* bytes; 18 | Py_ssize_t len; 19 | 20 | if(PyString_Check(str)) 21 | { 22 | conv = PyUnicode_FromEncodedObject(str, "utf-8", "replace"); 23 | if(conv == NULL) goto error; 24 | str = conv; 25 | } 26 | else if(!PyUnicode_Check(str)) 27 | { 28 | PyErr_SetString(PyExc_TypeError, "Invalid string conversion."); 29 | goto error; 30 | } 31 | 32 | encoded = PyUnicode_AsEncodedString(str, "utf-16", "strict"); 33 | if(encoded == NULL) goto error; 34 | if(PyString_AsStringAndSize(encoded, &bytes, &len) < 0) goto error; 35 | if(len < 2) 36 | { 37 | PyErr_SetString(PyExc_ValueError, "Failed to find byte-order mark."); 38 | goto error; 39 | } 40 | 41 | if(((unsigned short*) bytes)[0] != 0xFEFF) 42 | { 43 | PyErr_SetString(PyExc_ValueError, "Invalid UTF-16 BOM"); 44 | goto error; 45 | } 46 | 47 | ret = JS_NewUCStringCopyN(cx->cx, (jschar*) (bytes+2), (len/2)-1); 48 | 49 | goto success; 50 | 51 | error: 52 | success: 53 | Py_XDECREF(conv); 54 | Py_XDECREF(encoded); 55 | return ret; 56 | } 57 | 58 | jsval 59 | py2js_string(Context* cx, PyObject* str) 60 | { 61 | JSString* val = py2js_string_obj(cx, str); 62 | if(val == NULL) 63 | { 64 | PyErr_Clear(); 65 | return JSVAL_VOID; 66 | } 67 | 68 | return STRING_TO_JSVAL(val); 69 | } 70 | 71 | PyObject* 72 | js2py_string(Context* cx, jsval val) 73 | { 74 | JSString* str; 75 | jschar* bytes; 76 | size_t len; 77 | 78 | if(!JSVAL_IS_STRING(val)) 79 | { 80 | PyErr_SetString(PyExc_TypeError, "Value is not a JS String."); 81 | return NULL; 82 | } 83 | 84 | str = JSVAL_TO_STRING(val); 85 | len = JS_GetStringLength(str); 86 | bytes = JS_GetStringChars(str); 87 | 88 | return PyUnicode_Decode((const char*) bytes, len*2, "utf-16", "strict"); 89 | } 90 | -------------------------------------------------------------------------------- /tests/test-context.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | import time 7 | 8 | @t.rt() 9 | def test_no_provided_runtime(rt): 10 | t.raises(TypeError, t.spidermonkey.Context) 11 | 12 | @t.rt() 13 | def test_invalid_runtime(rt): 14 | t.raises(TypeError, t.spidermonkey.Context, 0) 15 | 16 | @t.rt() 17 | def test_creating_new_context(rt): 18 | t.eq(isinstance(rt.new_context(), t.spidermonkey.Context), True) 19 | 20 | @t.cx() 21 | def test_basic_execution(cx): 22 | t.eq(cx.execute("var x = 4; x * x;"), 16) 23 | t.lt(cx.execute("22/7;") - 3.14285714286, 0.00000001) 24 | 25 | @t.cx() 26 | def test_reentry(cx): 27 | cx.execute("var x = 42;") 28 | t.eq(cx.execute("x;"), 42) 29 | 30 | @t.cx() 31 | def test_null(cx): 32 | cx.execute("x = null;") 33 | t.eq(cx.execute("x;"), None) 34 | 35 | @t.cx() 36 | def test_get_set_limits(cx): 37 | t.eq(cx.max_time(), 0) 38 | t.eq(cx.max_memory(), 0) 39 | t.eq(cx.max_time(10), 0) # Accessors return previous value. 40 | t.eq(cx.max_time(), 10) 41 | t.eq(cx.max_memory(10), 0) 42 | t.eq(cx.max_memory(), 10) 43 | 44 | @t.cx() 45 | def test_exceed_time(cx): 46 | script = """ 47 | var time = function() {return (new Date()).getTime();}; 48 | var start = time(); 49 | while((time() - start) < 2000) {} 50 | """ 51 | cx.max_time(1) 52 | t.raises(SystemError, cx.execute, script) 53 | 54 | @t.cx() 55 | def test_does_not_exceed_time(cx): 56 | cx.max_time(1) 57 | func = cx.execute("function() {return 1;}") 58 | time.sleep(1.1) 59 | cx.execute("var f = 2;"); 60 | time.sleep(1.1) 61 | func() 62 | time.sleep(1.1) 63 | cx.execute("f;"); 64 | 65 | @t.cx() 66 | def test_exceed_memory(cx): 67 | cx.max_memory(10000) 68 | script = "var f = []; var b = 1000000; while(b-- > 0) f[f.length] = b*0.9;" 69 | t.raises(MemoryError, cx.execute, script) 70 | 71 | @t.cx() 72 | def test_small_limit(cx): 73 | cx.max_memory(1) 74 | t.raises(MemoryError, cx.execute, "var f = []; while(true) f.push(2.3);"); 75 | 76 | @t.cx() 77 | def test_does_not_exceed_memory(cx): 78 | cx.max_memory(10000) 79 | script = "var f = 2; f;" 80 | cx.execute(script) 81 | 82 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsmath.h: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | * 4 | * The contents of this file are subject to the Mozilla Public License Version 5 | * 1.1 (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * http://www.mozilla.org/MPL/ 8 | * 9 | * Software distributed under the License is distributed on an "AS IS" basis, 10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | * for the specific language governing rights and limitations under the 12 | * License. 13 | * 14 | * The Original Code is Mozilla Communicator client code, released 15 | * March 31, 1998. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Netscape Communications Corporation. 19 | * Portions created by the Initial Developer are Copyright (C) 1998-1999 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * 24 | * Alternatively, the contents of this file may be used under the terms of 25 | * either of the GNU General Public License Version 2 or later (the "GPL"), 26 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 27 | * in which case the provisions of the GPL or the LGPL are applicable instead 28 | * of those above. If you wish to allow use of your version of this file only 29 | * under the terms of either the GPL or the LGPL, and not to allow others to 30 | * use your version of this file under the terms of the MPL, indicate your 31 | * decision by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL or the LGPL. If you do not delete 33 | * the provisions above, a recipient may use your version of this file under 34 | * the terms of any one of the MPL, the GPL or the LGPL. 35 | * 36 | * ***** END LICENSE BLOCK ***** */ 37 | 38 | /* -*- Mode: C; tab-width: 8 -*- 39 | * Copyright (C) 1998-1999 Netscape Communications Corporation, All Rights Reserved. 40 | */ 41 | 42 | #ifndef jsmath_h___ 43 | #define jsmath_h___ 44 | /* 45 | * JS math functions. 46 | */ 47 | 48 | JS_BEGIN_EXTERN_C 49 | 50 | extern JSClass js_MathClass; 51 | 52 | extern JSObject * 53 | js_InitMathClass(JSContext *cx, JSObject *obj); 54 | 55 | JS_END_EXTERN_C 56 | 57 | #endif /* jsmath_h___ */ 58 | -------------------------------------------------------------------------------- /tests/test-object.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | 7 | @t.cx() 8 | def test_object_repr(cx): 9 | t.eq(repr(cx.execute('var f = {"foo": "bar"}; f;')), "[object Object]") 10 | 11 | @t.cx() 12 | def test_object_attr_access(cx): 13 | t.eq(cx.execute('var f = {"foo": "bar"}; f;').foo, "bar") 14 | 15 | @t.cx() 16 | def test_object_item_access(cx): 17 | t.eq(cx.execute('var f = {"foo": "bar"}; f;')["foo"], "bar") 18 | 19 | @t.cx() 20 | def test_attribute_creation(cx): 21 | ret = cx.execute('var f = {"foo": "bar"}; f;') 22 | ret.pinky = "taking over." 23 | t.eq(cx.execute("f.pinky;"), "taking over.") 24 | 25 | @t.cx() 26 | def test_item_creation(cx): 27 | ret = cx.execute('var f = {"foo": "bar"}; f;') 28 | ret["pinky"] = "the world" 29 | t.eq(cx.execute("f.pinky;"), "the world") 30 | 31 | @t.cx() 32 | def test_js_mutation(cx): 33 | ret = cx.execute('var f = {"foo": "bar"}; f;') 34 | cx.execute('f["foo"] = 13;') 35 | t.eq(ret.foo, 13) 36 | 37 | @t.cx() 38 | def test_int_is_str_item(cx): 39 | ret = cx.execute('var f = {"2": "bar"}; f;') 40 | t.eq(ret["2"], "bar") 41 | t.eq(ret[2], "bar") 42 | 43 | @t.cx() 44 | def test_del_item_from_py(cx): 45 | ret = cx.execute('var f = {2: "bar"}; f;') 46 | del ret[2] 47 | t.eq(cx.execute('f[2];'), None) 48 | 49 | @t.cx() 50 | def test_del_attr_from_py(cx): 51 | ret = cx.execute('var f = {2: "bar"}; f;') 52 | delattr(ret, "2") 53 | t.eq(cx.execute("f[2]"), None) 54 | 55 | @t.cx() 56 | def test_array_repr(cx): 57 | t.eq(repr(cx.execute('[1, "foo", undefined];')), "1,foo,") 58 | 59 | @t.cx() 60 | def test_array_length(cx): 61 | t.eq(cx.execute('[1, "foo", undefined];').length, 3) 62 | 63 | @t.cx() 64 | def test_array_equality(cx): 65 | t.eq(cx.execute("[1,2,3];"), [1, 2, 3]) 66 | 67 | @t.cx() 68 | def test_mapping_equality(cx): 69 | js = 'var d = {0: 0, "a": 1, 2: "b", "c": "d", "blah": 2.5}; d;' 70 | py = {0: 0, "a": 1, 2: "b", "c": "d", "blah": 2.5} 71 | t.eq(cx.execute(js), py) 72 | 73 | @t.cx() 74 | def test_nested_object_equality(cx): 75 | t.eq( 76 | cx.execute('["foo", 2, {"bar": 2.3, "spam": [1,2,3]}];'), 77 | [u"foo", 2, {u"bar": 2.3, u"spam": [1,2,3]}] 78 | ) 79 | -------------------------------------------------------------------------------- /tests/t.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import unittest 6 | import spidermonkey 7 | from spidermonkey import JSError 8 | 9 | class test(object): 10 | def __call__(self, func): 11 | def run(): 12 | func(*self.args()) 13 | run.func_name = func.func_name 14 | return run 15 | def args(self, func): 16 | raise NotImplementedError() 17 | 18 | class rt(test): 19 | def args(self): 20 | return (spidermonkey.Runtime(),) 21 | 22 | class cx(test): 23 | def args(self): 24 | rt = spidermonkey.Runtime() 25 | return (rt.new_context(),) 26 | 27 | class echo(test): 28 | def args(self): 29 | rt = spidermonkey.Runtime() 30 | cx = rt.new_context() 31 | echo = cx.execute("function(arg) {return arg;}") 32 | return (echo,) 33 | 34 | class glbl(test): 35 | def __init__(self, name, value): 36 | self.name = name 37 | self.value = value 38 | def args(self): 39 | rt = spidermonkey.Runtime() 40 | cx = rt.new_context() 41 | cx.add_global(self.name, self.value) 42 | return (cx, self.value) 43 | 44 | def eq(a, b): 45 | assert a == b, "%r != %r" % (a, b) 46 | 47 | def ne(a, b): 48 | assert a != b, "%r == %r" % (a, b) 49 | 50 | def lt(a, b): 51 | assert a < b, "%r >= %r" % (a, b) 52 | 53 | def gt(a, b): 54 | assert a > b, "%r <= %r" % (a, b) 55 | 56 | def isin(a, b): 57 | assert a in b, "%r is not in %r" % (a, b) 58 | 59 | def isnotin(a, b): 60 | assert a not in b, "%r is in %r" % (a, b) 61 | 62 | def has(a, b): 63 | assert hasattr(a, b), "%r has no attribute %r" % (a, b) 64 | 65 | def hasnot(a, b): 66 | assert not hasattr(a, b), "%r has an attribute %r" % (a, b) 67 | 68 | def raises(exctype, func, *args, **kwargs): 69 | try: 70 | func(*args, **kwargs) 71 | except exctype, inst: 72 | pass 73 | else: 74 | func_name = getattr(func, "func_name", "") 75 | raise AssertionError("Function %s did not raise %s" % ( 76 | func_name, exctype.__name__)) 77 | 78 | def is_js_object(obj): 79 | assert isinstance(obj, spidermonkey.Object), \ 80 | "%r is not an instance of spdermonkey.Object." % obj 81 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsfile.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef _jsfile_h__ 41 | #define _jsfile_h__ 42 | 43 | #if JS_HAS_FILE_OBJECT 44 | 45 | #include "jsobj.h" 46 | 47 | extern JS_PUBLIC_API(JSObject*) 48 | js_InitFileClass(JSContext *cx, JSObject* obj); 49 | 50 | extern JS_PUBLIC_API(JSObject*) 51 | js_NewFileObject(JSContext *cx, char *bytes); 52 | 53 | extern JSClass js_FileClass; 54 | 55 | #endif /* JS_HAS_FILE_OBJECT */ 56 | #endif /* _jsfile_h__ */ 57 | -------------------------------------------------------------------------------- /old-sm/jshash.pxi: -------------------------------------------------------------------------------- 1 | 2 | def js_is_hash(Context cx, jsval v): 3 | return JSVAL_IS_OBJECT(v) 4 | 5 | def py_is_hash(Context cx, object py_obj): 6 | return isinstance(py_obj, (types.DictionaryType, types.DictType)) 7 | 8 | cdef object js2py_hash(Context cx, jsval v): 9 | cdef JSObject* hash 10 | cdef JSObject *obj 11 | cdef JSIdArray *props 12 | cdef jsval jskey 13 | cdef jsval jsv 14 | cdef int i 15 | cdef dict ret 16 | cdef PyJSString js_str 17 | 18 | hash = JSVAL_TO_OBJECT(v) 19 | 20 | props = JS_Enumerate(cx.cx, hash) 21 | if props == NULL: 22 | raise JSError("Failed to enumerate hash properties.") 23 | 24 | ret = {} 25 | 26 | try: 27 | for i from 0 <= i < props.length: 28 | if not JS_IdToValue(cx.cx, (props.vector)[i], &jskey): 29 | raise JSError("Failed to convert dict to JavaScript.") 30 | 31 | if js_is_string(cx, jskey): 32 | key = js2py_string(cx, jskey) 33 | js_str = py2js_jsstring(cx.cx, key) 34 | 35 | if not JS_GetUCProperty(cx.cx, hash, js_str.chars(), js_str.length(), &jsv): 36 | raise JSError("Faield to retrieve textual hash property.") 37 | elif js_is_int(cx, jskey): 38 | key = js2py_int(cx, jskey) 39 | if not JS_GetElement(cx.cx, hash, key, &jsv): 40 | raise JSError("Failed to retrive numeric hash property.") 41 | else: 42 | raise AssertionError("Invalid JavaScript property.") 43 | 44 | ret[key] = js2py(cx, jsv) 45 | finally: 46 | JS_DestroyIdArray(cx.cx, props) 47 | 48 | return ret 49 | 50 | 51 | cdef jsval py2js_hash(Context cx, dict py_obj, JSObject* parent): 52 | cdef JSObject* obj 53 | cdef jsval elem 54 | cdef PyJSString js_str 55 | 56 | obj = JS_NewObject(cx.cx, NULL, NULL, parent) 57 | if obj == NULL: 58 | raise JSError("Failed to create new JavaScript object for dict instance.") 59 | 60 | for k, v in py_obj.iteritems(): 61 | js_str = py2js_jsstring(cx.cx, k) 62 | elem = py2js(cx, v, obj) 63 | 64 | if not JS_SetUCProperty(cx.cx, obj, js_str.chars(), js_str.length(), &elem): 65 | raise JSError("Failed to set JavaScript property for dict instance.") 66 | 67 | return OBJECT_TO_JSVAL(obj) 68 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jscompat.h: -------------------------------------------------------------------------------- 1 | /* ***** BEGIN LICENSE BLOCK ***** 2 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 3 | * 4 | * The contents of this file are subject to the Mozilla Public License Version 5 | * 1.1 (the "License"); you may not use this file except in compliance with 6 | * the License. You may obtain a copy of the License at 7 | * http://www.mozilla.org/MPL/ 8 | * 9 | * Software distributed under the License is distributed on an "AS IS" basis, 10 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 11 | * for the specific language governing rights and limitations under the 12 | * License. 13 | * 14 | * The Original Code is Mozilla Communicator client code, released 15 | * March 31, 1998. 16 | * 17 | * The Initial Developer of the Original Code is 18 | * Netscape Communications Corporation. 19 | * Portions created by the Initial Developer are Copyright (C) 1998-1999 20 | * the Initial Developer. All Rights Reserved. 21 | * 22 | * Contributor(s): 23 | * 24 | * Alternatively, the contents of this file may be used under the terms of 25 | * either of the GNU General Public License Version 2 or later (the "GPL"), 26 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 27 | * in which case the provisions of the GPL or the LGPL are applicable instead 28 | * of those above. If you wish to allow use of your version of this file only 29 | * under the terms of either the GPL or the LGPL, and not to allow others to 30 | * use your version of this file under the terms of the MPL, indicate your 31 | * decision by deleting the provisions above and replace them with the notice 32 | * and other provisions required by the GPL or the LGPL. If you do not delete 33 | * the provisions above, a recipient may use your version of this file under 34 | * the terms of any one of the MPL, the GPL or the LGPL. 35 | * 36 | * ***** END LICENSE BLOCK ***** */ 37 | 38 | /* -*- Mode: C; tab-width: 8 -*- 39 | * Copyright (C) 1996-1999 Netscape Communications Corporation, All Rights Reserved. 40 | */ 41 | #ifndef jscompat_h___ 42 | #define jscompat_h___ 43 | /* 44 | * Compatibility glue for various NSPR versions. We must always define int8, 45 | * int16, jsword, and so on to minimize differences with js/ref, no matter what 46 | * the NSPR typedef names may be. 47 | */ 48 | #include "jstypes.h" 49 | #include "jslong.h" 50 | 51 | typedef JSIntn intN; 52 | typedef JSUintn uintN; 53 | typedef JSUword jsuword; 54 | typedef JSWord jsword; 55 | typedef float float32; 56 | #define allocPriv allocPool 57 | #endif /* jscompat_h___ */ 58 | -------------------------------------------------------------------------------- /tests/test-function.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | import threading 7 | 8 | @t.cx() 9 | def test_call_js_func(cx): 10 | t.eq(cx.execute('function() {return "yipee";};')(), "yipee") 11 | 12 | @t.cx() 13 | def test_call_js_with_arg(cx): 14 | func = cx.execute("function(v) {return v * 2;};") 15 | t.eq(func(2), 4) 16 | 17 | @t.cx() 18 | def test_function_with_dict_arg(cx): 19 | func = cx.execute("function(doc) {if(doc.data) return doc.data;};") 20 | t.eq(func({"data": 2}), 2) 21 | t.eq(func({}), None) 22 | 23 | @t.cx() 24 | def test_function_returning_unicode(cx): 25 | def bar(): 26 | return u"\u0042" 27 | cx.add_global("bound", bar) 28 | t.eq(cx.execute("bound();"), u"\u0042") 29 | 30 | @t.cx() 31 | def test_global_function(cx): 32 | def meander(): 33 | return "Meandering enthusiastically!" 34 | cx.add_global("meander", meander) 35 | t.eq(cx.execute("meander();"), "Meandering enthusiastically!") 36 | 37 | @t.cx() 38 | def test_bound_method(cx): 39 | class Foo(object): 40 | def callme(self, arg): 41 | return "I am serious. And don't call me Shirley." 42 | f = Foo() 43 | cx.add_global("func", f.callme) 44 | ret = cx.execute('func("Surely you can\'t be serious.");') 45 | t.eq("Shirley" in ret, True) 46 | 47 | @t.cx() 48 | def test_bound_method_no_return(cx): 49 | class Foo(object): 50 | def callme(self): 51 | pass 52 | f = Foo() 53 | cx.add_global("func", f.callme) 54 | ret = cx.execute("func()") 55 | t.eq(ret, None) 56 | 57 | @t.cx() 58 | def test_bound_method_from_js_func(cx): 59 | class Foo(object): 60 | def callme(self): 61 | return 4 62 | f = Foo() 63 | cx.add_global("dude", f.callme) 64 | func = cx.execute("function(a) {return a * dude();}") 65 | ret = func(3) 66 | t.eq(ret, 12) 67 | 68 | def test_bound_method_in_thread(): 69 | class Foo(object): 70 | def __init__(self): 71 | self.t = threading.Thread(target=self.run) 72 | self.t.start() 73 | def run(self): 74 | rt = t.spidermonkey.Runtime() 75 | cx = rt.new_context() 76 | cx.add_global("stuff", self.call) 77 | ret = cx.execute("stuff() * 4;") 78 | t.eq(ret, 8) 79 | def call(self): 80 | return 2 81 | f = Foo() 82 | f.t.join() 83 | 84 | 85 | -------------------------------------------------------------------------------- /spidermonkey/spidermonkey.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | 11 | #ifndef PyMODINIT_FUNC 12 | #define PyMODINIT_FUNC void 13 | #endif 14 | 15 | PyObject* SpidermonkeyModule = NULL; 16 | PyTypeObject* RuntimeType = NULL; 17 | PyTypeObject* ContextType = NULL; 18 | PyTypeObject* ObjectType = NULL; 19 | PyTypeObject* ArrayType = NULL; 20 | PyTypeObject* FunctionType = NULL; 21 | PyTypeObject* IteratorType = NULL; 22 | PyTypeObject* HashCObjType = NULL; 23 | PyObject* JSError = NULL; 24 | 25 | static PyMethodDef spidermonkey_methods[] = { 26 | {NULL} 27 | }; 28 | 29 | PyMODINIT_FUNC 30 | initspidermonkey(void) 31 | { 32 | PyObject* m; 33 | 34 | if(PyType_Ready(&_RuntimeType) < 0) return; 35 | if(PyType_Ready(&_ContextType) < 0) return; 36 | if(PyType_Ready(&_ObjectType) < 0) return; 37 | 38 | _ArrayType.tp_base = &_ObjectType; 39 | if(PyType_Ready(&_ArrayType) < 0) return; 40 | 41 | _FunctionType.tp_base = &_ObjectType; 42 | if(PyType_Ready(&_FunctionType) < 0) return; 43 | 44 | if(PyType_Ready(&_IteratorType) < 0) return; 45 | 46 | if(PyType_Ready(&_HashCObjType) < 0) return; 47 | 48 | m = Py_InitModule3("spidermonkey", spidermonkey_methods, 49 | "The Python-Spidermonkey bridge."); 50 | 51 | if(m == NULL) 52 | { 53 | return; 54 | } 55 | 56 | RuntimeType = &_RuntimeType; 57 | Py_INCREF(RuntimeType); 58 | PyModule_AddObject(m, "Runtime", (PyObject*) RuntimeType); 59 | 60 | ContextType = &_ContextType; 61 | Py_INCREF(ContextType); 62 | PyModule_AddObject(m, "Context", (PyObject*) ContextType); 63 | 64 | ObjectType = &_ObjectType; 65 | Py_INCREF(ObjectType); 66 | PyModule_AddObject(m, "Object", (PyObject*) ObjectType); 67 | 68 | ArrayType = &_ArrayType; 69 | Py_INCREF(ArrayType); 70 | PyModule_AddObject(m, "Array", (PyObject*) ArrayType); 71 | 72 | FunctionType = &_FunctionType; 73 | Py_INCREF(FunctionType); 74 | PyModule_AddObject(m, "Function", (PyObject*) FunctionType); 75 | 76 | IteratorType = &_IteratorType; 77 | Py_INCREF(IteratorType); 78 | // No module access on purpose. 79 | 80 | HashCObjType = &_HashCObjType; 81 | Py_INCREF(HashCObjType); 82 | // Don't add access from the module on purpose. 83 | 84 | JSError = PyErr_NewException("spidermonkey.JSError", NULL, NULL); 85 | PyModule_AddObject(m, "JSError", JSError); 86 | 87 | SpidermonkeyModule = m; 88 | } 89 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsshell.msg: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | /* 41 | Error messages for JSShell. See js.msg for format. 42 | */ 43 | 44 | MSG_DEF(JSSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "") 45 | MSG_DEF(JSSMSG_CANT_OPEN, 1, 2, JSEXN_NONE, "can't open {0}: {1}") 46 | MSG_DEF(JSSMSG_TRAP_USAGE, 2, 0, JSEXN_NONE, "usage: trap [fun] [pc] expr") 47 | MSG_DEF(JSSMSG_LINE2PC_USAGE, 3, 0, JSEXN_NONE, "usage: line2pc [fun] line") 48 | MSG_DEF(JSSMSG_FILE_SCRIPTS_ONLY, 4, 0, JSEXN_NONE, "only works on JS scripts read from files") 49 | MSG_DEF(JSSMSG_UNEXPECTED_EOF, 5, 1, JSEXN_NONE, "unexpected EOF in {0}") 50 | MSG_DEF(JSSMSG_DOEXP_USAGE, 6, 0, JSEXN_NONE, "usage: doexp obj id") 51 | -------------------------------------------------------------------------------- /spidermonkey/error.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | #include "frameobject.h" // Python 11 | #include "traceback.h" // Python 12 | 13 | void 14 | add_frame(const char* srcfile, const char* funcname, int linenum) 15 | { 16 | PyObject* src = NULL; 17 | PyObject* func = NULL; 18 | PyObject* glbl = NULL; 19 | PyObject* tpl = NULL; 20 | PyObject* str = NULL; 21 | PyCodeObject* code = NULL; 22 | PyFrameObject* frame = NULL; 23 | 24 | src = PyString_FromString(srcfile); 25 | if(src == NULL) goto error; 26 | 27 | func = PyString_FromString(funcname); 28 | if(func == NULL) goto error; 29 | 30 | glbl = PyModule_GetDict(SpidermonkeyModule); 31 | if(glbl == NULL) goto error; 32 | 33 | tpl = PyTuple_New(0); 34 | if(tpl == NULL) goto error; 35 | 36 | str = PyString_FromString(""); 37 | if(str == NULL) goto error; 38 | 39 | code = PyCode_New( 40 | 0, /*co_argcount*/ 41 | 0, /*co_nlocals*/ 42 | 0, /*co_stacksize*/ 43 | 0, /*co_flags*/ 44 | str, /*co_code*/ 45 | tpl, /*co_consts*/ 46 | tpl, /*co_names*/ 47 | tpl, /*co_varnames*/ 48 | tpl, /*co_freevars*/ 49 | tpl, /*co_cellvars*/ 50 | src, /*co_filename*/ 51 | func, /*co_name*/ 52 | linenum, /*co_firstlineno*/ 53 | str /*co_lnotab*/ 54 | ); 55 | if(code == NULL) goto error; 56 | 57 | frame = PyFrame_New(PyThreadState_Get(), code, glbl, NULL); 58 | if(frame == NULL) goto error; 59 | 60 | frame->f_lineno = linenum; 61 | PyTraceBack_Here(frame); 62 | 63 | goto success; 64 | 65 | error: 66 | success: 67 | Py_XDECREF(func); 68 | Py_XDECREF(src); 69 | Py_XDECREF(tpl); 70 | Py_XDECREF(str); 71 | Py_XDECREF(code); 72 | Py_XDECREF(frame); 73 | } 74 | 75 | void 76 | report_error_cb(JSContext* cx, const char* message, JSErrorReport* report) 77 | { 78 | const char* srcfile = report->filename; 79 | const char* mesg = message; 80 | 81 | if(!PyErr_Occurred()) 82 | { 83 | PyErr_SetString(JSError, "Error executing JavaScript."); 84 | } 85 | 86 | if(srcfile == NULL) srcfile = ""; 87 | if(mesg == NULL) mesg = ""; 88 | 89 | add_frame(srcfile, mesg, report->lineno); 90 | } 91 | -------------------------------------------------------------------------------- /spidermonkey/convert.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | 11 | jsval 12 | py2js(Context* cx, PyObject* obj) 13 | { 14 | if(obj == Py_None) 15 | { 16 | return JSVAL_NULL; 17 | } 18 | else if(obj == Py_True) 19 | { 20 | return JSVAL_TRUE; 21 | } 22 | else if(obj == Py_False) 23 | { 24 | return JSVAL_FALSE; 25 | } 26 | else if(PyInt_Check(obj) || PyLong_Check(obj)) 27 | { 28 | return py2js_integer(cx, obj); 29 | } 30 | else if(PyFloat_Check(obj)) 31 | { 32 | return py2js_double(cx, obj); 33 | } 34 | else if(PyString_Check(obj) || PyUnicode_Check(obj)) 35 | { 36 | return py2js_string(cx, obj); 37 | } 38 | else if(PyObject_TypeCheck(obj, ObjectType)) 39 | { 40 | return ((Object*) obj)->val; 41 | } 42 | else 43 | { 44 | return py2js_object(cx, obj); 45 | } 46 | 47 | PyErr_SetString(PyExc_ValueError, "Unable to convert Python value to JS."); 48 | return JSVAL_VOID; 49 | } 50 | 51 | PyObject* 52 | js2py(Context* cx, jsval val) 53 | { 54 | return js2py_with_parent(cx, val, JSVAL_NULL); 55 | } 56 | 57 | PyObject* 58 | js2py_with_parent(Context* cx, jsval val, jsval parent) 59 | { 60 | JSType vtype = JS_TypeOfValue(cx->cx, val); 61 | 62 | /* 63 | There's not JSType for null. Or rather, its 64 | reported as Object which causes segfaults. 65 | */ 66 | if(val == JSVAL_NULL || val == JSVAL_VOID) 67 | { 68 | Py_RETURN_NONE; 69 | } 70 | else if(vtype == JSTYPE_BOOLEAN) 71 | { 72 | if(val == JSVAL_TRUE) 73 | { 74 | Py_RETURN_TRUE; 75 | } 76 | else 77 | { 78 | Py_RETURN_FALSE; 79 | } 80 | } 81 | else if(vtype == JSTYPE_STRING) 82 | { 83 | return js2py_string(cx, val); 84 | } 85 | else if(vtype == JSTYPE_NUMBER) 86 | { 87 | if(JSVAL_IS_INT(val)) return js2py_integer(cx, val); 88 | else return js2py_double(cx, val); 89 | } 90 | else if(vtype == JSTYPE_FUNCTION) 91 | { 92 | return js2py_function(cx, val, parent); 93 | } 94 | else if(vtype == JSTYPE_OBJECT) 95 | { 96 | JSObject* obj = JSVAL_TO_OBJECT(val); 97 | if(JS_IsArrayObject(cx->cx, obj)) 98 | { 99 | return js2py_array(cx, val); 100 | } 101 | 102 | return js2py_object(cx, val); 103 | } 104 | 105 | PyErr_SetString(PyExc_RuntimeError, "Unknown JSVAL type."); 106 | return NULL; 107 | } 108 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsbool.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef jsbool_h___ 41 | #define jsbool_h___ 42 | /* 43 | * JS boolean interface. 44 | */ 45 | 46 | JS_BEGIN_EXTERN_C 47 | 48 | /* 49 | * Crypto-booleans, not visible to script but used internally by the engine. 50 | * 51 | * JSVAL_HOLE is a useful value for identifying a hole in an array. It's also 52 | * used in the interpreter to represent "no exception pending". In general it 53 | * can be used to represent "no value". 54 | * 55 | * JSVAL_ARETURN is used to throw asynchronous return for generator.close(). 56 | */ 57 | #define JSVAL_HOLE BOOLEAN_TO_JSVAL(2) 58 | #define JSVAL_ARETURN BOOLEAN_TO_JSVAL(3) 59 | 60 | extern JSClass js_BooleanClass; 61 | 62 | extern JSObject * 63 | js_InitBooleanClass(JSContext *cx, JSObject *obj); 64 | 65 | extern JSObject * 66 | js_BooleanToObject(JSContext *cx, JSBool b); 67 | 68 | extern JSString * 69 | js_BooleanToString(JSContext *cx, JSBool b); 70 | 71 | extern JSBool 72 | js_ValueToBoolean(JSContext *cx, jsval v, JSBool *bp); 73 | 74 | JS_END_EXTERN_C 75 | 76 | #endif /* jsbool_h___ */ 77 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsstddef.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | /* 41 | * stddef inclusion here to first declare ptrdif as a signed long instead of a 42 | * signed int. 43 | */ 44 | 45 | #ifdef _WINDOWS 46 | # ifndef XP_WIN 47 | # define XP_WIN 48 | # endif 49 | #if defined(_WIN32) || defined(WIN32) 50 | # ifndef XP_WIN32 51 | # define XP_WIN32 52 | # endif 53 | #else 54 | # ifndef XP_WIN16 55 | # define XP_WIN16 56 | # endif 57 | #endif 58 | #endif 59 | 60 | #ifdef XP_WIN16 61 | #ifndef _PTRDIFF_T_DEFINED 62 | typedef long ptrdiff_t; 63 | 64 | /* 65 | * The Win16 compiler treats pointer differences as 16-bit signed values. 66 | * This macro allows us to treat them as 17-bit signed values, stored in 67 | * a 32-bit type. 68 | */ 69 | #define PTRDIFF(p1, p2, type) \ 70 | ((((unsigned long)(p1)) - ((unsigned long)(p2))) / sizeof(type)) 71 | 72 | #define _PTRDIFF_T_DEFINED 73 | #endif /*_PTRDIFF_T_DEFINED*/ 74 | #else /*WIN16*/ 75 | 76 | #define PTRDIFF(p1, p2, type) \ 77 | ((p1) - (p2)) 78 | 79 | #endif 80 | 81 | #include 82 | 83 | 84 | -------------------------------------------------------------------------------- /spidermonkey/hashcobj.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | 11 | PyObject* 12 | HashCObj_FromVoidPtr(void *cobj) 13 | { 14 | HashCObj* self = NULL; 15 | 16 | self = PyObject_NEW(HashCObj, HashCObjType); 17 | if(self == NULL) goto error; 18 | self->cobj = cobj; 19 | 20 | goto success; 21 | 22 | error: 23 | success: 24 | return (PyObject*) self; 25 | } 26 | 27 | void* 28 | HashCObj_AsVoidPtr(PyObject* self) 29 | { 30 | return ((HashCObj*)self)->cobj; 31 | } 32 | 33 | int 34 | HashCObj_cmp(PyObject* self, PyObject* other) 35 | { 36 | int ret = -1; 37 | 38 | if(!PyObject_TypeCheck(self, HashCObjType)) 39 | { 40 | PyErr_SetString(PyExc_ValueError, "Invalid comparison object."); 41 | goto error; 42 | } 43 | 44 | if(!PyObject_TypeCheck(other, HashCObjType)) 45 | { 46 | PyErr_SetString(PyExc_ValueError, "Invalid comparison object 2."); 47 | goto error; 48 | } 49 | 50 | if(((HashCObj*)self)->cobj == ((HashCObj*)other)->cobj) 51 | { 52 | ret = 0; 53 | } 54 | else 55 | { 56 | ret = 1; 57 | } 58 | 59 | goto success; 60 | 61 | error: 62 | success: 63 | return ret; 64 | } 65 | 66 | PyObject* 67 | HashCObj_repr(PyObject* self) 68 | { 69 | return PyString_FromFormat("<%s Ptr: %p>", 70 | self->ob_type->tp_name, 71 | ((HashCObj*)self)->cobj); 72 | } 73 | 74 | long 75 | HashCObj_hash(HashCObj* self) 76 | { 77 | return _Py_HashPointer(self->cobj); 78 | } 79 | 80 | PyTypeObject _HashCObjType = { 81 | PyObject_HEAD_INIT(NULL) 82 | 0, /*ob_size*/ 83 | "spidermonkey._HashCObj", /*tp_name*/ 84 | sizeof(HashCObj), /*tp_basicsize*/ 85 | 0, /*tp_itemsize*/ 86 | 0, /*tp_dealloc*/ 87 | 0, /*tp_print*/ 88 | 0, /*tp_getattr*/ 89 | 0, /*tp_setattr*/ 90 | (cmpfunc)HashCObj_cmp, /*tp_compare*/ 91 | (reprfunc)HashCObj_repr, /*tp_repr*/ 92 | 0, /*tp_as_number*/ 93 | 0, /*tp_as_sequence*/ 94 | 0, /*tp_as_mapping*/ 95 | (hashfunc)HashCObj_hash, /*tp_hash*/ 96 | 0, /*tp_call*/ 97 | 0, /*tp_str*/ 98 | 0, /*tp_getattro*/ 99 | 0, /*tp_setattro*/ 100 | 0, /*tp_as_buffer*/ 101 | 0, /*tp_flags*/ 102 | "Internal hashing object.", /*tp_doc*/ 103 | }; 104 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jslog2.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is Mozilla Communicator client code, released 16 | * March 31, 1998. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Netscape Communications Corporation. 20 | * Portions created by the Initial Developer are Copyright (C) 1998 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either of the GNU General Public License Version 2 or later (the "GPL"), 27 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | #include "jsstddef.h" 40 | #include "jsbit.h" 41 | #include "jsutil.h" 42 | 43 | /* 44 | ** Compute the log of the least power of 2 greater than or equal to n 45 | */ 46 | JS_PUBLIC_API(JSIntn) JS_CeilingLog2(JSUint32 n) 47 | { 48 | JSIntn log2; 49 | 50 | JS_CEILING_LOG2(log2, n); 51 | return log2; 52 | } 53 | 54 | /* 55 | ** Compute the log of the greatest power of 2 less than or equal to n. 56 | ** This really just finds the highest set bit in the word. 57 | */ 58 | JS_PUBLIC_API(JSIntn) JS_FloorLog2(JSUint32 n) 59 | { 60 | JSIntn log2; 61 | 62 | JS_FLOOR_LOG2(log2, n); 63 | return log2; 64 | } 65 | 66 | /* 67 | * js_FloorLog2wImpl has to be defined only for 64-bit non-GCC case. 68 | */ 69 | #if !defined(JS_HAS_GCC_BUILTIN_CLZ) && JS_BYTES_PER_WORD == 8 70 | 71 | JSUword 72 | js_FloorLog2wImpl(JSUword n) 73 | { 74 | JSUword log2, m; 75 | 76 | JS_ASSERT(n != 0); 77 | 78 | log2 = 0; 79 | m = n >> 32; 80 | if (m != 0) { n = m; log2 = 32; } 81 | m = n >> 16; 82 | if (m != 0) { n = m; log2 |= 16; } 83 | m = n >> 8; 84 | if (m != 0) { n = m; log2 |= 8; } 85 | m = n >> 4; 86 | if (m != 0) { n = m; log2 |= 4; } 87 | m = n >> 2; 88 | if (m != 0) { n = m; log2 |= 2; } 89 | log2 |= (n >> 1); 90 | 91 | return log2; 92 | } 93 | 94 | #endif 95 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsosdep.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef jsosdep_h___ 41 | #define jsosdep_h___ 42 | /* 43 | * OS (and machine, and compiler XXX) dependent information. 44 | */ 45 | 46 | #if defined(XP_WIN) || defined(XP_OS2) 47 | 48 | #if defined(_WIN32) || defined (XP_OS2) 49 | #define JS_HAVE_LONG_LONG 50 | #else 51 | #undef JS_HAVE_LONG_LONG 52 | #endif 53 | #endif /* XP_WIN || XP_OS2 */ 54 | 55 | #ifdef XP_BEOS 56 | #define JS_HAVE_LONG_LONG 57 | #endif 58 | 59 | 60 | #ifdef XP_UNIX 61 | 62 | /* 63 | * Get OS specific header information. 64 | */ 65 | #if defined(XP_MACOSX) || defined(DARWIN) 66 | #define JS_HAVE_LONG_LONG 67 | 68 | #elif defined(AIXV3) || defined(AIX) 69 | #define JS_HAVE_LONG_LONG 70 | 71 | #elif defined(BSDI) 72 | #define JS_HAVE_LONG_LONG 73 | 74 | #elif defined(HPUX) 75 | #define JS_HAVE_LONG_LONG 76 | 77 | #elif defined(IRIX) 78 | #define JS_HAVE_LONG_LONG 79 | 80 | #elif defined(linux) 81 | #define JS_HAVE_LONG_LONG 82 | 83 | #elif defined(OSF1) 84 | #define JS_HAVE_LONG_LONG 85 | 86 | #elif defined(_SCO_DS) 87 | #undef JS_HAVE_LONG_LONG 88 | 89 | #elif defined(SOLARIS) 90 | #define JS_HAVE_LONG_LONG 91 | 92 | #elif defined(FREEBSD) 93 | #define JS_HAVE_LONG_LONG 94 | 95 | #elif defined(SUNOS4) 96 | #undef JS_HAVE_LONG_LONG 97 | 98 | /* 99 | ** Missing function prototypes 100 | */ 101 | 102 | extern void *sbrk(int); 103 | 104 | #elif defined(UNIXWARE) 105 | #undef JS_HAVE_LONG_LONG 106 | 107 | #elif defined(VMS) && defined(__ALPHA) 108 | #define JS_HAVE_LONG_LONG 109 | 110 | #endif 111 | 112 | #endif /* XP_UNIX */ 113 | 114 | #endif /* jsosdep_h___ */ 115 | 116 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsarray.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef jsarray_h___ 41 | #define jsarray_h___ 42 | /* 43 | * JS Array interface. 44 | */ 45 | #include "jsprvtd.h" 46 | #include "jspubtd.h" 47 | 48 | JS_BEGIN_EXTERN_C 49 | 50 | /* Generous sanity-bound on length (in elements) of array initialiser. */ 51 | #define ARRAY_INIT_LIMIT JS_BIT(24) 52 | 53 | extern JSBool 54 | js_IdIsIndex(jsval id, jsuint *indexp); 55 | 56 | extern JSClass js_ArrayClass; 57 | 58 | extern JSObject * 59 | js_InitArrayClass(JSContext *cx, JSObject *obj); 60 | 61 | extern JSObject * 62 | js_NewArrayObject(JSContext *cx, jsuint length, jsval *vector); 63 | 64 | extern JSBool 65 | js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp); 66 | 67 | extern JSBool 68 | js_SetLengthProperty(JSContext *cx, JSObject *obj, jsuint length); 69 | 70 | extern JSBool 71 | js_HasLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp); 72 | 73 | /* 74 | * Test whether an object is "array-like". Currently this means whether obj 75 | * is an Array or an arguments object. We would like an API, and probably a 76 | * way in the language, to bless other objects as array-like: having indexed 77 | * properties, and a 'length' property of uint32 value equal to one more than 78 | * the greatest index. 79 | */ 80 | extern JSBool 81 | js_IsArrayLike(JSContext *cx, JSObject *obj, JSBool *answerp, jsuint *lengthp); 82 | 83 | /* 84 | * JS-specific heap sort function. 85 | */ 86 | typedef JSBool (*JSComparator)(void *arg, const void *a, const void *b, 87 | int *result); 88 | 89 | extern JSBool 90 | js_HeapSort(void *vec, size_t nel, void *pivot, size_t elsize, 91 | JSComparator cmp, void *arg); 92 | 93 | JS_END_EXTERN_C 94 | 95 | #endif /* jsarray_h___ */ 96 | -------------------------------------------------------------------------------- /old-t/class_test.py: -------------------------------------------------------------------------------- 1 | import types 2 | import unittest 3 | import spidermonkey 4 | 5 | class ClassTests(unittest.TestCase): 6 | def setUp(self): 7 | rt = spidermonkey.Runtime() 8 | self.cx = rt.create_context() 9 | class spam(object): 10 | def __init__(self): 11 | self.args = [] 12 | self.val = 42 13 | self._private = u"no peeking" 14 | def foo(self, *args): 15 | self.args.append(args) 16 | def _private_method(self): 17 | assert False 18 | def __getitem__(self, key): 19 | assert isinstance(key, (types.IntType, types.LongType)) 20 | self.args.append(key) 21 | return self.val 22 | def __setitem__(self, key, value): 23 | assert isinstance(key, (types.IntType, types.LongType)) 24 | self.args.append((key, value)) 25 | self.val = value 26 | self.cx.install_class(spam) 27 | self.spam = spam() 28 | self.cx.bind(u"bs", self.spam) 29 | 30 | def test_private(self): 31 | self.assertEqual(self.cx.execute(u"bs._private;"), None) 32 | self.cx.execute(u"bs._private = 1;") 33 | self.assertEqual(self.spam._private, u"no peeking") 34 | self.assertEqual(self.cx.execute(u"bs._private_method;"), None) 35 | self.assertEqual(self.cx.execute(u"bs._private_method = 1;"), True) 36 | self.assertEqual(isinstance(self.spam._private_method, types.MethodType), True) 37 | # in fact, even normal methods shouldn't be assignable to 38 | self.assertEqual(self.cx.execute(u"bs.foo = 1;"), True) 39 | self.assertEqual(isinstance(self.spam.foo, types.MethodType), True) 40 | 41 | def test_bind_module(self): 42 | self.assertRaises(TypeError, self.cx.install_class, __builtins__) 43 | 44 | def test_no_constructor(self): 45 | class foo: 46 | pass 47 | self.cx.install_class(foo, bind_constructor=False) 48 | self.assertRaises(spidermonkey.JSError, self.cx.execute, u"var f = new foo();") 49 | f2 = foo() 50 | self.cx.bind(u"f2", f2) 51 | self.assertEqual(self.cx.execute(u"f2;"), f2) 52 | 53 | def test_js_specific(self): 54 | class bar: 55 | __jsname__ = u"eggs" 56 | def __init__(self, arg): 57 | self.arg = arg 58 | 59 | @staticmethod 60 | def __jsinit__(cx): 61 | return bar(42) 62 | self.cx.install_class(bar) 63 | self.cx.execute(u"var e = new eggs();") 64 | self.assertEqual(self.cx.execute(u"e.arg;"), 42) 65 | 66 | def test_assign_new_property(self): 67 | self.cx.execute(u"bs.xyzzy = 1;") 68 | self.assertEqual(self.cx.execute(u"bs.xyzzy;"), 1) 69 | 70 | def test_identity(self): 71 | self.assertEqual(self.cx.execute(u"bs;"), self.spam) 72 | 73 | def test_call(self): 74 | self.cx.execute(u'bs.foo("hi");') 75 | self.assertEqual(self.spam.args.pop(), (u"hi",)) 76 | 77 | def test_construct(self): 78 | s = self.cx.execute(u"""\ 79 | var s = new spam(); 80 | s.foo(1, "blah", ["1", 2, "three"]); 81 | s; 82 | """) 83 | self.assertEqual(s.args.pop(), (1, u"blah", [u"1", 2, u"three"])) 84 | 85 | def test_getsetitem(self): 86 | # property lookup with an integer is mapped to __get/__setitem__ 87 | self.assertEqual(self.cx.execute(u"bs[0];"), 42) 88 | self.cx.execute(u"bs[0] = 2;") 89 | self.assertEqual(self.cx.execute(u"bs[0];"), 2) 90 | 91 | if __name__ == "__main__": 92 | unittest.main() 93 | -------------------------------------------------------------------------------- /spidermonkey/libjs/prmjtime.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef prmjtime_h___ 41 | #define prmjtime_h___ 42 | /* 43 | * PR date stuff for mocha and java. Placed here temporarily not to break 44 | * Navigator and localize changes to mocha. 45 | */ 46 | #include 47 | #include "jslong.h" 48 | #ifdef MOZILLA_CLIENT 49 | #include "jscompat.h" 50 | #endif 51 | 52 | JS_BEGIN_EXTERN_C 53 | 54 | typedef struct PRMJTime PRMJTime; 55 | 56 | /* 57 | * Broken down form of 64 bit time value. 58 | */ 59 | struct PRMJTime { 60 | JSInt32 tm_usec; /* microseconds of second (0-999999) */ 61 | JSInt8 tm_sec; /* seconds of minute (0-59) */ 62 | JSInt8 tm_min; /* minutes of hour (0-59) */ 63 | JSInt8 tm_hour; /* hour of day (0-23) */ 64 | JSInt8 tm_mday; /* day of month (1-31) */ 65 | JSInt8 tm_mon; /* month of year (0-11) */ 66 | JSInt8 tm_wday; /* 0=sunday, 1=monday, ... */ 67 | JSInt16 tm_year; /* absolute year, AD */ 68 | JSInt16 tm_yday; /* day of year (0 to 365) */ 69 | JSInt8 tm_isdst; /* non-zero if DST in effect */ 70 | }; 71 | 72 | /* Some handy constants */ 73 | #define PRMJ_USEC_PER_SEC 1000000L 74 | #define PRMJ_USEC_PER_MSEC 1000L 75 | 76 | /* Return the current local time in micro-seconds */ 77 | extern JSInt64 78 | PRMJ_Now(void); 79 | 80 | /* get the difference between this time zone and gmt timezone in seconds */ 81 | extern JSInt32 82 | PRMJ_LocalGMTDifference(void); 83 | 84 | /* Format a time value into a buffer. Same semantics as strftime() */ 85 | extern size_t 86 | PRMJ_FormatTime(char *buf, int buflen, char *fmt, PRMJTime *tm); 87 | 88 | /* Get the DST offset for the local time passed in */ 89 | extern JSInt64 90 | PRMJ_DSTOffset(JSInt64 local_time); 91 | 92 | JS_END_EXTERN_C 93 | 94 | #endif /* prmjtime_h___ */ 95 | 96 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsutil.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | /* 41 | * PR assertion checker. 42 | */ 43 | 44 | #ifndef jsutil_h___ 45 | #define jsutil_h___ 46 | 47 | JS_BEGIN_EXTERN_C 48 | 49 | #ifdef DEBUG 50 | 51 | extern JS_PUBLIC_API(void) 52 | JS_Assert(const char *s, const char *file, JSIntn ln); 53 | #define JS_ASSERT(_expr) \ 54 | ((_expr)?((void)0):JS_Assert(# _expr,__FILE__,__LINE__)) 55 | 56 | #define JS_NOT_REACHED(_reasonStr) \ 57 | JS_Assert(_reasonStr,__FILE__,__LINE__) 58 | 59 | #else 60 | 61 | #define JS_ASSERT(expr) ((void) 0) 62 | #define JS_NOT_REACHED(reasonStr) 63 | 64 | #endif /* defined(DEBUG) */ 65 | 66 | /* 67 | * Compile-time assert. "condition" must be a constant expression. 68 | * The macro should be used only once per source line in places where 69 | * a "typedef" declaration is allowed. 70 | */ 71 | #define JS_STATIC_ASSERT(condition) \ 72 | JS_STATIC_ASSERT_IMPL(condition, __LINE__) 73 | #define JS_STATIC_ASSERT_IMPL(condition, line) \ 74 | JS_STATIC_ASSERT_IMPL2(condition, line) 75 | #define JS_STATIC_ASSERT_IMPL2(condition, line) \ 76 | typedef int js_static_assert_line_##line[(condition) ? 1 : -1] 77 | 78 | /* 79 | ** Abort the process in a non-graceful manner. This will cause a core file, 80 | ** call to the debugger or other moral equivalent as well as causing the 81 | ** entire process to stop. 82 | */ 83 | extern JS_PUBLIC_API(void) JS_Abort(void); 84 | 85 | #ifdef XP_UNIX 86 | 87 | typedef struct JSCallsite JSCallsite; 88 | 89 | struct JSCallsite { 90 | uint32 pc; 91 | char *name; 92 | const char *library; 93 | int offset; 94 | JSCallsite *parent; 95 | JSCallsite *siblings; 96 | JSCallsite *kids; 97 | void *handy; 98 | }; 99 | 100 | extern JSCallsite *JS_Backtrace(int skip); 101 | 102 | #endif 103 | 104 | JS_END_EXTERN_C 105 | 106 | #endif /* jsutil_h___ */ 107 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsexn.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | /* 41 | * JS runtime exception classes. 42 | */ 43 | 44 | #ifndef jsexn_h___ 45 | #define jsexn_h___ 46 | 47 | JS_BEGIN_EXTERN_C 48 | 49 | extern JSClass js_ErrorClass; 50 | 51 | /* 52 | * Initialize the exception constructor/prototype hierarchy. 53 | */ 54 | extern JSObject * 55 | js_InitExceptionClasses(JSContext *cx, JSObject *obj); 56 | 57 | /* 58 | * Given a JSErrorReport, check to see if there is an exception associated with 59 | * the error number. If there is, then create an appropriate exception object, 60 | * set it as the pending exception, and set the JSREPORT_EXCEPTION flag on the 61 | * error report. Exception-aware host error reporters should probably ignore 62 | * error reports so flagged. Returns JS_TRUE if an associated exception is 63 | * found and set, JS_FALSE otherwise.. 64 | */ 65 | extern JSBool 66 | js_ErrorToException(JSContext *cx, const char *message, JSErrorReport *reportp); 67 | 68 | /* 69 | * Called if a JS API call to js_Execute or js_InternalCall fails; calls the 70 | * error reporter with the error report associated with any uncaught exception 71 | * that has been raised. Returns true if there was an exception pending, and 72 | * the error reporter was actually called. 73 | * 74 | * The JSErrorReport * that the error reporter is called with is currently 75 | * associated with a JavaScript object, and is not guaranteed to persist after 76 | * the object is collected. Any persistent uses of the JSErrorReport contents 77 | * should make their own copy. 78 | * 79 | * The flags field of the JSErrorReport will have the JSREPORT_EXCEPTION flag 80 | * set; embeddings that want to silently propagate JavaScript exceptions to 81 | * other contexts may want to use an error reporter that ignores errors with 82 | * this flag. 83 | */ 84 | extern JSBool 85 | js_ReportUncaughtException(JSContext *cx); 86 | 87 | extern JSErrorReport * 88 | js_ErrorFromException(JSContext *cx, jsval exn); 89 | 90 | extern const JSErrorFormatString * 91 | js_GetLocalizedErrorMessage(JSContext* cx, void *userRef, const char *locale, 92 | const uintN errorNumber); 93 | 94 | JS_END_EXTERN_C 95 | 96 | #endif /* jsexn_h___ */ 97 | -------------------------------------------------------------------------------- /tests/test-global.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # 3 | # This file is part of the python-spidermonkey package released 4 | # under the MIT license. 5 | import t 6 | 7 | @t.cx() 8 | def test_bind_global(cx): 9 | cx.add_global("foo", "yay spring!") 10 | t.eq(cx.execute("foo;"), "yay spring!") 11 | 12 | @t.cx() 13 | def test_use_global(cx): 14 | cx.add_global("biz", 3) 15 | t.eq(cx.execute("biz * biz;"), 9) 16 | 17 | @t.cx() 18 | def test_unicode_in_global(cx): 19 | cx.add_global(u"\u00FC", 234) 20 | t.eq(cx.execute(u"\u00FC;"), 234) 21 | 22 | @t.cx() 23 | def test_unbind_global(cx): 24 | cx.add_global("bizzle", 29) 25 | t.eq(cx.execute("bizzle"), 29) 26 | t.eq(cx.rem_global("bizzle"), 29) 27 | t.raises(t.JSError, cx.execute, "bizzle") 28 | 29 | @t.cx() 30 | def test_unbinding_unicode(cx): 31 | cx.add_global(u"\u00E9", 734) 32 | t.eq(cx.execute(u"\u00E9;"), 734) 33 | t.eq(cx.rem_global(u"\u00E9"), 734) 34 | t.raises(t.JSError, cx.execute, u"\u00E9") 35 | 36 | class Foo(object): 37 | def __init__(self): 38 | self.blam = 8 39 | 40 | @t.glbl("rain", Foo()) 41 | def test_attr_fetch(cx, glbl): 42 | t.eq(cx.execute("rain.blam;"), 8) 43 | 44 | @t.glbl("rain", Foo()) 45 | def test_attr_mutate(cx, glbl): 46 | cx.execute("rain.blam = 4;") 47 | t.eq(glbl.blam, 4) 48 | 49 | @t.glbl("rain", Foo()) 50 | def test_attr_usage(cx, glbl): 51 | t.eq(cx.execute("rain.blam / 2;"), 4) 52 | 53 | @t.glbl("rain", Foo()) 54 | def test_repeated_usage(cx, glbl): 55 | t.eq(cx.execute("rain.blam = 3; rain.blam / 3;"), 1) 56 | 57 | @t.glbl("rain", Foo()) 58 | def test_js_rem_attr(cx, glbl): 59 | t.has(glbl, "blam") 60 | cx.execute("delete rain.blam;") 61 | t.hasnot(glbl, "blam") 62 | 63 | @t.rt() 64 | def test_py_with_global(rt): 65 | rt.new_context({}) 66 | 67 | @t.rt() 68 | def test_py_with_invalid_global(rt): 69 | t.raises(TypeError, rt.new_context, "Break!") 70 | 71 | @t.rt() 72 | def test_py_get_global(rt): 73 | glbl = {"foo": "bar"} 74 | cx = rt.new_context(glbl) 75 | t.eq(cx.execute("foo;"), "bar") 76 | 77 | @t.rt() 78 | def test_py_global_by_kwarg(rt): 79 | glbl = {"foo": "bar"} 80 | cx = rt.new_context(glbl=glbl) 81 | t.eq(cx.execute("foo;"), "bar") 82 | 83 | @t.rt() 84 | def test_py_set_global(rt): 85 | glbl = {} 86 | cx = rt.new_context(glbl) 87 | cx.execute("foo = 71;") 88 | t.eq(cx.execute("foo;"), 71); 89 | t.eq(glbl["foo"], 71) 90 | 91 | class FunctionTest(object): 92 | def __init__(self): 93 | self.data = {} 94 | def __getitem__(self, key): 95 | return self.data[key] 96 | def __setitem__(self, key, value): 97 | self.data[key] = value 98 | 99 | @t.rt() 100 | def test_py_set_function_global(rt): 101 | glbl = FunctionTest() 102 | cx = rt.new_context(glbl) 103 | cx.execute("function foo() {};") 104 | t.is_js_object(glbl["foo"]) 105 | 106 | class ActiveGlobal(object): 107 | def __init__(self): 108 | self.data = {} 109 | def __getitem__(self, key): 110 | return self.data[key] 111 | def __setitem__(self, key, value): 112 | self.data[key] = value * 2 113 | 114 | @t.rt() 115 | def test_py_no_del_item(rt): 116 | glbl = ActiveGlobal() 117 | cx = rt.new_context(glbl) 118 | cx.execute('foo = 4;') 119 | t.eq(glbl.data["foo"], 8) 120 | cx.execute("delete foo;") 121 | t.isin("foo", glbl.data) 122 | 123 | class ActiveGlobalWithDel(ActiveGlobal): 124 | def __delitem__(self, key): 125 | del self.data[key] 126 | 127 | @t.rt() 128 | def test_py_del_global(rt): 129 | glbl = ActiveGlobalWithDel() 130 | cx = rt.new_context(glbl) 131 | cx.execute("foo = 4;") 132 | t.eq(glbl.data["foo"], 8) 133 | cx.execute("delete foo;") 134 | t.isnotin("foo", glbl.data) 135 | 136 | @t.rt() 137 | def test_py_with_active_global(rt): 138 | glbl = ActiveGlobal() 139 | cx = rt.new_context(glbl) 140 | cx.execute("foo = 4;") 141 | t.eq(cx.execute("foo;"), 8) 142 | t.eq(glbl.data["foo"], 8); 143 | -------------------------------------------------------------------------------- /tests/test-access.py: -------------------------------------------------------------------------------- 1 | # Copyright 2009 Paul J. Davis 2 | # Copyright 2009 Richard Boulton 3 | # 4 | # This file is part of the python-spidermonkey package released 5 | # under the MIT license. 6 | import t 7 | 8 | @t.cx() 9 | def test_set_callback(cx): 10 | t.eq(cx.set_access(), None) 11 | t.raises(TypeError, cx.set_access, "foo") 12 | t.raises(TypeError, cx.set_access, 1) 13 | def cb(obj, name): return True 14 | t.eq(cx.set_access(cb), None) 15 | t.eq(cx.set_access(), cb) 16 | # Check that we don't erase it. 17 | t.eq(cx.set_access(), cb) 18 | 19 | @t.cx() 20 | def test_always_callback(cx): 21 | names = [] 22 | def fn(obj, name): 23 | names.append(name) 24 | return True 25 | cx.set_access(fn) 26 | cx.add_global("foo", {"bar": "baz"}) 27 | t.eq(cx.execute('foo["bar"]'), "baz") 28 | t.eq(names, ["bar"]) 29 | 30 | @t.cx() 31 | def test_no_underscores(cx): 32 | def fn(obj, name): 33 | return name.strip()[:1] != "_" 34 | cx.set_access(fn) 35 | cx.add_global("foo", {"bar": "baz", "_bar": "_baz"}) 36 | t.eq(cx.execute('foo["bar"]'), "baz") 37 | t.raises(t.JSError, cx.execute, 'foo["_bar"]') 38 | 39 | @t.cx() 40 | def test_no_set_invalid(cx): 41 | def fn(obj, name): 42 | return name.strip()[:1] != "_" 43 | cx.set_access(fn) 44 | glbl = {} 45 | cx.add_global("foo", glbl) 46 | cx.execute('foo["bar"] = "baz";') 47 | t.raises(t.JSError, cx.execute, 'foo["_bar"] = "baz"') 48 | t.eq(glbl, {"bar": "baz"}) 49 | 50 | @t.rt() 51 | def test_access_in_ctor(rt): 52 | def fn(obj, name): 53 | return name != "bing" 54 | cx = rt.new_context(access=fn) 55 | cx.add_global("foo", {"bing": "boo"}) 56 | t.raises(t.JSError, cx.execute, 'foo["bing"];') 57 | 58 | @t.rt() 59 | def test_access_global(rt): 60 | names = [] 61 | def fn(obj, name): 62 | names.append(name) 63 | return not name.startswith("_") 64 | glbl = {"foo": "bar", "_bin": "zingle"} 65 | cx = rt.new_context(glbl, fn) 66 | t.eq(cx.execute('foo;'), "bar") 67 | t.raises(t.JSError, cx.execute, '_bin;') 68 | t.eq(names, ["foo", "foo", "_bin"]) 69 | 70 | @t.cx() 71 | def test_dissallow_ctor(cx): 72 | class DirtyCar(object): 73 | def __init__(self): 74 | self.zap = 2 75 | def check(obj, name): 76 | return name != "__init__" 77 | cx.add_global("DirtyCar", DirtyCar) 78 | cx.set_access(check) 79 | t.raises(t.JSError, cx.execute, "DirtyCall();") 80 | 81 | @t.cx() 82 | def test_dissalow_call(cx): 83 | class PepsiCan(object): 84 | def __init__(self): 85 | self.caffeine = "zaney!" 86 | def __call__(self, arg): 87 | return arg * 2 88 | def check(obj, name): 89 | return name != "__call__" 90 | cx.add_global("PepsiCan", PepsiCan) 91 | cx.set_access(check) 92 | t.eq(cx.execute("var c = new PepsiCan(); c.caffeine;"), "zaney!") 93 | t.raises(t.JSError, cx.execute, "c();") 94 | 95 | @t.cx() 96 | def test_on_wrapped_obj(cx): 97 | class ShamWow(object): 98 | def __init__(self): 99 | self.bar = 2 100 | self._bing = 3 101 | def func(): 102 | return ShamWow() 103 | cx.add_global("whee", func) 104 | 105 | def check(obj, name): 106 | return name in ["__call__", "__init__"] or not name.startswith("_") 107 | cx.set_access(check); 108 | 109 | t.eq(cx.execute("var f = whee(); f.bar;"), 2) 110 | t.raises(t.JSError, cx.execute, "f._bing") 111 | 112 | @t.cx() 113 | def test_obj_method(cx): 114 | class Checker(object): 115 | def __init__(self): 116 | self.names = [] 117 | def check(self, obj, name): 118 | self.names.append(name) 119 | return name != "kablooie" 120 | c = Checker() 121 | cx.set_access(c.check) 122 | cx.add_global("bing", {"kablooie": "bar", "bing": 3}) 123 | t.eq(cx.execute('bing["bing"]'), 3) 124 | t.raises(t.JSError, cx.execute, 'bing["kablooie"]') 125 | t.eq(c.names, ["bing", "kablooie"]) 126 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsdate.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | /* 41 | * JS Date class interface. 42 | */ 43 | 44 | #ifndef jsdate_h___ 45 | #define jsdate_h___ 46 | 47 | JS_BEGIN_EXTERN_C 48 | 49 | extern JSClass js_DateClass; 50 | 51 | extern JSObject * 52 | js_InitDateClass(JSContext *cx, JSObject *obj); 53 | 54 | /* 55 | * These functions provide a C interface to the date/time object 56 | */ 57 | 58 | /* 59 | * Construct a new Date Object from a time value given in milliseconds UTC 60 | * since the epoch. 61 | */ 62 | extern JS_FRIEND_API(JSObject*) 63 | js_NewDateObjectMsec(JSContext* cx, jsdouble msec_time); 64 | 65 | /* 66 | * Construct a new Date Object from an exploded local time value. 67 | */ 68 | extern JS_FRIEND_API(JSObject*) 69 | js_NewDateObject(JSContext* cx, int year, int mon, int mday, 70 | int hour, int min, int sec); 71 | 72 | /* 73 | * Detect whether the internal date value is NaN. (Because failure is 74 | * out-of-band for js_DateGet*) 75 | */ 76 | extern JS_FRIEND_API(JSBool) 77 | js_DateIsValid(JSContext *cx, JSObject* obj); 78 | 79 | extern JS_FRIEND_API(int) 80 | js_DateGetYear(JSContext *cx, JSObject* obj); 81 | 82 | extern JS_FRIEND_API(int) 83 | js_DateGetMonth(JSContext *cx, JSObject* obj); 84 | 85 | extern JS_FRIEND_API(int) 86 | js_DateGetDate(JSContext *cx, JSObject* obj); 87 | 88 | extern JS_FRIEND_API(int) 89 | js_DateGetHours(JSContext *cx, JSObject* obj); 90 | 91 | extern JS_FRIEND_API(int) 92 | js_DateGetMinutes(JSContext *cx, JSObject* obj); 93 | 94 | extern JS_FRIEND_API(int) 95 | js_DateGetSeconds(JSContext *cx, JSObject* obj); 96 | 97 | extern JS_FRIEND_API(void) 98 | js_DateSetYear(JSContext *cx, JSObject *obj, int year); 99 | 100 | extern JS_FRIEND_API(void) 101 | js_DateSetMonth(JSContext *cx, JSObject *obj, int year); 102 | 103 | extern JS_FRIEND_API(void) 104 | js_DateSetDate(JSContext *cx, JSObject *obj, int date); 105 | 106 | extern JS_FRIEND_API(void) 107 | js_DateSetHours(JSContext *cx, JSObject *obj, int hours); 108 | 109 | extern JS_FRIEND_API(void) 110 | js_DateSetMinutes(JSContext *cx, JSObject *obj, int minutes); 111 | 112 | extern JS_FRIEND_API(void) 113 | js_DateSetSeconds(JSContext *cx, JSObject *obj, int seconds); 114 | 115 | extern JS_FRIEND_API(jsdouble) 116 | js_DateGetMsecSinceEpoch(JSContext *cx, JSObject *obj); 117 | 118 | JS_END_EXTERN_C 119 | 120 | #endif /* jsdate_h___ */ 121 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsiter.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * vim: set ts=8 sw=4 et tw=78: 3 | * 4 | * ***** BEGIN LICENSE BLOCK ***** 5 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef jsiter_h___ 41 | #define jsiter_h___ 42 | /* 43 | * JavaScript iterators. 44 | */ 45 | #include "jsprvtd.h" 46 | #include "jspubtd.h" 47 | 48 | #define JSITER_ENUMERATE 0x1 /* for-in compatible hidden default iterator */ 49 | #define JSITER_FOREACH 0x2 /* return [key, value] pair rather than key */ 50 | #define JSITER_KEYVALUE 0x4 /* destructuring for-in wants [key, value] */ 51 | 52 | extern void 53 | js_CloseNativeIterator(JSContext *cx, JSObject *iterobj); 54 | 55 | extern void 56 | js_CloseIteratorState(JSContext *cx, JSObject *iterobj); 57 | 58 | /* 59 | * Convert the value stored in *vp to its iteration object. The flags should 60 | * contain JSITER_ENUMERATE if js_ValueToIterator is called when enumerating 61 | * for-in semantics are required, and when the caller can guarantee that the 62 | * iterator will never be exposed to scripts. 63 | */ 64 | extern JSBool 65 | js_ValueToIterator(JSContext *cx, uintN flags, jsval *vp); 66 | 67 | /* 68 | * Given iterobj, call iterobj.next(). If the iterator stopped, set *rval to 69 | * JSVAL_HOLE. Otherwise set it to the result of the next call. 70 | */ 71 | extern JSBool 72 | js_CallIteratorNext(JSContext *cx, JSObject *iterobj, jsval *rval); 73 | 74 | #if JS_HAS_GENERATORS 75 | 76 | /* 77 | * Generator state codes. 78 | */ 79 | typedef enum JSGeneratorState { 80 | JSGEN_NEWBORN, /* not yet started */ 81 | JSGEN_OPEN, /* started by a .next() or .send(undefined) call */ 82 | JSGEN_RUNNING, /* currently executing via .next(), etc., call */ 83 | JSGEN_CLOSING, /* close method is doing asynchronous return */ 84 | JSGEN_CLOSED /* closed, cannot be started or closed again */ 85 | } JSGeneratorState; 86 | 87 | struct JSGenerator { 88 | JSGenerator *next; 89 | JSObject *obj; 90 | JSGeneratorState state; 91 | JSStackFrame frame; 92 | JSArena arena; 93 | jsval stack[1]; 94 | }; 95 | 96 | #define FRAME_TO_GENERATOR(fp) \ 97 | ((JSGenerator *) ((uint8 *)(fp) - offsetof(JSGenerator, frame))) 98 | 99 | extern JSObject * 100 | js_NewGenerator(JSContext *cx, JSStackFrame *fp); 101 | 102 | extern JSBool 103 | js_CloseGeneratorObject(JSContext *cx, JSGenerator *gen); 104 | 105 | #endif 106 | 107 | extern JSClass js_GeneratorClass; 108 | extern JSClass js_IteratorClass; 109 | extern JSClass js_StopIterationClass; 110 | 111 | extern JSObject * 112 | js_InitIteratorClasses(JSContext *cx, JSObject *obj); 113 | 114 | #endif /* jsiter_h___ */ 115 | -------------------------------------------------------------------------------- /old-sm/jshelpers.c: -------------------------------------------------------------------------------- 1 | JSString* py2js_jsstring_c(JSContext* cx, PyObject* str) 2 | { 3 | PyObject* encoded = NULL; 4 | char* bytes; 5 | Py_ssize_t len; 6 | 7 | if(!PyUnicode_Check(str)) 8 | { 9 | return NULL; 10 | } 11 | 12 | encoded = PyUnicode_AsEncodedString(str, "utf-16", "strict"); 13 | if(encoded == NULL) 14 | { 15 | return NULL; 16 | } 17 | 18 | if(PyString_AsStringAndSize(encoded, &bytes, &len) < 0) 19 | { 20 | return NULL; 21 | } 22 | 23 | if(len < 4) 24 | { 25 | return NULL; 26 | } 27 | 28 | // No idea why python adds FFFE to encoded UTF-16 data. 29 | return JS_NewUCStringCopyN(cx, bytes+2, (len/2)-1); 30 | } 31 | 32 | PyObject* js2py_jsstring_c(JSString* str) 33 | { 34 | jschar* bytes; 35 | size_t len; 36 | 37 | if(str == NULL) 38 | { 39 | return NULL; 40 | } 41 | 42 | len = JS_GetStringLength(str); 43 | bytes = JS_GetStringChars(str); 44 | 45 | return PyUnicode_Decode((const char*) bytes, (size_t) (len * 2), "utf-16", "strict"); 46 | } 47 | 48 | void 49 | js_context_attach(JSContext* cx, PyObject* obj) 50 | { 51 | Py_XINCREF(obj); 52 | JS_SetContextPrivate(cx, (void*) obj); 53 | } 54 | 55 | JSBool 56 | js_context_has_data(JSContext* cx) 57 | { 58 | if(JS_GetContextPrivate(cx) == NULL) 59 | { 60 | return JS_FALSE; 61 | } 62 | 63 | return JS_TRUE; 64 | } 65 | 66 | PyObject* 67 | js_context_fetch(JSContext* cx) 68 | { 69 | PyObject* obj = (PyObject*) JS_GetContextPrivate(cx); 70 | Py_XINCREF(obj); 71 | return obj; 72 | } 73 | 74 | PyObject* 75 | js_context_destroy(JSContext* cx) 76 | { 77 | PyObject* ret = (PyObject*) JS_GetContextPrivate(cx); 78 | return ret; 79 | } 80 | 81 | void 82 | js_object_attach(JSContext* cx, JSObject* js_obj, PyObject* py_obj) 83 | { 84 | Py_XINCREF(py_obj); 85 | JS_SetPrivate(cx, js_obj, (void*) py_obj); 86 | } 87 | 88 | JSBool 89 | js_object_has_data(JSContext* cx, JSObject* js_obj) 90 | { 91 | JSClass* class = JS_GetClass(cx, js_obj); 92 | 93 | if(class == NULL) 94 | { 95 | return JS_FALSE; 96 | } 97 | 98 | if(!(class->flags & JSCLASS_HAS_PRIVATE)) 99 | { 100 | return JS_FALSE; 101 | } 102 | 103 | if(JS_GetPrivate(cx, js_obj) == NULL) 104 | { 105 | return JS_FALSE; 106 | } 107 | 108 | return JS_TRUE; 109 | } 110 | 111 | PyObject* 112 | js_object_fetch(JSContext* cx, JSObject* js_obj) 113 | { 114 | PyObject* py_obj = (PyObject*) JS_GetPrivate(cx, js_obj); 115 | Py_XINCREF(py_obj); 116 | return py_obj; 117 | } 118 | 119 | PyObject* 120 | js_object_destroy(JSContext* cx, JSObject* js_obj) 121 | { 122 | return (PyObject*) JS_GetPrivate(cx, js_obj); 123 | } 124 | 125 | void 126 | js_function_attach(JSContext* cx, JSObject* js_obj, PyObject* py_obj) 127 | { 128 | Py_XINCREF(py_obj); 129 | jsval slot = PRIVATE_TO_JSVAL(py_obj); 130 | JS_SetReservedSlot(cx, js_obj, 0, slot); 131 | } 132 | 133 | JSBool 134 | js_function_has_data(JSContext* cx, JSObject* js_obj) 135 | { 136 | jsval slot; 137 | if(JS_GetReservedSlot(cx, js_obj, 0, &slot) != JS_TRUE) 138 | { 139 | return JS_FALSE; 140 | } 141 | 142 | void* data = JSVAL_TO_PRIVATE(slot); 143 | 144 | if(data == NULL) 145 | { 146 | return JS_FALSE; 147 | } 148 | 149 | return JS_TRUE; 150 | } 151 | 152 | PyObject* 153 | js_function_fetch(JSContext* cx, JSObject* js_obj) 154 | { 155 | jsval slot; 156 | if(JS_GetReservedSlot(cx, js_obj, 0, &slot) != JS_TRUE) 157 | { 158 | return JS_FALSE; 159 | } 160 | 161 | PyObject* py_obj = (PyObject*) JSVAL_TO_PRIVATE(slot); 162 | Py_XINCREF(py_obj); 163 | return py_obj; 164 | } 165 | 166 | PyObject* 167 | js_function_destroy(JSContext* cx, JSObject* js_obj) 168 | { 169 | jsval slot; 170 | if(JS_GetReservedSlot(cx, js_obj, 0, &slot) != JS_TRUE) 171 | { 172 | return JS_FALSE; 173 | } 174 | 175 | PyObject* py_obj = (PyObject*) JSVAL_TO_PRIVATE(slot); 176 | return py_obj; 177 | } 178 | 179 | static JSClass js_global_class = 180 | { 181 | "RootObjectClass", 182 | JSCLASS_GLOBAL_FLAGS, 183 | JS_PropertyStub, 184 | JS_PropertyStub, 185 | JS_PropertyStub, 186 | JS_PropertyStub, 187 | JS_EnumerateStub, 188 | JS_ResolveStub, 189 | JS_ConvertStub, 190 | JS_FinalizeStub, 191 | JSCLASS_NO_OPTIONAL_MEMBERS 192 | }; 193 | 194 | JSObject * 195 | js_make_global_object(JSContext *cx) 196 | { 197 | return JS_NewObject(cx, &js_global_class, NULL, NULL); 198 | } 199 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsclist.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is Mozilla Communicator client code, released 16 | * March 31, 1998. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Netscape Communications Corporation. 20 | * Portions created by the Initial Developer are Copyright (C) 1998 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either of the GNU General Public License Version 2 or later (the "GPL"), 27 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | #ifndef jsclist_h___ 40 | #define jsclist_h___ 41 | 42 | #include "jstypes.h" 43 | 44 | /* 45 | ** Circular linked list 46 | */ 47 | typedef struct JSCListStr { 48 | struct JSCListStr *next; 49 | struct JSCListStr *prev; 50 | } JSCList; 51 | 52 | /* 53 | ** Insert element "_e" into the list, before "_l". 54 | */ 55 | #define JS_INSERT_BEFORE(_e,_l) \ 56 | JS_BEGIN_MACRO \ 57 | (_e)->next = (_l); \ 58 | (_e)->prev = (_l)->prev; \ 59 | (_l)->prev->next = (_e); \ 60 | (_l)->prev = (_e); \ 61 | JS_END_MACRO 62 | 63 | /* 64 | ** Insert element "_e" into the list, after "_l". 65 | */ 66 | #define JS_INSERT_AFTER(_e,_l) \ 67 | JS_BEGIN_MACRO \ 68 | (_e)->next = (_l)->next; \ 69 | (_e)->prev = (_l); \ 70 | (_l)->next->prev = (_e); \ 71 | (_l)->next = (_e); \ 72 | JS_END_MACRO 73 | 74 | /* 75 | ** Return the element following element "_e" 76 | */ 77 | #define JS_NEXT_LINK(_e) \ 78 | ((_e)->next) 79 | /* 80 | ** Return the element preceding element "_e" 81 | */ 82 | #define JS_PREV_LINK(_e) \ 83 | ((_e)->prev) 84 | 85 | /* 86 | ** Append an element "_e" to the end of the list "_l" 87 | */ 88 | #define JS_APPEND_LINK(_e,_l) JS_INSERT_BEFORE(_e,_l) 89 | 90 | /* 91 | ** Insert an element "_e" at the head of the list "_l" 92 | */ 93 | #define JS_INSERT_LINK(_e,_l) JS_INSERT_AFTER(_e,_l) 94 | 95 | /* Return the head/tail of the list */ 96 | #define JS_LIST_HEAD(_l) (_l)->next 97 | #define JS_LIST_TAIL(_l) (_l)->prev 98 | 99 | /* 100 | ** Remove the element "_e" from it's circular list. 101 | */ 102 | #define JS_REMOVE_LINK(_e) \ 103 | JS_BEGIN_MACRO \ 104 | (_e)->prev->next = (_e)->next; \ 105 | (_e)->next->prev = (_e)->prev; \ 106 | JS_END_MACRO 107 | 108 | /* 109 | ** Remove the element "_e" from it's circular list. Also initializes the 110 | ** linkage. 111 | */ 112 | #define JS_REMOVE_AND_INIT_LINK(_e) \ 113 | JS_BEGIN_MACRO \ 114 | (_e)->prev->next = (_e)->next; \ 115 | (_e)->next->prev = (_e)->prev; \ 116 | (_e)->next = (_e); \ 117 | (_e)->prev = (_e); \ 118 | JS_END_MACRO 119 | 120 | /* 121 | ** Return non-zero if the given circular list "_l" is empty, zero if the 122 | ** circular list is not empty 123 | */ 124 | #define JS_CLIST_IS_EMPTY(_l) \ 125 | ((_l)->next == (_l)) 126 | 127 | /* 128 | ** Initialize a circular list 129 | */ 130 | #define JS_INIT_CLIST(_l) \ 131 | JS_BEGIN_MACRO \ 132 | (_l)->next = (_l); \ 133 | (_l)->prev = (_l); \ 134 | JS_END_MACRO 135 | 136 | #define JS_INIT_STATIC_CLIST(_l) \ 137 | {(_l), (_l)} 138 | 139 | #endif /* jsclist_h___ */ 140 | -------------------------------------------------------------------------------- /old-sm/jscontext.pxi: -------------------------------------------------------------------------------- 1 | 2 | class JSRootObject(object): 3 | pass 4 | 5 | cdef class Context: 6 | cdef JSContext* cx 7 | cdef Runtime rt 8 | cdef ObjectAdapter root 9 | cdef GC gc 10 | cdef object reg 11 | cdef object classes 12 | cdef object error 13 | 14 | def __cinit__(self, Runtime rt, root): 15 | self.rt = rt 16 | 17 | STACK_CHUNK_SIZE = 8192 18 | 19 | self.cx = JS_NewContext(rt.rt, STACK_CHUNK_SIZE) 20 | if self.cx == NULL: 21 | raise JSError("Failed to create Context") 22 | 23 | def __init__(Context self, Runtime rt, root): 24 | cdef ClassAdapter ca 25 | cdef JSObject* js_obj 26 | cdef PyObject* py_obj 27 | 28 | self.gc = GC(self) 29 | self.reg = {} 30 | self.classes = {} 31 | self.error = None 32 | 33 | js_context_attach(self.cx, self) 34 | 35 | if not root: 36 | root = JSRootObject() 37 | 38 | ca = self.install_class(root.__class__, False, True) 39 | js_obj = JS_NewObject(self.cx, ca.js_class, NULL, NULL) 40 | if js_obj == NULL: 41 | raise JSError("Failed to create root object.") 42 | self.root = ObjectAdapter(self, ca, None, root) 43 | self.root.js_obj = js_obj 44 | js_object_attach(self.cx, self.root.js_obj, self.root) 45 | 46 | if not JS_InitStandardClasses(self.cx, js_obj): 47 | raise JSError("Failed to initialize standard classes.") 48 | 49 | JS_SetErrorReporter(self.cx, __report_error_callback__) 50 | 51 | def __dealloc__(self): 52 | JS_DestroyContext(self.cx) 53 | 54 | def install_class(self, py_class, bind_constructor=True, is_global=False, flags=0): 55 | """\ 56 | Install a Python class into the JavaScript runtime. 57 | """ 58 | if not inspect.isclass(py_class): 59 | raise TypeError("Unable to install %r as a class." % py_class) 60 | if not isinstance(flags, (types.IntType, types.LongType)): 61 | raise TypeError("Flags is not an integer.") 62 | 63 | if py_class in self.classes: 64 | return self.classes[py_class] 65 | 66 | ca = ClassAdapter(self, self.root, py_class, bind_constructor, is_global, flags) 67 | self.classes[py_class] = ca 68 | return ca 69 | 70 | def bind(Context self, name, obj): 71 | """\ 72 | Attach a Python object to the JavaScript runtime. 73 | 74 | You should be able to attach most types of Python objects 75 | including builtin types, object instances, functions etc. About 76 | the only thing you can't bind is a Python class which should 77 | be isntalled into the JavaScript environment using 78 | Context.install_class 79 | 80 | This call will bind the provided object `obj` to the JS root. The 81 | Python value is also referenced to keep it from being garbage 82 | collected. 83 | """ 84 | cdef ClassAdapter ca 85 | cdef jsval jsv 86 | cdef PyJSString js_str 87 | 88 | js_str = py2js_jsstring(self.cx, name) 89 | 90 | ca = self.install_class(obj.__class__) 91 | jsv = py2js(self, obj, self.root.js_obj) 92 | if not JS_DefineUCProperty(self.cx, self.root.js_obj, js_str.chars(), js_str.length(), jsv, 93 | __get_property_callback__, __set_property_callback__, 0): 94 | raise JSError("Failed to bind Python object to the global object.") 95 | 96 | def unbind(Context self, name): 97 | cdef jsval rval 98 | cdef PyJSString js_str 99 | 100 | js_str = py2js_jsstring(self.cx, name) 101 | 102 | ret = self.execute(name + unicode(";")) # yeah yeah, I know. 103 | if not JS_DeleteUCProperty2(self.cx, self.root.js_obj, js_str.chars(), js_str.length(), &rval): 104 | raise JSError("Failed to unbind property: %s" % name) 105 | # This always returns True for some reason 106 | #return js2py(self, rval) 107 | return ret 108 | 109 | def execute(Context self, script): 110 | """\ 111 | Execute JavaScript source code. 112 | """ 113 | cdef jsval rval 114 | cdef PyJSString js_str 115 | 116 | js_str = py2js_jsstring(self.cx, script) 117 | 118 | try: 119 | if not JS_EvaluateUCScript(self.cx, self.root.js_obj, js_str.chars(), js_str.length(), "Python", 0, &rval): 120 | raise JSError(self.error) 121 | return js2py(self, rval) 122 | finally: 123 | self.gc.run_maybe() 124 | 125 | def set_error(self, mesg): 126 | self.error = mesg 127 | 128 | 129 | -------------------------------------------------------------------------------- /spidermonkey/runtime.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | 11 | PyObject* 12 | Runtime_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) 13 | { 14 | Runtime* self = NULL; 15 | unsigned int stacksize = 0x2000000; // 32 MiB heap size. 16 | 17 | if(!PyArg_ParseTuple(args, "|I", &stacksize)) goto error; 18 | 19 | self = (Runtime*) type->tp_alloc(type, 0); 20 | if(self == NULL) goto error; 21 | 22 | self->rt = JS_NewRuntime(stacksize); 23 | if(self->rt == NULL) goto error; 24 | 25 | goto success; 26 | 27 | error: 28 | Py_XDECREF(self); 29 | 30 | success: 31 | return (PyObject*) self; 32 | } 33 | 34 | int 35 | Runtime_init(Runtime* self, PyObject* args, PyObject* kwargs) 36 | { 37 | return 0; 38 | } 39 | 40 | void 41 | Runtime_dealloc(Runtime* self) 42 | { 43 | if(self->rt != NULL) 44 | { 45 | JS_DestroyRuntime(self->rt); 46 | } 47 | } 48 | 49 | PyObject* 50 | Runtime_new_context(Runtime* self, PyObject* args, PyObject* kwargs) 51 | { 52 | PyObject* cx = NULL; 53 | PyObject* tpl = NULL; 54 | PyObject* global = Py_None; 55 | PyObject* access = Py_None; 56 | 57 | char* keywords[] = {"glbl", "access", NULL}; 58 | 59 | if(!PyArg_ParseTupleAndKeywords( 60 | args, kwargs, 61 | "|OO", 62 | keywords, 63 | &global, 64 | &access 65 | )) goto error; 66 | 67 | tpl = Py_BuildValue("OOO", self, global, access); 68 | if(tpl == NULL) goto error; 69 | 70 | cx = PyObject_CallObject((PyObject*) ContextType, tpl); 71 | goto success; 72 | 73 | error: 74 | Py_XDECREF(cx); 75 | 76 | success: 77 | Py_XDECREF(tpl); 78 | return cx; 79 | } 80 | 81 | static PyMemberDef Runtime_members[] = { 82 | {NULL} 83 | }; 84 | 85 | static PyMethodDef Runtime_methods[] = { 86 | { 87 | "new_context", 88 | (PyCFunction)Runtime_new_context, 89 | METH_VARARGS | METH_KEYWORDS, 90 | "Create a new JavaScript Context." 91 | }, 92 | {NULL} 93 | }; 94 | 95 | PyTypeObject _RuntimeType = { 96 | PyObject_HEAD_INIT(NULL) 97 | 0, /*ob_size*/ 98 | "spidermonkey.Runtime", /*tp_name*/ 99 | sizeof(Runtime), /*tp_basicsize*/ 100 | 0, /*tp_itemsize*/ 101 | (destructor)Runtime_dealloc, /*tp_dealloc*/ 102 | 0, /*tp_print*/ 103 | 0, /*tp_getattr*/ 104 | 0, /*tp_setattr*/ 105 | 0, /*tp_compare*/ 106 | 0, /*tp_repr*/ 107 | 0, /*tp_as_number*/ 108 | 0, /*tp_as_sequence*/ 109 | 0, /*tp_as_mapping*/ 110 | 0, /*tp_hash*/ 111 | 0, /*tp_call*/ 112 | 0, /*tp_str*/ 113 | 0, /*tp_getattro*/ 114 | 0, /*tp_setattro*/ 115 | 0, /*tp_as_buffer*/ 116 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 117 | "JavaScript Runtime", /*tp_doc*/ 118 | 0, /*tp_traverse*/ 119 | 0, /*tp_clear*/ 120 | 0, /*tp_richcompare*/ 121 | 0, /*tp_weaklistoffset*/ 122 | 0, /*tp_iter*/ 123 | 0, /*tp_iternext*/ 124 | Runtime_methods, /*tp_methods*/ 125 | Runtime_members, /*tp_members*/ 126 | 0, /*tp_getset*/ 127 | 0, /*tp_base*/ 128 | 0, /*tp_dict*/ 129 | 0, /*tp_descr_get*/ 130 | 0, /*tp_descr_set*/ 131 | 0, /*tp_dictoffset*/ 132 | (initproc)Runtime_init, /*tp_init*/ 133 | 0, /*tp_alloc*/ 134 | Runtime_new, /*tp_new*/ 135 | }; 136 | 137 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsproto.tbl: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * vim: set sw=4 ts=8 et tw=80 ft=c: 3 | * 4 | * ***** BEGIN LICENSE BLOCK ***** 5 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 6 | * 7 | * The contents of this file are subject to the Mozilla Public License Version 8 | * 1.1 (the "License"); you may not use this file except in compliance with 9 | * the License. You may obtain a copy of the License at 10 | * http://www.mozilla.org/MPL/ 11 | * 12 | * Software distributed under the License is distributed on an "AS IS" basis, 13 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 14 | * for the specific language governing rights and limitations under the 15 | * License. 16 | * 17 | * The Original Code is SpiderMonkey 1.7 work in progress, released 18 | * February 14, 2006. 19 | * 20 | * The Initial Developer of the Original Code is 21 | * Brendan Eich 22 | * 23 | * Contributor(s): 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either of the GNU General Public License Version 2 or later (the "GPL"), 27 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | #include "jsconfig.h" 40 | 41 | #if JS_HAS_SCRIPT_OBJECT 42 | # define SCRIPT_INIT js_InitScriptClass 43 | #else 44 | # define SCRIPT_INIT js_InitNullClass 45 | #endif 46 | 47 | #if JS_HAS_XML_SUPPORT 48 | # define XML_INIT js_InitXMLClass 49 | # define NAMESPACE_INIT js_InitNamespaceClass 50 | # define QNAME_INIT js_InitQNameClass 51 | # define ANYNAME_INIT js_InitAnyNameClass 52 | # define ATTRIBUTE_INIT js_InitAttributeNameClass 53 | #else 54 | # define XML_INIT js_InitNullClass 55 | # define NAMESPACE_INIT js_InitNullClass 56 | # define QNAME_INIT js_InitNullClass 57 | # define ANYNAME_INIT js_InitNullClass 58 | # define ATTRIBUTE_INIT js_InitNullClass 59 | #endif 60 | 61 | #if JS_HAS_GENERATORS 62 | # define GENERATOR_INIT js_InitIteratorClasses 63 | #else 64 | # define GENERATOR_INIT js_InitNullClass 65 | #endif 66 | 67 | #if JS_HAS_FILE_OBJECT 68 | # define FILE_INIT js_InitFileClass 69 | #else 70 | # define FILE_INIT js_InitNullClass 71 | #endif 72 | 73 | /* 74 | * Enumerator codes in the second column must not change -- they are part of 75 | * the JS XDR API. 76 | */ 77 | JS_PROTO(Null, 0, js_InitNullClass) 78 | JS_PROTO(Object, 1, js_InitFunctionAndObjectClasses) 79 | JS_PROTO(Function, 2, js_InitFunctionAndObjectClasses) 80 | JS_PROTO(Array, 3, js_InitArrayClass) 81 | JS_PROTO(Boolean, 4, js_InitBooleanClass) 82 | JS_PROTO(Call, 5, js_InitCallClass) 83 | JS_PROTO(Date, 6, js_InitDateClass) 84 | JS_PROTO(Math, 7, js_InitMathClass) 85 | JS_PROTO(Number, 8, js_InitNumberClass) 86 | JS_PROTO(String, 9, js_InitStringClass) 87 | JS_PROTO(RegExp, 10, js_InitRegExpClass) 88 | JS_PROTO(Script, 11, SCRIPT_INIT) 89 | JS_PROTO(XML, 12, XML_INIT) 90 | JS_PROTO(Namespace, 13, NAMESPACE_INIT) 91 | JS_PROTO(QName, 14, QNAME_INIT) 92 | JS_PROTO(AnyName, 15, ANYNAME_INIT) 93 | JS_PROTO(AttributeName, 16, ATTRIBUTE_INIT) 94 | JS_PROTO(Error, 17, js_InitExceptionClasses) 95 | JS_PROTO(InternalError, 18, js_InitExceptionClasses) 96 | JS_PROTO(EvalError, 19, js_InitExceptionClasses) 97 | JS_PROTO(RangeError, 20, js_InitExceptionClasses) 98 | JS_PROTO(ReferenceError, 21, js_InitExceptionClasses) 99 | JS_PROTO(SyntaxError, 22, js_InitExceptionClasses) 100 | JS_PROTO(TypeError, 23, js_InitExceptionClasses) 101 | JS_PROTO(URIError, 24, js_InitExceptionClasses) 102 | JS_PROTO(Generator, 25, GENERATOR_INIT) 103 | JS_PROTO(Iterator, 26, js_InitIteratorClasses) 104 | JS_PROTO(StopIteration, 27, js_InitIteratorClasses) 105 | JS_PROTO(UnusedProto28, 28, js_InitNullClass) 106 | JS_PROTO(File, 29, FILE_INIT) 107 | JS_PROTO(Block, 30, js_InitBlockClass) 108 | 109 | #undef SCRIPT_INIT 110 | #undef XML_INIT 111 | #undef NAMESPACE_INIT 112 | #undef QNAME_INIT 113 | #undef ANYNAME_INIT 114 | #undef ATTRIBUTE_INIT 115 | #undef GENERATOR_INIT 116 | #undef FILE_INIT 117 | -------------------------------------------------------------------------------- /old-sm/jsfunction.pxi: -------------------------------------------------------------------------------- 1 | 2 | cdef class Function: 3 | cdef Context cx 4 | cdef jsval func 5 | 6 | def __init__(Function self, Context cx): 7 | self.cx = cx 8 | 9 | def __call__(Function self, *args): 10 | cdef jsval* argv 11 | cdef jsval rval 12 | cdef jsval jsarg 13 | 14 | nr_args = len(args) 15 | argv = xmalloc(sizeof(jsval) * nr_args) 16 | try: 17 | for i from 0 <= i < nr_args: 18 | arg = args[i] 19 | jsarg = py2js(self.cx, arg, NULL) 20 | argv[i] = jsarg 21 | 22 | if not JS_CallFunctionValue(self.cx.cx, self.cx.root.js_obj, self.func, nr_args, argv, &rval): 23 | raise JSError(self.cx.error) 24 | finally: 25 | free(argv) 26 | 27 | retval = js2py(self.cx, rval) 28 | self.cx.gc.run_maybe() 29 | 30 | return retval 31 | 32 | def __dealloc__(Function self): 33 | JS_RemoveRoot(self.cx.cx, &self.func) 34 | 35 | 36 | cdef class FunctionAdapter: 37 | cdef Context cx 38 | cdef JSObject* js_obj 39 | cdef object py_obj 40 | 41 | def __cinit__(FunctionAdapter self, Context cx, object obj): 42 | self.cx = cx 43 | self.py_obj = obj 44 | 45 | def __repr__(self): 46 | return "" % self.py_obj 47 | 48 | 49 | cdef JSBool __bound_method_callback__(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval): 50 | cdef Context pycx 51 | cdef ObjectAdapter oa 52 | cdef JSFunction* jsfunc 53 | cdef int i 54 | 55 | try: 56 | if not js_context_has_data(cx): 57 | raise JSError("Unknown JSContext object.") 58 | 59 | pycx = js_context_fetch(cx) 60 | 61 | if not js_object_has_data(cx, obj): 62 | return JS_FALSE 63 | 64 | oa = js_object_fetch(cx, obj) 65 | 66 | jsfunc = JS_ValueToFunction(cx, argv[-2]) 67 | method_name = JS_GetFunctionName(jsfunc) 68 | method = getattr(oa.py_obj, method_name) 69 | 70 | args = [None] * argc 71 | for i from 0 <= i < argc: 72 | args[i] = js2py(pycx, argv[i]) 73 | 74 | py_rval = method(*args) 75 | rval[0] = py2js(pycx, py_rval, obj) 76 | 77 | return JS_TRUE 78 | except: 79 | return report_python_error(cx) 80 | 81 | cdef JSBool __function_callback__(JSContext* cx, JSObject* obj, uintN argc, jsval* argv, jsval* rval): 82 | cdef Context pycx 83 | cdef FunctionAdapter fa 84 | cdef JSFunction* jsfunc 85 | cdef JSObject* jsobj 86 | cdef int i 87 | 88 | try: 89 | if not js_context_has_data(cx): 90 | raise JSError("Unknown JSContext object.") 91 | 92 | pycx = js_context_fetch(cx) 93 | jsfunc = JS_ValueToFunction(cx, argv[-2]) 94 | jsobj = JS_GetFunctionObject(jsfunc) 95 | 96 | if not js_function_has_data(cx, jsobj): 97 | raise JSError("Function call back without attached functor.") 98 | 99 | fa = js_function_fetch(cx, jsobj) 100 | 101 | args = [None] * argc 102 | for i from 0 <= i < argc: 103 | args[i] = js2py(pycx, argv[i]) 104 | 105 | py_rval = fa.py_obj(*args) 106 | rval[0] = py2js(pycx, py_rval, obj) 107 | 108 | return JS_TRUE 109 | except: 110 | return report_python_error(cx) 111 | 112 | def js_is_function(Context cx, jsval jsv): 113 | return JS_TypeOfValue(cx.cx, jsv) == JSTYPE_FUNCTION 114 | 115 | def py_is_function(Context cx, object py_obj): 116 | return isinstance(py_obj, (types.FunctionType, types.LambdaType)) 117 | 118 | def py_is_bound_method(Context cx, object py_obj): 119 | return isinstance(py_obj, types.MethodType) 120 | 121 | cdef object js2py_function(Context cx, jsval jsv): 122 | cdef Function ret 123 | ret = Function(cx) 124 | ret.func = jsv 125 | JS_AddRoot(cx.cx, &ret.func) 126 | return ret 127 | 128 | cdef jsval py2js_bound_method(Context cx, object py_obj, JSObject* parent): 129 | cdef FunctionAdapter fa 130 | cdef JSFunction* func 131 | cdef JSObject* obj 132 | 133 | if hasattr(py_obj, "func_name"): 134 | name = py_obj.func_name 135 | elif hasattr(py_obj, "im_fun") and hasattr(py_obj.im_fun, "func_name"): 136 | name = py_obj.im_fun.func_name 137 | else: 138 | raise JSError("Failed to find function name.") 139 | 140 | func = JS_NewFunction(cx.cx, __bound_method_callback__, 0, 0, NULL, name) 141 | obj = JS_GetFunctionObject(func) 142 | return OBJECT_TO_JSVAL(obj) 143 | 144 | cdef jsval py2js_function(Context cx, object py_obj, JSObject* parent): 145 | cdef FunctionAdapter fa 146 | cdef JSFunction* func 147 | cdef JSObject* obj 148 | cdef jsval slot 149 | 150 | if hasattr(py_obj, "func_name"): 151 | name = py_obj.func_name 152 | elif hasattr(py_obj, "im_fun") and hasattr(py_obj.im_fun, "func_name"): 153 | name = py_obj.im_fun.func_name 154 | else: 155 | raise JSError("Failed to find function name.") 156 | 157 | func = JS_NewFunction(cx.cx, __function_callback__, 0, 0, NULL, name) 158 | fa = FunctionAdapter(cx, py_obj) 159 | fa.js_obj = JS_GetFunctionObject(func) 160 | 161 | js_function_attach(cx.cx, fa.js_obj, fa) 162 | 163 | return OBJECT_TO_JSVAL(fa.js_obj) 164 | -------------------------------------------------------------------------------- /spidermonkey/jsarray.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | 11 | PyObject* 12 | js2py_array(Context* cx, jsval val) 13 | { 14 | return make_object(ArrayType, cx, val); 15 | } 16 | 17 | Py_ssize_t 18 | Array_length(Object* self) 19 | { 20 | Py_ssize_t ret = -1; 21 | jsuint length; 22 | 23 | JS_BeginRequest(self->cx->cx); 24 | 25 | if(!JS_GetArrayLength(self->cx->cx, self->obj, &length)) 26 | { 27 | PyErr_SetString(PyExc_AttributeError, "Failed to get array length."); 28 | goto done; 29 | } 30 | 31 | ret = (Py_ssize_t) length; 32 | 33 | done: 34 | JS_EndRequest(self->cx->cx); 35 | return ret; 36 | } 37 | 38 | PyObject* 39 | Array_get_item(Object* self, Py_ssize_t idx) 40 | { 41 | PyObject* ret = NULL; 42 | jsval rval; 43 | jsint pos = (jsint) idx; 44 | 45 | JS_BeginRequest(self->cx->cx); 46 | 47 | if(idx >= Array_length(self)) 48 | { 49 | PyErr_SetString(PyExc_IndexError, "List index out of range."); 50 | goto done; 51 | } 52 | 53 | if(!JS_GetElement(self->cx->cx, self->obj, pos, &rval)) 54 | { 55 | PyErr_SetString(PyExc_AttributeError, "Failed to get array item."); 56 | goto done; 57 | } 58 | 59 | ret = js2py(self->cx, rval); 60 | 61 | done: 62 | JS_EndRequest(self->cx->cx); 63 | return ret; 64 | } 65 | 66 | int 67 | Array_set_item(Object* self, Py_ssize_t idx, PyObject* val) 68 | { 69 | int ret = -1; 70 | jsval pval; 71 | jsint pos = (jsint) idx; 72 | 73 | JS_BeginRequest(self->cx->cx); 74 | 75 | pval = py2js(self->cx, val); 76 | if(pval == JSVAL_VOID) goto done; 77 | 78 | if(!JS_SetElement(self->cx->cx, self->obj, pos, &pval)) 79 | { 80 | PyErr_SetString(PyExc_AttributeError, "Failed to set array item."); 81 | goto done; 82 | } 83 | 84 | ret = 0; 85 | 86 | done: 87 | JS_EndRequest(self->cx->cx); 88 | return ret; 89 | } 90 | 91 | PyObject* 92 | Array_iterator(Object* self) 93 | { 94 | return PySeqIter_New((PyObject*) self); 95 | } 96 | 97 | static PyMemberDef Array_members[] = { 98 | {0, 0, 0, 0} 99 | }; 100 | 101 | static PyMethodDef Array_methods[] = { 102 | {0, 0, 0, 0} 103 | }; 104 | 105 | static PySequenceMethods Array_seq_methods = { 106 | (lenfunc)Array_length, /*sq_length*/ 107 | 0, /*sq_concat*/ 108 | 0, /*sq_repeat*/ 109 | (ssizeargfunc)Array_get_item, /*sq_item*/ 110 | 0, /*sq_slice*/ 111 | (ssizeobjargproc)Array_set_item, /*sq_ass_item*/ 112 | 0, /*sq_ass_slice*/ 113 | 0, /*sq_contains*/ 114 | 0, /*sq_inplace_concat*/ 115 | 0, /*sq_inplace_repeat*/ 116 | }; 117 | 118 | PyTypeObject _ArrayType = { 119 | PyObject_HEAD_INIT(NULL) 120 | 0, /*ob_size*/ 121 | "spidermonkey.Array", /*tp_name*/ 122 | sizeof(Object), /*tp_basicsize*/ 123 | 0, /*tp_itemsize*/ 124 | 0, /*tp_dealloc*/ 125 | 0, /*tp_print*/ 126 | 0, /*tp_getattr*/ 127 | 0, /*tp_setattr*/ 128 | 0, /*tp_compare*/ 129 | 0, /*tp_repr*/ 130 | 0, /*tp_as_number*/ 131 | &Array_seq_methods, /*tp_as_sequence*/ 132 | 0, /*tp_as_mapping*/ 133 | 0, /*tp_hash*/ 134 | 0, /*tp_call*/ 135 | 0, /*tp_str*/ 136 | 0, /*tp_getattro*/ 137 | 0, /*tp_setattro*/ 138 | 0, /*tp_as_buffer*/ 139 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 140 | "JavaScript Array", /*tp_doc*/ 141 | 0, /*tp_traverse*/ 142 | 0, /*tp_clear*/ 143 | 0, /*tp_richcompare*/ 144 | 0, /*tp_weaklistoffset*/ 145 | (getiterfunc)Array_iterator, /*tp_iter*/ 146 | 0, /*tp_iternext*/ 147 | Array_methods, /*tp_methods*/ 148 | Array_members, /*tp_members*/ 149 | 0, /*tp_getset*/ 150 | 0, /*tp_base*/ 151 | 0, /*tp_dict*/ 152 | 0, /*tp_descr_get*/ 153 | 0, /*tp_descr_set*/ 154 | 0, /*tp_dictoffset*/ 155 | 0, /*tp_init*/ 156 | 0, /*tp_alloc*/ 157 | 0, /*tp_new*/ 158 | }; 159 | -------------------------------------------------------------------------------- /spidermonkey/jsiterator.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | 11 | PyObject* 12 | Iterator_Wrap(Context* cx, JSObject* obj) 13 | { 14 | Iterator* self = NULL; 15 | PyObject* tpl = NULL; 16 | PyObject* ret = NULL; 17 | 18 | JS_BeginRequest(cx->cx); 19 | 20 | // Build our new python object. 21 | tpl = Py_BuildValue("(O)", cx); 22 | if(tpl == NULL) goto error; 23 | 24 | self = (Iterator*) PyObject_CallObject((PyObject*) IteratorType, tpl); 25 | if(self == NULL) goto error; 26 | 27 | // Attach a JS property iterator. 28 | self->iter = JS_NewPropertyIterator(cx->cx, obj); 29 | if(self->iter == NULL) goto error; 30 | 31 | self->root = OBJECT_TO_JSVAL(self->iter); 32 | if(!JS_AddRoot(cx->cx, &(self->root))) 33 | { 34 | PyErr_SetString(PyExc_RuntimeError, "Failed to set GC root."); 35 | goto error; 36 | } 37 | 38 | ret = (PyObject*) self; 39 | goto success; 40 | 41 | error: 42 | Py_XDECREF(self); 43 | ret = NULL; // In case it was AddRoot 44 | success: 45 | Py_XDECREF(tpl); 46 | JS_EndRequest(cx->cx); 47 | return (PyObject*) ret; 48 | } 49 | 50 | PyObject* 51 | Iterator_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) 52 | { 53 | Context* cx = NULL; 54 | Iterator* self = NULL; 55 | 56 | if(!PyArg_ParseTuple(args, "O!", ContextType, &cx)) goto error; 57 | 58 | self = (Iterator*) type->tp_alloc(type, 0); 59 | if(self == NULL) goto error; 60 | 61 | Py_INCREF(cx); 62 | self->cx = cx; 63 | self->iter = NULL; 64 | goto success; 65 | 66 | error: 67 | ERROR("spidermonkey.Iterator.new"); 68 | success: 69 | return (PyObject*) self; 70 | } 71 | 72 | int 73 | Iterator_init(Iterator* self, PyObject* args, PyObject* kwargs) 74 | { 75 | return 0; 76 | } 77 | 78 | void 79 | Iterator_dealloc(Iterator* self) 80 | { 81 | if(self->iter != NULL) 82 | { 83 | JS_BeginRequest(self->cx->cx); 84 | JS_RemoveRoot(self->cx->cx, &(self->root)); 85 | JS_EndRequest(self->cx->cx); 86 | } 87 | 88 | Py_XDECREF(self->cx); 89 | } 90 | 91 | PyObject* 92 | Iterator_next(Iterator* self) 93 | { 94 | PyObject* ret = NULL; 95 | jsid propid; 96 | jsval propname; 97 | 98 | JS_BeginRequest(self->cx->cx); 99 | 100 | if(!JS_NextProperty(self->cx->cx, self->iter, &propid)) 101 | { 102 | PyErr_SetString(PyExc_RuntimeError, "Failed to iterate next JS prop."); 103 | goto done; 104 | } 105 | 106 | if(!JS_IdToValue(self->cx->cx, propid, &propname)) 107 | { 108 | PyErr_SetString(PyExc_RuntimeError, "Failed to convert property id."); 109 | goto done; 110 | } 111 | 112 | if(propname != JSVAL_VOID) 113 | { 114 | ret = js2py(self->cx, propname); 115 | } 116 | 117 | // We return NULL with no error to signal completion. 118 | 119 | done: 120 | JS_EndRequest(self->cx->cx); 121 | return ret; 122 | } 123 | 124 | static PyMemberDef Iterator_members[] = { 125 | {NULL} 126 | }; 127 | 128 | static PyMethodDef Iterator_methods[] = { 129 | {NULL} 130 | }; 131 | 132 | PyTypeObject _IteratorType = { 133 | PyObject_HEAD_INIT(NULL) 134 | 0, /*ob_size*/ 135 | "spidermonkey.Iterator", /*tp_name*/ 136 | sizeof(Iterator), /*tp_basicsize*/ 137 | 0, /*tp_itemsize*/ 138 | (destructor)Iterator_dealloc, /*tp_dealloc*/ 139 | 0, /*tp_print*/ 140 | 0, /*tp_getattr*/ 141 | 0, /*tp_setattr*/ 142 | 0, /*tp_compare*/ 143 | 0, /*tp_repr*/ 144 | 0, /*tp_as_number*/ 145 | 0, /*tp_as_sequence*/ 146 | 0, /*tp_as_mapping*/ 147 | 0, /*tp_hash*/ 148 | 0, /*tp_call*/ 149 | 0, /*tp_str*/ 150 | 0, /*tp_getattro*/ 151 | 0, /*tp_setattro*/ 152 | 0, /*tp_as_buffer*/ 153 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 154 | "JavaScript Iterator", /*tp_doc*/ 155 | 0, /*tp_traverse*/ 156 | 0, /*tp_clear*/ 157 | 0, /*tp_richcompare*/ 158 | 0, /*tp_weaklistoffset*/ 159 | 0, /*tp_iter*/ 160 | (iternextfunc)Iterator_next, /*tp_iternext*/ 161 | Iterator_methods, /*tp_methods*/ 162 | Iterator_members, /*tp_members*/ 163 | 0, /*tp_getset*/ 164 | 0, /*tp_base*/ 165 | 0, /*tp_dict*/ 166 | 0, /*tp_descr_get*/ 167 | 0, /*tp_descr_set*/ 168 | 0, /*tp_dictoffset*/ 169 | (initproc)Iterator_init, /*tp_init*/ 170 | 0, /*tp_alloc*/ 171 | Iterator_new, /*tp_new*/ 172 | }; 173 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Execute arbitrary JavaScript code from Python. Allows you to reference 3 | arbitrary Python objects and functions in the JavaScript VM 4 | 5 | Having issues? 6 | ============== 7 | 8 | The project support site can be found at [lighthouseapp.com][lh]. 9 | 10 | Requirements 11 | ============ 12 | 13 | Pkg-Config 14 | ---------- 15 | 16 | Mac OS X: 17 | 18 | This should be installed by default. If not there is a port package: 19 | 20 | $ sudo port install pkgconfig 21 | 22 | Debian/Ubuntu: 23 | 24 | This is also generally installed by default, but I have reports of it being 25 | otherwise. 26 | 27 | $ sudo apt-get install pkg-config 28 | 29 | Gentoo: 30 | 31 | XXX: Can anyone verify this package name? 32 | 33 | $ sudo emerge pkgconfig 34 | 35 | Python Development Files 36 | ------------------------ 37 | 38 | Mac OS X: 39 | 40 | If you installed Python via port then the headers should already be installed. 41 | I have not heard reports of problems from people using the bundled 42 | interpreters. 43 | 44 | Debian/Ubuntu: 45 | 46 | $ sudo apt-get install pythonX.X-dev 47 | 48 | Where X.X is the version of Python you are using. I have not tested 49 | python-spidermonkey on Py3K so it may be horribly broken there. 50 | 51 | Gentoo: 52 | 53 | If you have python installed, then the headers should already be installed. 54 | 55 | Netscape Portable Runtime (nspr) 56 | -------------------------------- 57 | 58 | The nspr library is required for building the Spidermonkey sources. You should 59 | be able to grab it from your package manager of choice with something like the 60 | following: 61 | 62 | Mac OS X: 63 | 64 | $ sudo port install nspr 65 | 66 | Debian/Ubuntu: 67 | 68 | $ sudo apt-get install libnspr4-dev 69 | 70 | Gentoo: 71 | 72 | $ sudo emerge nspr 73 | 74 | Alternatively you can build from [source][nspr]. If you choose this route make 75 | sure that the nspr-config command is on your $PATH when running the install 76 | commands below. 77 | 78 | If you choose this route make 79 | sure that the pkg-config command is on your `$PATH` when running the install 80 | commands below. Additionally, make sure that `$PKG_CONFIG_PATH` is properly 81 | set. 82 | 83 | XULRunner (optional) 84 | -------------------- 85 | You can optionally build the extension linked to your system's spidermonkey 86 | library, which is installed with XULRunner. You should be able to grab it from 87 | your package manager of choice with something like the following: 88 | 89 | Mac OS X: 90 | 91 | $ sudo port install xulrunner 92 | 93 | Debian/Ubuntu: 94 | 95 | $ sudo apt-get install xulrunner-1.9-dev 96 | 97 | Gentoo: 98 | 99 | $ sudo emerge xulrunner 100 | 101 | As with [nspr][nspr], you can also build [xulrunner][xulrunner] from source. And as with [nspr][nspr] you need to make sure hat `$PATH` and `$PKG_CONFIG_PATH` are properly set when building the module. 102 | 103 | Installation 104 | ============ 105 | 106 | $ git clone git://github.com/davisp/python-spidermonkey.git 107 | $ cd python-spidermonkey 108 | $ python setup.py build 109 | $ python setup.py test 110 | 111 | $ sudo python setup.py install 112 | 113 | *OR* 114 | 115 | $ sudo python setup.py develop 116 | 117 | If you want to build with the system spidermonkey library, replace the build 118 | command with the following: 119 | 120 | $ python setup.py --system-library build 121 | 122 | Examples 123 | ======== 124 | 125 | Basics 126 | ------ 127 | 128 | >>> import spidermonkey 129 | >>> rt = spidermonkey.Runtime() 130 | >>> cx = rt.new_context() 131 | >>> cx.execute("var x = 3; x *= 4; x;") 132 | 12 133 | >>> class Orange(object): 134 | ... def is_ripe(self,arg): 135 | ... return "ripe %s" % arg 136 | ... 137 | >>> fruit = Orange() 138 | >>> cx.add_global("apple", fruit) 139 | >>> cx.execute('"Show me the " + apple.is_ripe("raisin");') 140 | u'Show me the ripe raisin' 141 | 142 | 143 | Playing with Classes 144 | -------------------- 145 | 146 | >>> import spidermonkey 147 | >>> class Monkey(object): 148 | ... def __init__(self): 149 | ... self.baz = "blammo" 150 | ... def wrench(self, arg): 151 | ... return "%s now wrenched" % arg 152 | ... 153 | >>> rt = spidermonkey.Runtime() 154 | >>> cx = rt.new_context() 155 | >>> cx.add_global("Monkey", Monkey) 156 | >>> monkey = cx.execute('var x = new Monkey(); x.baz = "schmammo"; x;') 157 | >>> monkey.baz 158 | u'schmammo' 159 | >>> monkey.__class__.__name__ 160 | 'Monkey' 161 | 162 | 163 | JavaScript Functions 164 | -------------------- 165 | 166 | >>> import spidermonkey 167 | >>> rt = spidermonkey.Runtime() 168 | >>> cx = rt.new_context() 169 | >>> func = cx.execute('function(val) {return "whoosh: " + val;}') 170 | >>> func("zipper!"); 171 | u'whoosh: zipper!' 172 | 173 | 174 | Filtering access to Python 175 | -------------------------- 176 | 177 | >>> import spidermonkey 178 | >>> rt = spidermonkey.Runtime() 179 | >>> def checker(obj, name): 180 | ... return not name.startswith("_") 181 | ... 182 | >>> cx = rt.new_context(access=checker) 183 | >>> # Alternatively: 184 | >>> cx.set_access() #doctest: +ELLIPSIS 185 | 186 | >>> cx.set_access(checker) #doctest: +ELLIPSIS 187 | 188 | >>> cx.add_global("fish", {"gold": "gone", "_old_lady": "huzza"}) 189 | >>> cx.execute('fish["_old_lady"];') 190 | Traceback (most recent call last): 191 | ... 192 | JSError: Error executing JavaScript. 193 | 194 | 195 | Previous Authors 196 | ================ 197 | 198 | * John J. Lee 199 | * Atul Varma 200 | 201 | [lh]: http://davisp.lighthouseapp.com/projects/26898-python-spidermonkey/overview 202 | [nspr]: ftp://ftp.mozilla.org/pub/mozilla.org/nspr/releases 203 | [xulrunner]: ftp://ftp.mozilla.org/pub/mozilla.org/xulrunner/releases 204 | -------------------------------------------------------------------------------- /spidermonkey/jsfunction.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 Paul J. Davis 3 | * 4 | * This file is part of the python-spidermonkey package released 5 | * under the MIT license. 6 | * 7 | */ 8 | 9 | #include "spidermonkey.h" 10 | 11 | PyObject* 12 | js2py_function(Context* cx, jsval val, jsval parent) 13 | { 14 | Function* ret = NULL; 15 | 16 | if(parent == JSVAL_VOID || !JSVAL_IS_OBJECT(parent)) 17 | { 18 | PyErr_BadInternalCall(); 19 | goto error; 20 | } 21 | 22 | ret = (Function*) make_object(FunctionType, cx, val); 23 | if(ret == NULL) goto error; 24 | 25 | ret->parent = parent; 26 | if(!JS_AddRoot(cx->cx, &(ret->parent))) 27 | { 28 | PyErr_SetString(PyExc_RuntimeError, "Failed to add GC root."); 29 | goto error; 30 | } 31 | 32 | goto success; 33 | 34 | error: 35 | Py_XDECREF((PyObject*)ret); 36 | ret = NULL; // In case of AddRoot error. 37 | success: 38 | return (PyObject*) ret; 39 | } 40 | 41 | void 42 | Function_dealloc(Function* self) 43 | { 44 | if(self->parent != JSVAL_VOID) 45 | { 46 | JS_BeginRequest(self->obj.cx->cx); 47 | JS_RemoveRoot(self->obj.cx->cx, &(self->parent)); 48 | JS_EndRequest(self->obj.cx->cx); 49 | } 50 | 51 | ObjectType->tp_dealloc((PyObject*) self); 52 | } 53 | 54 | PyObject* 55 | Function_call(Function* self, PyObject* args, PyObject* kwargs) 56 | { 57 | PyObject* item = NULL; 58 | PyObject* ret = NULL; 59 | Py_ssize_t argc; 60 | Py_ssize_t idx; 61 | JSContext* cx; 62 | JSObject* parent; 63 | jsval func; 64 | jsval* argv = NULL; 65 | jsval rval; 66 | JSBool started_counter = JS_FALSE; 67 | 68 | JS_BeginRequest(self->obj.cx->cx); 69 | 70 | argc = PySequence_Length(args); 71 | if(argc < 0) goto error; 72 | 73 | argv = malloc(sizeof(jsval) * argc); 74 | if(argv == NULL) 75 | { 76 | PyErr_NoMemory(); 77 | goto error; 78 | } 79 | 80 | for(idx = 0; idx < argc; idx++) 81 | { 82 | item = PySequence_GetItem(args, idx); 83 | if(item == NULL) goto error; 84 | 85 | argv[idx] = py2js(self->obj.cx, item); 86 | if(argv[idx] == JSVAL_VOID) goto error; 87 | Py_DECREF(item); 88 | item = NULL; // Prevent double decref. 89 | } 90 | 91 | func = self->obj.val; 92 | cx = self->obj.cx->cx; 93 | parent = JSVAL_TO_OBJECT(self->parent); 94 | 95 | // Mark us for execution time if not already marked 96 | if(self->obj.cx->start_time == 0) 97 | { 98 | started_counter = JS_TRUE; 99 | self->obj.cx->start_time = time(NULL); 100 | } 101 | 102 | if(!JS_CallFunctionValue(cx, parent, func, argc, argv, &rval)) 103 | { 104 | PyErr_SetString(PyExc_RuntimeError, "Failed to execute JS Function."); 105 | goto error; 106 | } 107 | 108 | ret = js2py(self->obj.cx, rval); 109 | JS_EndRequest(self->obj.cx->cx); 110 | JS_MaybeGC(cx); 111 | goto success; 112 | 113 | error: 114 | if(argv != NULL) free(argv); 115 | JS_EndRequest(self->obj.cx->cx); 116 | success: 117 | 118 | // Reset the time counter if we started it. 119 | if(started_counter) 120 | { 121 | self->obj.cx->start_time = 0; 122 | } 123 | 124 | Py_XDECREF(item); 125 | return ret; 126 | } 127 | 128 | static PyMemberDef Function_members[] = { 129 | {NULL} 130 | }; 131 | 132 | static PyMethodDef Function_methods[] = { 133 | {NULL} 134 | }; 135 | 136 | PyTypeObject _FunctionType = { 137 | PyObject_HEAD_INIT(NULL) 138 | 0, /*ob_size*/ 139 | "spidermonkey.Function", /*tp_name*/ 140 | sizeof(Function), /*tp_basicsize*/ 141 | 0, /*tp_itemsize*/ 142 | (destructor)Function_dealloc, /*tp_dealloc*/ 143 | 0, /*tp_print*/ 144 | 0, /*tp_getattr*/ 145 | 0, /*tp_setattr*/ 146 | 0, /*tp_compare*/ 147 | 0, /*tp_repr*/ 148 | 0, /*tp_as_number*/ 149 | 0, /*tp_as_sequence*/ 150 | 0, /*tp_as_mapping*/ 151 | 0, /*tp_hash*/ 152 | (ternaryfunc)Function_call, /*tp_call*/ 153 | 0, /*tp_str*/ 154 | 0, /*tp_getattro*/ 155 | 0, /*tp_setattro*/ 156 | 0, /*tp_as_buffer*/ 157 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ 158 | "JavaScript Function", /*tp_doc*/ 159 | 0, /*tp_traverse*/ 160 | 0, /*tp_clear*/ 161 | 0, /*tp_richcompare*/ 162 | 0, /*tp_weaklistoffset*/ 163 | 0, /*tp_iter*/ 164 | 0, /*tp_iternext*/ 165 | Function_methods, /*tp_methods*/ 166 | Function_members, /*tp_members*/ 167 | 0, /*tp_getset*/ 168 | 0, /*tp_base*/ 169 | 0, /*tp_dict*/ 170 | 0, /*tp_descr_get*/ 171 | 0, /*tp_descr_set*/ 172 | 0, /*tp_dictoffset*/ 173 | 0, /*tp_init*/ 174 | 0, /*tp_alloc*/ 175 | 0, /*tp_new*/ 176 | }; 177 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsdtoa.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef jsdtoa_h___ 41 | #define jsdtoa_h___ 42 | /* 43 | * Public interface to portable double-precision floating point to string 44 | * and back conversion package. 45 | */ 46 | 47 | #include "jscompat.h" 48 | 49 | JS_BEGIN_EXTERN_C 50 | 51 | /* 52 | * JS_strtod() returns as a double-precision floating-point number 53 | * the value represented by the character string pointed to by 54 | * s00. The string is scanned up to the first unrecognized 55 | * character. 56 | * If the value of se is not (char **)NULL, a pointer to 57 | * the character terminating the scan is returned in the location pointed 58 | * to by se. If no number can be formed, se is set to s00r, and 59 | * zero is returned. 60 | * 61 | * *err is set to zero on success; it's set to JS_DTOA_ERANGE on range 62 | * errors and JS_DTOA_ENOMEM on memory failure. 63 | */ 64 | #define JS_DTOA_ERANGE 1 65 | #define JS_DTOA_ENOMEM 2 66 | JS_FRIEND_API(double) 67 | JS_strtod(const char *s00, char **se, int *err); 68 | 69 | /* 70 | * Modes for converting floating-point numbers to strings. 71 | * 72 | * Some of the modes can round-trip; this means that if the number is converted to 73 | * a string using one of these mode and then converted back to a number, the result 74 | * will be identical to the original number (except that, due to ECMA, -0 will get converted 75 | * to +0). These round-trip modes return the minimum number of significand digits that 76 | * permit the round trip. 77 | * 78 | * Some of the modes take an integer parameter . 79 | */ 80 | /* NB: Keep this in sync with number_constants[]. */ 81 | typedef enum JSDToStrMode { 82 | DTOSTR_STANDARD, /* Either fixed or exponential format; round-trip */ 83 | DTOSTR_STANDARD_EXPONENTIAL, /* Always exponential format; round-trip */ 84 | DTOSTR_FIXED, /* Round to digits after the decimal point; exponential if number is large */ 85 | DTOSTR_EXPONENTIAL, /* Always exponential format; significant digits */ 86 | DTOSTR_PRECISION /* Either fixed or exponential format; significant digits */ 87 | } JSDToStrMode; 88 | 89 | 90 | /* Maximum number of characters (including trailing null) that a DTOSTR_STANDARD or DTOSTR_STANDARD_EXPONENTIAL 91 | * conversion can produce. This maximum is reached for a number like -0.0000012345678901234567. */ 92 | #define DTOSTR_STANDARD_BUFFER_SIZE 26 93 | 94 | /* Maximum number of characters (including trailing null) that one of the other conversions 95 | * can produce. This maximum is reached for TO_FIXED, which can generate up to 21 digits before the decimal point. */ 96 | #define DTOSTR_VARIABLE_BUFFER_SIZE(precision) ((precision)+24 > DTOSTR_STANDARD_BUFFER_SIZE ? (precision)+24 : DTOSTR_STANDARD_BUFFER_SIZE) 97 | 98 | /* 99 | * Convert dval according to the given mode and return a pointer to the resulting ASCII string. 100 | * The result is held somewhere in buffer, but not necessarily at the beginning. The size of 101 | * buffer is given in bufferSize, and must be at least as large as given by the above macros. 102 | * 103 | * Return NULL if out of memory. 104 | */ 105 | JS_FRIEND_API(char *) 106 | JS_dtostr(char *buffer, size_t bufferSize, JSDToStrMode mode, int precision, double dval); 107 | 108 | /* 109 | * Convert d to a string in the given base. The integral part of d will be printed exactly 110 | * in that base, regardless of how large it is, because there is no exponential notation for non-base-ten 111 | * numbers. The fractional part will be rounded to as few digits as possible while still preserving 112 | * the round-trip property (analogous to that of printing decimal numbers). In other words, if one were 113 | * to read the resulting string in via a hypothetical base-number-reading routine that rounds to the nearest 114 | * IEEE double (and to an even significand if there are two equally near doubles), then the result would 115 | * equal d (except for -0.0, which converts to "0", and NaN, which is not equal to itself). 116 | * 117 | * Return NULL if out of memory. If the result is not NULL, it must be released via free(). 118 | */ 119 | JS_FRIEND_API(char *) 120 | JS_dtobasestr(int base, double d); 121 | 122 | /* 123 | * Clean up any persistent RAM allocated during the execution of DtoA 124 | * routines, and remove any locks that might have been created. 125 | */ 126 | extern void js_FinishDtoa(void); 127 | 128 | JS_END_EXTERN_C 129 | 130 | #endif /* jsdtoa_h___ */ 131 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jshash.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef jshash_h___ 41 | #define jshash_h___ 42 | /* 43 | * API to portable hash table code. 44 | */ 45 | #include 46 | #include 47 | #include "jstypes.h" 48 | #include "jscompat.h" 49 | 50 | JS_BEGIN_EXTERN_C 51 | 52 | typedef uint32 JSHashNumber; 53 | typedef struct JSHashEntry JSHashEntry; 54 | typedef struct JSHashTable JSHashTable; 55 | 56 | #define JS_HASH_BITS 32 57 | #define JS_GOLDEN_RATIO 0x9E3779B9U 58 | 59 | typedef JSHashNumber (* JS_DLL_CALLBACK JSHashFunction)(const void *key); 60 | typedef intN (* JS_DLL_CALLBACK JSHashComparator)(const void *v1, const void *v2); 61 | typedef intN (* JS_DLL_CALLBACK JSHashEnumerator)(JSHashEntry *he, intN i, void *arg); 62 | 63 | /* Flag bits in JSHashEnumerator's return value */ 64 | #define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */ 65 | #define HT_ENUMERATE_STOP 1 /* stop enumerating entries */ 66 | #define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */ 67 | 68 | typedef struct JSHashAllocOps { 69 | void * (*allocTable)(void *pool, size_t size); 70 | void (*freeTable)(void *pool, void *item); 71 | JSHashEntry * (*allocEntry)(void *pool, const void *key); 72 | void (*freeEntry)(void *pool, JSHashEntry *he, uintN flag); 73 | } JSHashAllocOps; 74 | 75 | #define HT_FREE_VALUE 0 /* just free the entry's value */ 76 | #define HT_FREE_ENTRY 1 /* free value and entire entry */ 77 | 78 | struct JSHashEntry { 79 | JSHashEntry *next; /* hash chain linkage */ 80 | JSHashNumber keyHash; /* key hash function result */ 81 | const void *key; /* ptr to opaque key */ 82 | void *value; /* ptr to opaque value */ 83 | }; 84 | 85 | struct JSHashTable { 86 | JSHashEntry **buckets; /* vector of hash buckets */ 87 | uint32 nentries; /* number of entries in table */ 88 | uint32 shift; /* multiplicative hash shift */ 89 | JSHashFunction keyHash; /* key hash function */ 90 | JSHashComparator keyCompare; /* key comparison function */ 91 | JSHashComparator valueCompare; /* value comparison function */ 92 | JSHashAllocOps *allocOps; /* allocation operations */ 93 | void *allocPriv; /* allocation private data */ 94 | #ifdef HASHMETER 95 | uint32 nlookups; /* total number of lookups */ 96 | uint32 nsteps; /* number of hash chains traversed */ 97 | uint32 ngrows; /* number of table expansions */ 98 | uint32 nshrinks; /* number of table contractions */ 99 | #endif 100 | }; 101 | 102 | /* 103 | * Create a new hash table. 104 | * If allocOps is null, use default allocator ops built on top of malloc(). 105 | */ 106 | extern JS_PUBLIC_API(JSHashTable *) 107 | JS_NewHashTable(uint32 n, JSHashFunction keyHash, 108 | JSHashComparator keyCompare, JSHashComparator valueCompare, 109 | JSHashAllocOps *allocOps, void *allocPriv); 110 | 111 | extern JS_PUBLIC_API(void) 112 | JS_HashTableDestroy(JSHashTable *ht); 113 | 114 | /* Low level access methods */ 115 | extern JS_PUBLIC_API(JSHashEntry **) 116 | JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key); 117 | 118 | extern JS_PUBLIC_API(JSHashEntry *) 119 | JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **hep, JSHashNumber keyHash, 120 | const void *key, void *value); 121 | 122 | extern JS_PUBLIC_API(void) 123 | JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he); 124 | 125 | /* Higher level access methods */ 126 | extern JS_PUBLIC_API(JSHashEntry *) 127 | JS_HashTableAdd(JSHashTable *ht, const void *key, void *value); 128 | 129 | extern JS_PUBLIC_API(JSBool) 130 | JS_HashTableRemove(JSHashTable *ht, const void *key); 131 | 132 | extern JS_PUBLIC_API(intN) 133 | JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg); 134 | 135 | extern JS_PUBLIC_API(void *) 136 | JS_HashTableLookup(JSHashTable *ht, const void *key); 137 | 138 | extern JS_PUBLIC_API(intN) 139 | JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp); 140 | 141 | /* General-purpose C string hash function. */ 142 | extern JS_PUBLIC_API(JSHashNumber) 143 | JS_HashString(const void *key); 144 | 145 | /* Stub function just returns v1 == v2 */ 146 | extern JS_PUBLIC_API(intN) 147 | JS_CompareValues(const void *v1, const void *v2); 148 | 149 | JS_END_EXTERN_C 150 | 151 | #endif /* jshash_h___ */ 152 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsfun.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * 26 | * Alternatively, the contents of this file may be used under the terms of 27 | * either of the GNU General Public License Version 2 or later (the "GPL"), 28 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 29 | * in which case the provisions of the GPL or the LGPL are applicable instead 30 | * of those above. If you wish to allow use of your version of this file only 31 | * under the terms of either the GPL or the LGPL, and not to allow others to 32 | * use your version of this file under the terms of the MPL, indicate your 33 | * decision by deleting the provisions above and replace them with the notice 34 | * and other provisions required by the GPL or the LGPL. If you do not delete 35 | * the provisions above, a recipient may use your version of this file under 36 | * the terms of any one of the MPL, the GPL or the LGPL. 37 | * 38 | * ***** END LICENSE BLOCK ***** */ 39 | 40 | #ifndef jsfun_h___ 41 | #define jsfun_h___ 42 | /* 43 | * JS function definitions. 44 | */ 45 | #include "jsprvtd.h" 46 | #include "jspubtd.h" 47 | 48 | JS_BEGIN_EXTERN_C 49 | 50 | struct JSFunction { 51 | JSObject *object; /* back-pointer to GC'ed object header */ 52 | uint16 nargs; /* minimum number of actual arguments */ 53 | uint16 flags; /* bound method and other flags, see jsapi.h */ 54 | union { 55 | struct { 56 | uint16 extra; /* number of arg slots for local GC roots */ 57 | uint16 spare; /* reserved for future use */ 58 | JSNative native; /* native method pointer or null */ 59 | } n; 60 | struct { 61 | uint16 nvars; /* number of local variables */ 62 | uint16 nregexps; /* number of regular expressions literals */ 63 | JSScript *script; /* interpreted bytecode descriptor or null */ 64 | } i; 65 | } u; 66 | JSAtom *atom; /* name for diagnostics and decompiling */ 67 | JSClass *clasp; /* if non-null, constructor for this class */ 68 | }; 69 | 70 | #define JSFUN_INTERPRETED 0x8000 /* use u.i if set, u.n if unset */ 71 | 72 | #define FUN_INTERPRETED(fun) ((fun)->flags & JSFUN_INTERPRETED) 73 | #define FUN_NATIVE(fun) (FUN_INTERPRETED(fun) ? NULL : (fun)->u.n.native) 74 | #define FUN_SCRIPT(fun) (FUN_INTERPRETED(fun) ? (fun)->u.i.script : NULL) 75 | 76 | extern JSClass js_ArgumentsClass; 77 | extern JSClass js_CallClass; 78 | 79 | /* JS_FRIEND_DATA so that VALUE_IS_FUNCTION is callable from the shell. */ 80 | extern JS_FRIEND_DATA(JSClass) js_FunctionClass; 81 | 82 | /* 83 | * NB: jsapi.h and jsobj.h must be included before any call to this macro. 84 | */ 85 | #define VALUE_IS_FUNCTION(cx, v) \ 86 | (!JSVAL_IS_PRIMITIVE(v) && \ 87 | OBJ_GET_CLASS(cx, JSVAL_TO_OBJECT(v)) == &js_FunctionClass) 88 | 89 | extern JSBool 90 | js_fun_toString(JSContext *cx, JSObject *obj, uint32 indent, 91 | uintN argc, jsval *argv, jsval *rval); 92 | 93 | extern JSBool 94 | js_IsIdentifier(JSString *str); 95 | 96 | extern JSObject * 97 | js_InitFunctionClass(JSContext *cx, JSObject *obj); 98 | 99 | extern JSObject * 100 | js_InitArgumentsClass(JSContext *cx, JSObject *obj); 101 | 102 | extern JSObject * 103 | js_InitCallClass(JSContext *cx, JSObject *obj); 104 | 105 | extern JSFunction * 106 | js_NewFunction(JSContext *cx, JSObject *funobj, JSNative native, uintN nargs, 107 | uintN flags, JSObject *parent, JSAtom *atom); 108 | 109 | extern JSObject * 110 | js_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent); 111 | 112 | extern JSBool 113 | js_LinkFunctionObject(JSContext *cx, JSFunction *fun, JSObject *object); 114 | 115 | extern JSFunction * 116 | js_DefineFunction(JSContext *cx, JSObject *obj, JSAtom *atom, JSNative native, 117 | uintN nargs, uintN flags); 118 | 119 | /* 120 | * Flags for js_ValueToFunction and js_ReportIsNotFunction. We depend on the 121 | * fact that JSINVOKE_CONSTRUCT (aka JSFRAME_CONSTRUCTING) is 1, and test that 122 | * with #if/#error in jsfun.c. 123 | */ 124 | #define JSV2F_CONSTRUCT JSINVOKE_CONSTRUCT 125 | #define JSV2F_ITERATOR JSINVOKE_ITERATOR 126 | #define JSV2F_SEARCH_STACK 0x10000 127 | 128 | extern JSFunction * 129 | js_ValueToFunction(JSContext *cx, jsval *vp, uintN flags); 130 | 131 | extern JSObject * 132 | js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags); 133 | 134 | extern JSObject * 135 | js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags); 136 | 137 | extern void 138 | js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags); 139 | 140 | extern JSObject * 141 | js_GetCallObject(JSContext *cx, JSStackFrame *fp, JSObject *parent); 142 | 143 | extern JSBool 144 | js_PutCallObject(JSContext *cx, JSStackFrame *fp); 145 | 146 | extern JSBool 147 | js_GetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp); 148 | 149 | extern JSBool 150 | js_SetCallVariable(JSContext *cx, JSObject *obj, jsval id, jsval *vp); 151 | 152 | extern JSBool 153 | js_GetArgsValue(JSContext *cx, JSStackFrame *fp, jsval *vp); 154 | 155 | extern JSBool 156 | js_GetArgsProperty(JSContext *cx, JSStackFrame *fp, jsid id, 157 | JSObject **objp, jsval *vp); 158 | 159 | extern JSObject * 160 | js_GetArgsObject(JSContext *cx, JSStackFrame *fp); 161 | 162 | extern JSBool 163 | js_PutArgsObject(JSContext *cx, JSStackFrame *fp); 164 | 165 | extern JSBool 166 | js_XDRFunction(JSXDRState *xdr, JSObject **objp); 167 | 168 | JS_END_EXTERN_C 169 | 170 | #endif /* jsfun_h___ */ 171 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2009 Paul J. Davis 3 | # 4 | # This file is part of the python-spidermonkey package released 5 | # under the MIT license. 6 | # 7 | 8 | """\ 9 | Python/JavaScript bridge module, making use of Mozilla's spidermonkey 10 | JavaScript implementation. Allows implementation of JavaScript classes, 11 | objects and functions in Python, and evaluation and calling of JavaScript 12 | scripts and functions respectively. Borrows heavily from Claes Jacobssen's 13 | Javascript Perl module, in turn based on Mozilla's 'PerlConnect' Perl binding. 14 | """, 15 | 16 | # I haven't the sligthest, but this appears to fix 17 | # all those EINTR errors. Pulled and adapted for OS X 18 | # from twisted bug #733 19 | # 20 | # Definitely forgot to comment this out before distribution. 21 | # 22 | # import ctypes 23 | # import signal 24 | # libc = ctypes.CDLL("libc.dylib") 25 | # libc.siginterrupt(signal.SIGCHLD, 0) 26 | 27 | import glob 28 | import os 29 | import subprocess as sp 30 | import sys 31 | from distutils.dist import Distribution 32 | import ez_setup 33 | ez_setup.use_setuptools() 34 | from setuptools import setup, Extension 35 | 36 | DEBUG = "--debug" in sys.argv 37 | USE_SYSTEM_LIB = "--system-library" in sys.argv 38 | 39 | def find_sources(extensions=(".c", ".cpp")): 40 | if USE_SYSTEM_LIB: 41 | return [ 42 | fname 43 | for ext in extensions 44 | for fname in glob.glob("spidermonkey/*" + ext) 45 | ] 46 | else: 47 | return [ 48 | os.path.join(dpath, fname) 49 | for (dpath, dnames, fnames) in os.walk("./spidermonkey") 50 | for fname in fnames 51 | if fname.endswith(extensions) 52 | ] 53 | 54 | def pkg_config(pkg_name, config=None): 55 | pipe = sp.Popen("pkg-config --cflags --libs %s" % pkg_name, 56 | shell=True, stdout=sp.PIPE, stderr=sp.PIPE) 57 | (stdout, stderr) = pipe.communicate() 58 | if pipe.wait() != 0: 59 | raise RuntimeError("No package configuration found for: %s" % pkg_name) 60 | if config is None: 61 | config = { 62 | "include_dirs": [], 63 | "library_dirs": [], 64 | "libraries": [], 65 | "extra_compile_args": [], 66 | "extra_link_args": [] 67 | } 68 | prefixes = { 69 | "-I": ("include_dirs", 2), 70 | "-L": ("library_dirs", 2), 71 | "-l": ("libraries", 2), 72 | "-D": ("extra_compile_args", 0), 73 | "-Wl": ("extra_link_args", 0) 74 | } 75 | for flag in stdout.split(): 76 | for prefix in prefixes: 77 | if not flag.startswith(prefix): 78 | continue 79 | # Hack for xulrunner 80 | if flag.endswith("/stable"): 81 | flag = flag[:-6] + "unstable" 82 | name, trim = prefixes[prefix] 83 | config[name].append(flag[trim:]) 84 | return config 85 | 86 | def nspr_config(config=None): 87 | return pkg_config("nspr", config) 88 | 89 | def js_config(config=None): 90 | config = pkg_config("mozilla-js", config) 91 | if "-DJS_THREADSAFE" not in config["extra_compile_args"]: 92 | raise SystemError("Unable to link against a library that was " 93 | "compiled without -DJS_THREADSAFE"); 94 | return config 95 | 96 | def platform_config(): 97 | sysname = os.uname()[0] 98 | machine = os.uname()[-1] 99 | 100 | # If we're linking against a system library it should give 101 | # us all the information we need. 102 | if USE_SYSTEM_LIB: 103 | return js_config() 104 | 105 | # Build our configuration 106 | config = { 107 | "extra_compile_args": [ 108 | "-DJS_THREADSAFE", 109 | "-DPOSIX_SOURCE", 110 | "-D_BSD_SOURCE", 111 | "-Wno-strict-prototypes" # Disable copius JS warnings 112 | ], 113 | "include_dirs": [ 114 | "spidermonkey/libjs", 115 | "spidermonkey/%s-%s" % (sysname, machine) 116 | ], 117 | "library_dirs": [], 118 | "libraries": [], 119 | "extra_link_args": [] 120 | } 121 | 122 | # Debug builds are useful for finding errors in 123 | # the request counting semantics for Spidermonkey 124 | if DEBUG: 125 | config["extra_compile_args"].extend([ 126 | "-UNDEBG", 127 | "-DDEBUG", 128 | "-DJS_PARANOID_REQUEST" 129 | ]) 130 | 131 | if sysname in ["Linux", "FreeBSD"]: 132 | config["extra_compile_args"].extend([ 133 | "-DHAVE_VA_COPY", 134 | "-DVA_COPY=va_copy" 135 | ]) 136 | 137 | # Currently no suppot for Win32, patches welcome. 138 | if sysname in ["Darwin", "Linux", "FreeBSD"]: 139 | config["extra_compile_args"].append("-DXP_UNIX") 140 | else: 141 | raise RuntimeError("Unknown system name: %s" % sysname) 142 | 143 | return nspr_config(config=config) 144 | 145 | Distribution.global_options.append(("debug", None, 146 | "Build a DEBUG version of spidermonkey.")) 147 | Distribution.global_options.append(("system-library", None, 148 | "Link against an installed system library.")) 149 | 150 | setup( 151 | name = "python-spidermonkey", 152 | version = "0.0.7", 153 | license = "MIT", 154 | author = "Paul J. Davis", 155 | author_email = "paul.joseph.davis@gmail.com", 156 | description = "JavaScript / Python bridge.", 157 | long_description = __doc__, 158 | url = "http://github.com/davisp/python-spidermonkey", 159 | download_url = "http://github.com/davisp/python-spidermonkey.git", 160 | zip_safe = False, 161 | 162 | classifiers = [ 163 | 'Development Status :: 3 - Alpha', 164 | 'Intended Audience :: Developers', 165 | 'License :: OSI Approved :: MIT License', 166 | 'Natural Language :: English', 167 | 'Operating System :: OS Independent', 168 | 'Programming Language :: C', 169 | 'Programming Language :: JavaScript', 170 | 'Programming Language :: Other', 171 | 'Programming Language :: Python', 172 | 'Topic :: Internet :: WWW/HTTP :: Browsers', 173 | 'Topic :: Internet :: WWW/HTTP :: Dynamic Content', 174 | 'Topic :: Software Development :: Libraries :: Python Modules', 175 | ], 176 | 177 | setup_requires = [ 178 | 'setuptools>=0.6c8', 179 | 'nose>=0.10.0', 180 | ], 181 | 182 | ext_modules = [ 183 | Extension( 184 | "spidermonkey", 185 | sources=find_sources(), 186 | **platform_config() 187 | ) 188 | ], 189 | 190 | test_suite = 'nose.collector', 191 | 192 | ) 193 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsprf.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 | /* ***** BEGIN LICENSE BLOCK ***** 3 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 4 | * 5 | * The contents of this file are subject to the Mozilla Public License Version 6 | * 1.1 (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * http://www.mozilla.org/MPL/ 9 | * 10 | * Software distributed under the License is distributed on an "AS IS" basis, 11 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing rights and limitations under the 13 | * License. 14 | * 15 | * The Original Code is Mozilla Communicator client code, released 16 | * March 31, 1998. 17 | * 18 | * The Initial Developer of the Original Code is 19 | * Netscape Communications Corporation. 20 | * Portions created by the Initial Developer are Copyright (C) 1998 21 | * the Initial Developer. All Rights Reserved. 22 | * 23 | * Contributor(s): 24 | * 25 | * Alternatively, the contents of this file may be used under the terms of 26 | * either of the GNU General Public License Version 2 or later (the "GPL"), 27 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 28 | * in which case the provisions of the GPL or the LGPL are applicable instead 29 | * of those above. If you wish to allow use of your version of this file only 30 | * under the terms of either the GPL or the LGPL, and not to allow others to 31 | * use your version of this file under the terms of the MPL, indicate your 32 | * decision by deleting the provisions above and replace them with the notice 33 | * and other provisions required by the GPL or the LGPL. If you do not delete 34 | * the provisions above, a recipient may use your version of this file under 35 | * the terms of any one of the MPL, the GPL or the LGPL. 36 | * 37 | * ***** END LICENSE BLOCK ***** */ 38 | 39 | #ifndef jsprf_h___ 40 | #define jsprf_h___ 41 | 42 | /* 43 | ** API for PR printf like routines. Supports the following formats 44 | ** %d - decimal 45 | ** %u - unsigned decimal 46 | ** %x - unsigned hex 47 | ** %X - unsigned uppercase hex 48 | ** %o - unsigned octal 49 | ** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above 50 | ** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above 51 | ** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above 52 | ** %s - string 53 | ** %hs - 16-bit version of above (only available if compiled with JS_C_STRINGS_ARE_UTF8) 54 | ** %c - character 55 | ** %hc - 16-bit version of above (only available if compiled with JS_C_STRINGS_ARE_UTF8) 56 | ** %p - pointer (deals with machine dependent pointer size) 57 | ** %f - float 58 | ** %g - float 59 | */ 60 | #include "jstypes.h" 61 | #include 62 | #include 63 | 64 | JS_BEGIN_EXTERN_C 65 | 66 | /* 67 | ** sprintf into a fixed size buffer. Guarantees that a NUL is at the end 68 | ** of the buffer. Returns the length of the written output, NOT including 69 | ** the NUL, or (JSUint32)-1 if an error occurs. 70 | */ 71 | extern JS_PUBLIC_API(JSUint32) JS_snprintf(char *out, JSUint32 outlen, const char *fmt, ...); 72 | 73 | /* 74 | ** sprintf into a malloc'd buffer. Return a pointer to the malloc'd 75 | ** buffer on success, NULL on failure. Call "JS_smprintf_free" to release 76 | ** the memory returned. 77 | */ 78 | extern JS_PUBLIC_API(char*) JS_smprintf(const char *fmt, ...); 79 | 80 | /* 81 | ** Free the memory allocated, for the caller, by JS_smprintf 82 | */ 83 | extern JS_PUBLIC_API(void) JS_smprintf_free(char *mem); 84 | 85 | /* 86 | ** "append" sprintf into a malloc'd buffer. "last" is the last value of 87 | ** the malloc'd buffer. sprintf will append data to the end of last, 88 | ** growing it as necessary using realloc. If last is NULL, JS_sprintf_append 89 | ** will allocate the initial string. The return value is the new value of 90 | ** last for subsequent calls, or NULL if there is a malloc failure. 91 | */ 92 | extern JS_PUBLIC_API(char*) JS_sprintf_append(char *last, const char *fmt, ...); 93 | 94 | /* 95 | ** sprintf into a function. The function "f" is called with a string to 96 | ** place into the output. "arg" is an opaque pointer used by the stuff 97 | ** function to hold any state needed to do the storage of the output 98 | ** data. The return value is a count of the number of characters fed to 99 | ** the stuff function, or (JSUint32)-1 if an error occurs. 100 | */ 101 | typedef JSIntn (*JSStuffFunc)(void *arg, const char *s, JSUint32 slen); 102 | 103 | extern JS_PUBLIC_API(JSUint32) JS_sxprintf(JSStuffFunc f, void *arg, const char *fmt, ...); 104 | 105 | /* 106 | ** va_list forms of the above. 107 | */ 108 | extern JS_PUBLIC_API(JSUint32) JS_vsnprintf(char *out, JSUint32 outlen, const char *fmt, va_list ap); 109 | extern JS_PUBLIC_API(char*) JS_vsmprintf(const char *fmt, va_list ap); 110 | extern JS_PUBLIC_API(char*) JS_vsprintf_append(char *last, const char *fmt, va_list ap); 111 | extern JS_PUBLIC_API(JSUint32) JS_vsxprintf(JSStuffFunc f, void *arg, const char *fmt, va_list ap); 112 | 113 | /* 114 | *************************************************************************** 115 | ** FUNCTION: JS_sscanf 116 | ** DESCRIPTION: 117 | ** JS_sscanf() scans the input character string, performs data 118 | ** conversions, and stores the converted values in the data objects 119 | ** pointed to by its arguments according to the format control 120 | ** string. 121 | ** 122 | ** JS_sscanf() behaves the same way as the sscanf() function in the 123 | ** Standard C Library (stdio.h), with the following exceptions: 124 | ** - JS_sscanf() handles the NSPR integer and floating point types, 125 | ** such as JSInt16, JSInt32, JSInt64, and JSFloat64, whereas 126 | ** sscanf() handles the standard C types like short, int, long, 127 | ** and double. 128 | ** - JS_sscanf() has no multibyte character support, while sscanf() 129 | ** does. 130 | ** INPUTS: 131 | ** const char *buf 132 | ** a character string holding the input to scan 133 | ** const char *fmt 134 | ** the format control string for the conversions 135 | ** ... 136 | ** variable number of arguments, each of them is a pointer to 137 | ** a data object in which the converted value will be stored 138 | ** OUTPUTS: none 139 | ** RETURNS: JSInt32 140 | ** The number of values converted and stored. 141 | ** RESTRICTIONS: 142 | ** Multibyte characters in 'buf' or 'fmt' are not allowed. 143 | *************************************************************************** 144 | */ 145 | 146 | extern JS_PUBLIC_API(JSInt32) JS_sscanf(const char *buf, const char *fmt, ...); 147 | 148 | JS_END_EXTERN_C 149 | 150 | #endif /* jsprf_h___ */ 151 | -------------------------------------------------------------------------------- /spidermonkey/libjs/jsutil.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 | * 3 | * ***** BEGIN LICENSE BLOCK ***** 4 | * Version: MPL 1.1/GPL 2.0/LGPL 2.1 5 | * 6 | * The contents of this file are subject to the Mozilla Public License Version 7 | * 1.1 (the "License"); you may not use this file except in compliance with 8 | * the License. You may obtain a copy of the License at 9 | * http://www.mozilla.org/MPL/ 10 | * 11 | * Software distributed under the License is distributed on an "AS IS" basis, 12 | * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 13 | * for the specific language governing rights and limitations under the 14 | * License. 15 | * 16 | * The Original Code is Mozilla Communicator client code, released 17 | * March 31, 1998. 18 | * 19 | * The Initial Developer of the Original Code is 20 | * Netscape Communications Corporation. 21 | * Portions created by the Initial Developer are Copyright (C) 1998 22 | * the Initial Developer. All Rights Reserved. 23 | * 24 | * Contributor(s): 25 | * IBM Corp. 26 | * 27 | * Alternatively, the contents of this file may be used under the terms of 28 | * either of the GNU General Public License Version 2 or later (the "GPL"), 29 | * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), 30 | * in which case the provisions of the GPL or the LGPL are applicable instead 31 | * of those above. If you wish to allow use of your version of this file only 32 | * under the terms of either the GPL or the LGPL, and not to allow others to 33 | * use your version of this file under the terms of the MPL, indicate your 34 | * decision by deleting the provisions above and replace them with the notice 35 | * and other provisions required by the GPL or the LGPL. If you do not delete 36 | * the provisions above, a recipient may use your version of this file under 37 | * the terms of any one of the MPL, the GPL or the LGPL. 38 | * 39 | * ***** END LICENSE BLOCK ***** */ 40 | 41 | /* 42 | * PR assertion checker. 43 | */ 44 | #include "jsstddef.h" 45 | #include 46 | #include 47 | #include "jstypes.h" 48 | #include "jsutil.h" 49 | 50 | #ifdef WIN32 51 | # include 52 | #endif 53 | 54 | JS_PUBLIC_API(void) JS_Assert(const char *s, const char *file, JSIntn ln) 55 | { 56 | fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln); 57 | #if defined(WIN32) 58 | DebugBreak(); 59 | exit(3); 60 | #elif defined(XP_OS2) || (defined(__GNUC__) && defined(__i386)) 61 | asm("int $3"); 62 | #endif 63 | abort(); 64 | } 65 | 66 | #if defined DEBUG_notme && defined XP_UNIX 67 | 68 | #define __USE_GNU 1 69 | #include 70 | #include 71 | #include "jshash.h" 72 | #include "jsprf.h" 73 | 74 | JSCallsite js_calltree_root = {0, NULL, NULL, 0, NULL, NULL, NULL, NULL}; 75 | 76 | static JSCallsite * 77 | CallTree(void **bp) 78 | { 79 | void **bpup, **bpdown, *pc; 80 | JSCallsite *parent, *site, **csp; 81 | Dl_info info; 82 | int ok, offset; 83 | const char *symbol; 84 | char *method; 85 | 86 | /* Reverse the stack frame list to avoid recursion. */ 87 | bpup = NULL; 88 | for (;;) { 89 | bpdown = (void**) bp[0]; 90 | bp[0] = (void*) bpup; 91 | if ((void**) bpdown[0] < bpdown) 92 | break; 93 | bpup = bp; 94 | bp = bpdown; 95 | } 96 | 97 | /* Reverse the stack again, finding and building a path in the tree. */ 98 | parent = &js_calltree_root; 99 | do { 100 | bpup = (void**) bp[0]; 101 | bp[0] = (void*) bpdown; 102 | pc = bp[1]; 103 | 104 | csp = &parent->kids; 105 | while ((site = *csp) != NULL) { 106 | if (site->pc == pc) { 107 | /* Put the most recently used site at the front of siblings. */ 108 | *csp = site->siblings; 109 | site->siblings = parent->kids; 110 | parent->kids = site; 111 | 112 | /* Site already built -- go up the stack. */ 113 | goto upward; 114 | } 115 | csp = &site->siblings; 116 | } 117 | 118 | /* Check for recursion: see if pc is on our ancestor line. */ 119 | for (site = parent; site; site = site->parent) { 120 | if (site->pc == pc) 121 | goto upward; 122 | } 123 | 124 | /* 125 | * Not in tree at all: let's find our symbolic callsite info. 126 | * XXX static syms are masked by nearest lower global 127 | */ 128 | info.dli_fname = info.dli_sname = NULL; 129 | ok = dladdr(pc, &info); 130 | if (ok < 0) { 131 | fprintf(stderr, "dladdr failed!\n"); 132 | return NULL; 133 | } 134 | 135 | /* XXXbe sub 0x08040000? or something, see dbaron bug with tenthumbs comment */ 136 | symbol = info.dli_sname; 137 | offset = (char*)pc - (char*)info.dli_fbase; 138 | method = symbol 139 | ? strdup(symbol) 140 | : JS_smprintf("%s+%X", 141 | info.dli_fname ? info.dli_fname : "main", 142 | offset); 143 | if (!method) 144 | return NULL; 145 | 146 | /* Create a new callsite record. */ 147 | site = (JSCallsite *) malloc(sizeof(JSCallsite)); 148 | if (!site) 149 | return NULL; 150 | 151 | /* Insert the new site into the tree. */ 152 | site->pc = pc; 153 | site->name = method; 154 | site->library = info.dli_fname; 155 | site->offset = offset; 156 | site->parent = parent; 157 | site->siblings = parent->kids; 158 | parent->kids = site; 159 | site->kids = NULL; 160 | 161 | upward: 162 | parent = site; 163 | bpdown = bp; 164 | bp = bpup; 165 | } while (bp); 166 | 167 | return site; 168 | } 169 | 170 | JSCallsite * 171 | JS_Backtrace(int skip) 172 | { 173 | void **bp, **bpdown; 174 | 175 | /* Stack walking code adapted from Kipp's "leaky". */ 176 | #if defined(__i386) 177 | __asm__( "movl %%ebp, %0" : "=g"(bp)); 178 | #elif defined(__x86_64__) 179 | __asm__( "movq %%rbp, %0" : "=g"(bp)); 180 | #else 181 | /* 182 | * It would be nice if this worked uniformly, but at least on i386 and 183 | * x86_64, it stopped working with gcc 4.1, because it points to the 184 | * end of the saved registers instead of the start. 185 | */ 186 | bp = (void**) __builtin_frame_address(0); 187 | #endif 188 | while (--skip >= 0) { 189 | bpdown = (void**) *bp++; 190 | if (bpdown < bp) 191 | break; 192 | bp = bpdown; 193 | } 194 | 195 | return CallTree(bp); 196 | } 197 | 198 | #endif /* DEBUG_notme && XP_UNIX */ 199 | --------------------------------------------------------------------------------