diff --git a/spidermonkey/context.c b/spidermonkey/context.c index 81c4a5f..7b989b5 100644 --- a/spidermonkey/context.c +++ b/spidermonkey/context.c @@ -200,7 +200,7 @@ resolve(JSContext* jscx, JSObject* jsobj, jsval key) goto done; } - if(!js_DefineProperty(jscx, pycx->root, pid, JSVAL_VOID, NULL, NULL, + if(!js_DefineProperty(jscx, pycx->root0, pid, JSVAL_VOID, NULL, NULL, JSPROP_SHARED, NULL)) { JS_ReportError(jscx, "Failed to define property."); @@ -354,6 +354,7 @@ Context_new(PyTypeObject* type, PyObject* args, PyObject* kwargs) PyErr_SetString(PyExc_RuntimeError, "Error creating root object."); goto error; } + self->root0 = self->root; if(!JS_InitStandardClasses(self->cx, self->root)) { @@ -440,7 +441,7 @@ Context_add_global(Context* self, PyObject* args, PyObject* kwargs) jsv = py2js(self, pyval); if(jsv == JSVAL_VOID) goto error; - if(!js_SetProperty(self->cx, self->root, kid, &jsv)) + if(!js_SetProperty(self->cx, self->root0, kid, &jsv)) { PyErr_SetString(PyExc_AttributeError, "Failed to set global property."); goto error; @@ -475,7 +476,7 @@ Context_rem_global(Context* self, PyObject* args, PyObject* kwargs) PyErr_SetString(JSError, "Failed to create key id."); } - if(!js_GetProperty(self->cx, self->root, kid, &jsv)) + if(!js_GetProperty(self->cx, self->root0, kid, &jsv)) { PyErr_SetString(JSError, "Failed to get global property."); goto error; @@ -484,7 +485,7 @@ Context_rem_global(Context* self, PyObject* args, PyObject* kwargs) ret = js2py(self, jsv); if(ret == NULL) goto error; - if(!js_DeleteProperty(self->cx, self->root, kid, &jsv)) + if(!js_DeleteProperty(self->cx, self->root0, kid, &jsv)) { PyErr_SetString(JSError, "Failed to remove global property."); goto error; @@ -598,6 +599,60 @@ success: } PyObject* +Context_enter_scope(Context* self, PyObject* args, PyObject* kwargs) +{ + PyObject* ret = NULL; + JSObject* root = NULL; + + JS_BeginRequest(self->cx); + + root = JS_NewObject(self->cx, NULL, NULL, self->root); + if(root == NULL) + { + PyErr_SetString(PyExc_RuntimeError, "Error creating root object while entering scope."); + goto error; + } + self->root = root; + + JS_EndRequest(self->cx); + ret = Py_None; + Py_INCREF(ret); + goto success; + +error: + JS_EndRequest(self->cx); +success: + return ret; +} + +PyObject* +Context_leave_scope(Context* self, PyObject* args, PyObject* kwargs) +{ + PyObject* ret = NULL; + JSObject* root = NULL; + + JS_BeginRequest(self->cx); + + root = JS_GetParent(self->cx, self->root); + if(root == NULL) + { + PyErr_SetString(PyExc_RuntimeError, "Cannot leave scope if it was not entered."); + goto error; + } + self->root = root; + + JS_EndRequest(self->cx); + ret = Py_None; + Py_INCREF(ret); + goto success; + +error: + JS_EndRequest(self->cx); +success: + return ret; +} + +PyObject* Context_gc(Context* self, PyObject* args, PyObject* kwargs) { JS_GC(self->cx); @@ -687,6 +742,18 @@ static PyMethodDef Context_methods[] = { METH_VARARGS, "Get/Set the maximum time a context can execute for." }, + { + "enter_scope", + (PyCFunction)Context_enter_scope, + METH_VARARGS, + "Enter a new scope onto the scope stack." + }, + { + "leave_scope", + (PyCFunction)Context_leave_scope, + METH_VARARGS, + "Leave the current scope by removing it from the scope stack." + }, {NULL} }; diff --git a/spidermonkey/context.h b/spidermonkey/context.h index b8b0921..9c8f602 100644 --- a/spidermonkey/context.h +++ b/spidermonkey/context.h @@ -27,6 +27,7 @@ typedef struct { long max_heap; time_t max_time; time_t start_time; + JSObject* root0; } Context; PyObject* Context_get_class(Context* cx, const char* key);