changeset 136:b4e216d06e83

Added pymonkey.Script, which wraps a JSScript object, and context.compile_script()/execute_script().
author Atul Varma <varmaa@toolness.com>
date Sun, 23 Aug 2009 21:49:44 -0700
parents 9157e7c9cb81
children f83a1603c417
files setup.py src/context.cpp src/object.cpp src/pymonkey.cpp src/script.cpp src/script.h tests/test_pymonkey.py
diffstat 7 files changed, 261 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/setup.py	Sun Aug 23 21:04:51 2009 -0700
+++ b/setup.py	Sun Aug 23 21:49:44 2009 -0700
@@ -41,6 +41,7 @@
                 'utils.cpp',
                 'object.cpp',
                 'function.cpp',
+                'script.cpp',
                 'undefined.cpp',
                 'context.cpp',
                 'runtime.cpp']
--- a/src/context.cpp	Sun Aug 23 21:04:51 2009 -0700
+++ b/src/context.cpp	Sun Aug 23 21:49:44 2009 -0700
@@ -37,6 +37,7 @@
 #include "context.h"
 #include "object.h"
 #include "function.h"
+#include "script.h"
 #include "utils.h"
 
 // This is the default JSOperationCallback for pymonkey-owned JS contexts,
@@ -311,6 +312,65 @@
 }
 
 static PyObject *
