<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>test/test_require.py</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -473,6 +473,10 @@ Return the JavaScriptCore library as a CDLL or equivalent.&lt;p&gt;
 &lt;hr&gt;
 &lt;h4&gt;Methods&lt;/h4&gt;
 &lt;div style='margin-left:4em'&gt;
+&lt;p&gt;&lt;code&gt;&lt;strong&gt;&lt;a name='api.JSContextRef.addBuiltins'&gt;addBuiltins()&lt;/a&gt;&lt;/strong&gt;&lt;/code&gt;
+&lt;div style='margin-left:4em'&gt;
+Adds the nitro_pie shell builtin functions to this context.&lt;p&gt;
+&lt;/div&gt;
 &lt;p&gt;&lt;code&gt;&lt;strong&gt;&lt;a name='api.JSContextRef.checkScriptSyntax'&gt;checkScriptSyntax(script, sourceURL = None, startingLineNumber = 1)&lt;/a&gt;&lt;/strong&gt;&lt;/code&gt;
 &lt;div style='margin-left:4em'&gt;
 Check the syntax of a string of JavaScript code.&lt;p&gt;
@@ -629,6 +633,15 @@ Creates a new JavaScript number value.&lt;p&gt;
 
 &lt;/ul&gt;
 &lt;/div&gt;
+&lt;p&gt;&lt;code&gt;&lt;strong&gt;&lt;a name='api.JSContextRef.makePythonObjectRef'&gt;makePythonObjectRef(pythonValue)&lt;/a&gt;&lt;/strong&gt;&lt;/code&gt;
+&lt;div style='margin-left:4em'&gt;
+Creates a new JSObjectRef which holds a Python value.&lt;p&gt;
+&lt;p&gt;&lt;strong&gt;Returns:&lt;/strong&gt;
+&lt;ul&gt;
+&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;&lt;code&gt;&lt;a href='#api.JSValueRef'&gt;JSValueRef&lt;/a&gt;&lt;/code&gt;&lt;/code&gt;&lt;/strong&gt; -  the value created
+
+&lt;/ul&gt;
+&lt;/div&gt;
 &lt;p&gt;&lt;code&gt;&lt;strong&gt;&lt;a name='api.JSContextRef.makeString'&gt;makeString(string)&lt;/a&gt;&lt;/strong&gt;&lt;/code&gt;
 &lt;div style='margin-left:4em'&gt;
 Creates a new JavaScript string value.&lt;p&gt;</diff>
      <filename>doc/nitro_pie.html</filename>
    </modified>
    <modified>
      <diff>@@ -76,20 +76,36 @@ def _log(message=&quot;&quot;, args=None):
     
     print &quot;%s[%4d]: %s&quot; % (filename, lineNumber, message)
 
-if False:
-    #-------------------------------------------------------------------
-    kJSTypeUndefined = 0
-    kJSTypeNull      = 1
-    kJSTypeBoolean   = 2
-    kJSTypeNumber    = 3
-    kJSTypeString    = 4
-    kJSTypeObject    = 5 
+#--------------------------------------------------------------------
+class RememberedObjects(object):
+
+    index      = 1
+    remembered = {}
+    
+    #----------------------------------------------------------------
+    @staticmethod
+    def remember(obj, finalizer=None):
+        remembered[index] = (obj, finalizer)
+        
+        result  = index
+        index  += 1
+        return result
+        
+    #----------------------------------------------------------------
+    @staticmethod
+    def get(index):
+        return remembered[index][0]
+        
+    #----------------------------------------------------------------
+    @staticmethod
+    def forget(index):
+        (obj, finalizer) = remembered[index]
+
+        del remembered[index]
+        
+        if finalizer:
+            finalizer(obj)
     
-    #-------------------------------------------------------------------
-    kJSPropertyAttributeNone       = 0
-    kJSPropertyAttributeReadOnly   = 1 &lt;&lt; 1
-    kJSPropertyAttributeDontEnum   = 1 &lt;&lt; 2 
-    kJSPropertyAttributeDontDelete = 1 &lt;&lt; 3 
 
 #--------------------------------------------------------------------
 class JSContextRef(ctypes.c_void_p):
@@ -368,6 +384,25 @@ def callbackPrint(context, function, thisObject, args):
 
         return _JSValueMakeUndefined(self)
 
