changeset 2:b6f9d743a2b5

Refined require() implementation.
author Atul Varma <varmaa@toolness.com>
date Wed, 09 Sep 2009 21:48:49 -0700
parents ab09b8a10876
children 14d8d73774d7
files modules/foo.js pydertron.py test.js
diffstat 3 files changed, 52 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/modules/foo.js	Wed Sep 09 21:09:39 2009 -0700
+++ b/modules/foo.js	Wed Sep 09 21:48:49 2009 -0700
@@ -1,3 +1,5 @@
 exports.bar = function bar() {
   print('hay!');
 };
+
+print('loading foo');
--- a/pydertron.py	Wed Sep 09 21:09:39 2009 -0700
+++ b/pydertron.py	Wed Sep 09 21:48:49 2009 -0700
@@ -236,8 +236,9 @@
     def __init__(self, root_dir, watchdog=watchdog):
         rt = pydermonkey.Runtime()
         cx = rt.new_context()
-        root = cx.new_object()
-        cx.init_standard_classes(root)
+        root_proto = cx.new_object()
+        cx.init_standard_classes(root_proto)
+        root = cx.new_object(None, root_proto)
 
         cx.set_operation_callback(self._opcb)
         cx.set_throw_hook(self._throwhook)
@@ -251,6 +252,7 @@
         self.js_stack = None
         self.__py_to_js = {}
         self.__type_protos = {}
+        self.root_proto = root_proto
         self.root = self.wrap_jsobject(root, root)
 
     def finish(self):
@@ -472,26 +474,54 @@
     import os
     sandbox = JsSandbox("modules")
 
-    @jsexposed(on=sandbox.root, name='print')
+    modules = {}
+
+    @jsexposed(name='print')
     def jsprint(string):
         print string
 
-    @jsexposed(on=sandbox.root)
+    @jsexposed
     def require(path):
-        mcx = sandbox.rt.new_context()
-        module = mcx.new_object()
-        mcx.init_standard_classes(module)
-        exports = mcx.new_object()
-        mcx.define_property(module, 'exports', exports)
+        cx = sandbox.cx
+        frame = cx.get_stack()['caller']
+        curr_script = None
+        while frame and curr_script is None:
+            if frame['function'] and frame['function'].filename:
+                curr_script = frame['function'].filename
+            elif frame['script']:
+                curr_script = frame['script'].filename
+            frame = frame['caller']
+
+        if curr_script is None:
+            raise RuntimeError("Can't find calling script")
+
+        curr_dir = os.path.split(curr_script)[0]
 
-        wrappedmodule = sandbox.wrap_jsobject(module)
-        wrappedmodule['print'] = jsprint
-        wrappedmodule['require'] = require
+        filename = os.path.join(sandbox.root_dir, curr_dir, "%s.js" % path)
+        filename = os.path.normpath(filename)
+        if (not filename.startswith(sandbox.root_dir) or
+            not (os.path.exists(filename) and
+                 not os.path.isdir(filename))):
+            raise pydermonkey.error('Module not found: %s' % path)
+
+        if filename not in modules:
+            module = cx.new_object(None, sandbox.root_proto)
+            cx.init_standard_classes(module)
+            exports = cx.new_object()
+            cx.define_property(module, 'exports', exports)
 
-        filename = os.path.join(sandbox.root_dir, "%s.js" % path)
-        contents = open(filename).read()
-        mcx.evaluate_script(module, contents, filename, 1)
-        return sandbox.wrap_jsobject(exports)
+            install_globals(sandbox.wrap_jsobject(module))
+
+            contents = open(filename).read()
+            cx.evaluate_script(module, contents, filename, 1)
+            modules[filename] = sandbox.wrap_jsobject(exports)
 
+        return modules[filename]
+
+    def install_globals(target):
+        target['print'] = jsprint
+        target['require'] = require
+
+    install_globals(sandbox.root)
     sandbox.run_script('test.js')
     sandbox.finish()
--- a/test.js	Wed Sep 09 21:09:39 2009 -0700
+++ b/test.js	Wed Sep 09 21:48:49 2009 -0700
@@ -2,4 +2,8 @@
 
 foo.bar();
 
+foo = require('foo');
+
+foo.bar();
+
 print('hello');