+PYM_compileScript(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PYM_JSObject *object;
+  char *source = NULL;
+  int sourceLen;
+  const char *filename;
+  int lineNo;
+
+  if (!PyArg_ParseTuple(args, "O!es#si", &PYM_JSObjectType, &object,
+                        "utf-16", &source, &sourceLen, &filename, &lineNo))
+    return NULL;
+
+  PYM_UTF16String str(source, sourceLen);
+
+  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
+
+  JSScript *script;
+  script = JS_CompileUCScript(self->cx, object->obj, str.jsbuffer,
+                              str.jslen, filename, lineNo);
+
+  if (script == NULL) {
+    PYM_jsExceptionToPython(self);
+    return NULL;
+  }
+
+  return (PyObject *) PYM_newJSScript(self, script);
+}
+
+static PyObject *
+PYM_executeScript(PYM_JSContextObject *self, PyObject *args)
+{
+  PYM_SANITY_CHECK(self->runtime);
+  PYM_JSObject *object;
+  PYM_JSScript *script;
+
+  if (!PyArg_ParseTuple(args, "O!O!", &PYM_JSObjectType, &object,
+                        &PYM_JSScriptType, &script))
+    return NULL;
+
+  PYM_ENSURE_RUNTIME_MATCH(self->runtime, object->runtime);
+  PYM_ENSURE_RUNTIME_MATCH(self->runtime, script->base.runtime);
+
+  jsval rval;
+  JSBool result;
+  Py_BEGIN_ALLOW_THREADS;
+  result = JS_ExecuteScript(self->cx, object->obj, script->script, &rval);
+  Py_END_ALLOW_THREADS;
+
+  if (!result) {
+    PYM_jsExceptionToPython(self);
+    return NULL;
+  }
+
+  PyObject *pyRval = PYM_jsvalToPyObject(self, rval);
+  return pyRval;
+}
+
+static PyObject *
 PYM_evaluateScript(PYM_JSContextObject *self, PyObject *args)
 {
   PYM_SANITY_CHECK(self->runtime);
@@ -485,6 +545,14 @@
   {"init_standard_classes",
    (PyCFunction) PYM_initStandardClasses, METH_VARARGS,
    "Add standard classes and functions to the given object."},
+  {"compile_script",
+   (PyCFunction) PYM_compileScript, METH_VARARGS,
+   "Compile the given JavaScript code using the given filename"
+   "and line number information."},
+  {"execute_script",
+   (PyCFunction) PYM_executeScript, METH_VARARGS,
+   "Execute the given JavaScript script object in the context of "
+   "the given global object."},
   {"evaluate_script",
    (PyCFunction) PYM_evaluateScript, METH_VARARGS,
    "Evaluate the given JavaScript code in the context of the given "
--- a/src/object.cpp	Sun Aug 23 21:04:51 2009 -0700
+++ b/src/object.cpp	Sun Aug 23 21:49:44 2009 -0700
@@ -245,6 +245,5 @@
 
   JS_AddNamedRootRT(object->runtime->rt, &object->obj,
                     "Pymonkey-Generated Object");
-
   return object;
 }
--- a/src/pymonkey.cpp	Sun Aug 23 21:04:51 2009 -0700
+++ b/src/pymonkey.cpp	Sun Aug 23 21:49:44 2009 -0700
@@ -39,6 +39,7 @@
 #include "context.h"
 #include "object.h"
 #include "function.h"
+#include "script.h"
 #include "utils.h"
 
 static PyMethodDef PYM_methods[] = {
@@ -91,4 +92,11 @@
 
   Py_INCREF(&PYM_JSFunctionType);
   PyModule_AddObject(module, "Function", (PyObject *) &PYM_JSFunctionType);
+
+  PYM_JSScriptType.tp_base = &PYM_JSObjectType;
+  if (!PyType_Ready(&PYM_JSScriptType) < 0)
+    return;
+
+  Py_INCREF(&PYM_JSScriptType);
+  PyModule_AddObject(module, "Script", (PyObject *) &PYM_JSScriptType);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/script.cpp	Sun Aug 23 21:49:44 2009 -0700
@@ -0,0 +1,119 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Pymonkey.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Atul Varma <atul@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "script.h"
+#include "utils.h"
+
+static void
+PYM_JSScriptDealloc(PYM_JSScript *self)
+{
+  self->script = NULL;
+  PYM_JSObjectType.tp_dealloc((PyObject *) self);
+}
+
+PyTypeObject PYM_JSScriptType = {
+  PyObject_HEAD_INIT(NULL)
+  0,                           /*ob_size*/
+  "pymonkey.Script",           /*tp_name*/
+  sizeof(PYM_JSScript),        /*tp_basicsize*/
+  0,                           /*tp_itemsize*/
+                               /*tp_dealloc*/
+  (destructor) PYM_JSScriptDealloc,
+  0,                           /*tp_print*/
+  0,                           /*tp_getattr*/
+  0,                           /*tp_setattr*/
+  0,                           /*tp_compare*/
+  0,                           /*tp_repr*/
+  0,                           /*tp_as_number*/
+  0,                           /*tp_as_sequence*/
+  0,                           /*tp_as_mapping*/
+  0,                           /*tp_hash */
+  0,                           /*tp_call*/
+  0,                           /*tp_str*/
+  0,                           /*tp_getattro*/
+  0,                           /*tp_setattro*/
+  0,                           /*tp_as_buffer*/
+                               /*tp_flags*/
+  Py_TPFLAGS_DEFAULT,
+                               /* tp_doc */
+  "JavaScript Script.",
+  0,                           /* tp_traverse */
+  0,                           /* tp_clear */
+  0,                           /* tp_richcompare */
+  0,                           /* tp_weaklistoffset */
+  0,                           /* tp_iter */
+  0,                           /* tp_iternext */
+  0,                           /* tp_methods */
+  0,                           /* tp_members */
+  0,                           /* tp_getset */
+  0,                           /* tp_base */
+  0,                           /* tp_dict */
+  0,                           /* tp_descr_get */
+  0,                           /* tp_descr_set */
+  0,                           /* tp_dictoffset */
+  0,                           /* tp_init */
+  0,                           /* tp_alloc */
+  0,                           /* tp_new */
+};
+
+PYM_JSScript *
+PYM_newJSScript(PYM_JSContextObject *context, JSScript *script)
+{
+  JSObject *scriptObj = JS_GetScriptObject(script);
+  PYM_JSScript *object = NULL;
+
+  if (scriptObj)
+    object = (PYM_JSScript *) PYM_findJSObject(context, scriptObj);
+  else {
+    scriptObj = JS_NewScriptObject(context->cx, script);
+
+    if (scriptObj == NULL) {
+      PyErr_SetString(PYM_error, "JS_NewScriptObject() failed");
+      return NULL;
+    }
+  }
+
+  if (object == NULL) {
+    object = PyObject_New(PYM_JSScript, &PYM_JSScriptType);
+    if (object == NULL)
+      return NULL;
+
+    object->script = script;
+    return (PYM_JSScript *) PYM_newJSObject(context, scriptObj,
+                                            (PYM_JSObject *) object);
+  }
+  return object;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/script.h	Sun Aug 23 21:49:44 2009 -0700
@@ -0,0 +1,56 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Pymonkey.
+ *
+ * The Initial Developer of the Original Code is Mozilla.
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Atul Varma <atul@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef PYM_SCRIPT_H
+#define PYM_SCRIPT_H
+
+#include "object.h"
+#include "context.h"
+
+#include <jsapi.h>
+#include <Python.h>
+
+typedef struct {
+  PYM_JSObject base;
+  JSScript *script;
+} PYM_JSScript;
+
+extern PyTypeObject PYM_JSScriptType;
+
+extern PYM_JSScript *
+PYM_newJSScript(PYM_JSContextObject *context, JSScript *script);
+
+#endif
--- a/tests/test_pymonkey.py	Sun Aug 23 21:04:51 2009 -0700
+++ b/tests/test_pymonkey.py	Sun Aug 23 21:49:44 2009 -0700
@@ -32,6 +32,15 @@
             was_raised = True
         self.assertTrue(was_raised)
 
+    def testCompileScriptWorks(self):
+        rt = pymonkey.Runtime()
+        cx = rt.new_context()
+        obj = cx.new_object()
+        cx.init_standard_classes(obj)
+        code = '5 + 1'
+        script = cx.compile_script(obj, code, '<string>', 1)
+        self.assertEqual(cx.execute_script(obj, script), 6)
+
     def testErrorsRaisedIncludeStrings(self):
         self.assertRaises(pymonkey.error, self._evaljs, 'boop()')
         self.assertEqual(self.last_exception.args[1],