+    #----------------------------------------------------------------
+    def makePythonObjectRef(self, pythonValue):
+        &quot;&quot;&quot;Creates a new JSObjectRef which holds a Python value.
+        
+        @return (#[JSValueRef]) the value created
+        &quot;&quot;&quot;
+        JSLibrary._ensureLibrary()
+        _log(&quot;JSContextRef.$f(%s)&quot;, (self,))
+
+        return _JSValueMakeUndefined(self)
+
+        #----------------------------------------------------------------
+    def addBuiltins(self):
+        &quot;&quot;&quot;Adds the nitro_pie shell builtin functions to this context.
+        &quot;&quot;&quot;
+        
+        _register_builtins(self)
+        
+        return _JSValueMakeUndefined(self)
     
 #--------------------------------------------------------------------
 class JSGlobalContextRef(JSContextRef):
@@ -1849,6 +1884,42 @@ def _jsfunc_python_exec(context, function, thisObject, args):
 
 
 #-------------------------------------------------------------------------------
+require_modules = {}
+
+def _jsfunc_require(context, function, thisObject, args):
+    undefined = context.makeUndefined()
+
+    if len(args) == 0: return undefined
+
+    modFileName = args[0].toString(context)
+    if not os.path.exists(modFileName): 
+        print &quot;Unabled to load module '%s': not found&quot; % modFileName
+        return undefined
+
+    modFile = open(modFileName)
+    modFileContents = modFile.read()
+    modFile.close()
+    
+    if modFileName in require_modules:
+        return require_modules[modFileName]
+        
+    module = context.eval(&quot;({})&quot;)
+    require_modules[modFileName] = module
+    
+    modContext = JSGlobalContextRef.create()
+    modGlobal  = modContext.getGlobalObject()
+    modGlobal.protect(modContext)
+    
+    modGlobal.setProperty(modContext, &quot;exports&quot;, module)
+    
+    _register_builtins(modContext)
+    
+    modContext.eval(modFileContents, None, modFileName)
+    
+    return module
+
+
+#-------------------------------------------------------------------------------
 def _handleJSException(e, context):
 
     type = e.value.getType(context)
@@ -1883,6 +1954,22 @@ def _handleJSException(e, context):
         print &quot;   %s: %s&quot; % (prop, valStr)
         
     print
+
+#-------------------------------------------------------------------------------
+def _register_builtins(context):
+    globalObject = context.getGlobalObject()
+    globalObject.protect(context)
+    
+    function = context.makeFunction(  &quot;print&quot;, _jsfunc_print)
+    globalObject.setProperty(context, &quot;print&quot;, function)
+    
+    function = context.makeFunction(  &quot;python_exec&quot;, _jsfunc_python_exec)
+    globalObject.setProperty(context, &quot;python_exec&quot;, function)
+    
+    function = context.makeFunction(  &quot;require&quot;, _jsfunc_require)
+    globalObject.setProperty(context, &quot;require&quot;, function)
+
+    globalObject.unprotect(context)
     
 #-------------------------------------------------------------------------------
 def _main():
@@ -1901,16 +1988,11 @@ def _main():
     context = JSGlobalContextRef.create()
     
     globalObject = context.getGlobalObject()
-    globalObject.protect(context)
     
     #---------------------------------------------------------------
     # add builtins
     #---------------------------------------------------------------
-    function = context.makeFunction(  &quot;print&quot;, _jsfunc_print)
-    globalObject.setProperty(context, &quot;print&quot;, function)
-    
-    function = context.makeFunction(  &quot;python_exec&quot;, _jsfunc_python_exec)
-    globalObject.setProperty(context, &quot;python_exec&quot;, function)
+    _register_builtins(context)
     
     #---------------------------------------------------------------
     # add arguments</diff>
      <filename>lib/nitro_pie.py</filename>
    </modified>
    <modified>
      <diff>@@ -53,6 +53,7 @@ test_prototype
 test_tos
 test_iss
 test_shell
+test_require
 &quot;&quot;&quot;.split()
 
 modules = [__import__(moduleName) for moduleName in moduleNames]</diff>
      <filename>test/test_all.py</filename>
    </modified>
    <modified>
      <diff>@@ -26,8 +26,14 @@
 #-------------------------------------------------------------------
 
 import os
+import sys
 import inspect
 
+lib_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), &quot;../lib&quot;))
+if lib_path not in sys.path: sys.path.insert(0, lib_path)
+
+from nitro_pie import *
+
 #-------------------------------------------------------------------
 # logger
 #-------------------------------------------------------------------
@@ -64,3 +70,40 @@ def get_js_props(jsObject):
         result[name] = val
 
     return result
+
+#-------------------------------------------------------------------
+def dump_exception(e, context):
+    
+    type = e.value.getType(context)
+    if type != JSValueRef.kJSTypeObject:
+        print &quot;Exception thrown: value=%s&quot; % e.value.toString(context)
+        return
+    
+    e = e.value.asJSObjectRef(context)
+    
+    def getDefault(context, obj, property, default):
+        if not obj.hasProperty(context, property):
+            return default
+            
+        val = obj.getProperty(context, property)
+        return val.toString(context)
+    
+    name      = getDefault(context, e, &quot;name&quot;,      &quot;???&quot;)
+    message   = getDefault(context, e, &quot;message&quot;,   &quot;???&quot;) 
+    sourceURL = getDefault(context, e, &quot;sourceURL&quot;, &quot;???&quot;)
+    line      = getDefault(context, e, &quot;line&quot;,      &quot;???&quot;)
+
+    print &quot;Exception thrown: %s: %s: at %s[%s]&quot; % (name, message, sourceURL, line)
+
+    props = e.getPropertyNames(context)
+    knownProps = &quot;name message sourceURL line&quot;.split()
+    for prop in props:
+        if prop in knownProps: continue
+
+        val = e.getProperty(context, prop)
+        valStr = val.toString(context)
+        
+        print &quot;   %s: %s&quot; % (prop, valStr)
+        
+    print
+    
\ No newline at end of file</diff>
      <filename>test/test_utils.py</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>1fcea9c7a4ed66a9e98d796929bdf4b78dc527aa</id>
    </parent>
  </parents>
  <author>
    <name>Patrick Mueller</name>
    <email>pmuellr@yahoo.com</email>
  </author>
  <url>http://github.com/pmuellr/nitro_pie/commit/489b4237b05d80013cddfbca8957c6116a4f4f82</url>
  <id>489b4237b05d80013cddfbca8957c6116a4f4f82</id>
  <committed-date>2009-05-15T08:37:22-07:00</committed-date>
  <authored-date>2009-05-15T08:37:22-07:00</authored-date>
  <message>added primordial require() with passing tests</message>
  <tree>824c320f861828b8566330f48e543e28b99759f2</tree>
  <committer>
    <name>Patrick Mueller</name>
    <email>pmuellr@yahoo.com</email>
  </committer>
</commit>
