<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/johnson/runtime.rb</filename>
    </added>
    <added>
      <filename>test/johnson/runtime_test.rb</filename>
    </added>
    <added>
      <filename>todo/.keep</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -6,94 +6,6 @@
 #include &quot;idhash.h&quot;
 #include &quot;jsdbgapi.h&quot;
 
-/*
- * call-seq:
- *   global
- *
- * Returns the global object used for this context.
- */
-static VALUE global(VALUE self)
-{
-  OurContext* context;
-  Data_Get_Struct(self, OurContext, context);
-  return convert_to_ruby(context, OBJECT_TO_JSVAL(context-&gt;global));
-}
-
-/*
- * call-seq:
- *   evaluate(script, filename=nil, linenum=nil)
- *
- * Evaluate +script+ with +filename+ using +linenum+
- */
-static VALUE evaluate(int argc, VALUE* argv, VALUE self)
-{
-  VALUE script, filename, linenum;
-
-  OurContext* context;
-  Data_Get_Struct(self, OurContext, context);
-
-  rb_scan_args( argc, argv, &quot;12&quot;, &amp;script, &amp;filename, &amp;linenum );
-
-  // clean things up first
-  context-&gt;ex = 0;
-  memset(context-&gt;msg, 0, MAX_EXCEPTION_MESSAGE_SIZE);
-
-  const char* filenamez = RTEST(filename) ? StringValueCStr(filename) : &quot;none&quot;;
-  int linenumi = RTEST(linenum) ? NUM2INT(linenum) : 1;
-
-  jsval js;
-
-  // FIXME: should be able to pass in the 'file' name
-  JSBool ok = JS_EvaluateScript(context-&gt;js, context-&gt;global,
-    StringValuePtr(script), (unsigned)StringValueLen(script), filenamez, (unsigned)linenumi, &amp;js);
-
-  if (!ok)
-  {
-    if (JS_IsExceptionPending(context-&gt;js))
-    {
-      // If there's an exception pending here, it's a syntax error.
-      JS_GetPendingException(context-&gt;js, &amp;context-&gt;ex);
-      JS_ClearPendingException(context-&gt;js);
-    }
-
-    if (context-&gt;ex)
-    {
-      return rb_funcall(self, rb_intern(&quot;handle_js_exception&quot;),
-        1, convert_to_ruby(context, context-&gt;ex));
-      
-      // VALUE message, file, line, stack;
-      // 
-      // jsval js_message;
-      // assert(JS_GetProperty(context-&gt;js, JSVAL_TO_OBJECT(context-&gt;ex), &quot;message&quot;, &amp;js_message));
-      // message = convert_to_ruby(context, js_message);
-      // 
-      // jsval js_file;
-      // assert(JS_GetProperty(context-&gt;js, JSVAL_TO_OBJECT(context-&gt;ex), &quot;fileName&quot;, &amp;js_file));
-      // file = convert_to_ruby(context, js_file);
-      // 
-      // jsval js_line;
-      // assert(JS_GetProperty(context-&gt;js, JSVAL_TO_OBJECT(context-&gt;ex), &quot;lineNumber&quot;, &amp;js_line));
-      // line = convert_to_ruby(context, js_line);
-      // 
-      // jsval js_stack;
-      // assert(JS_GetProperty(context-&gt;js, JSVAL_TO_OBJECT(context-&gt;ex), &quot;stack&quot;, &amp;js_stack));
-      // stack = convert_to_ruby(context, js_stack);
-      // 
-      // return rb_funcall(self, rb_intern(&quot;handle_js_exception&quot;),
-      //   4, message, file, line, stack);
-    }
-    
-    char* msg = context-&gt;msg;
-
-    // toString() whatever the exception object is (if we have one)
-    if (context-&gt;ex) msg = JS_GetStringBytes(JS_ValueToString(context-&gt;js, context-&gt;ex));
-
-    return Johnson_Error_raise(msg);
-  }
-
-  return convert_to_ruby(context, js);
-}
-
 // callback for JS_SetErrorReporter
 static void report_js_error(JSContext* js, const char* message, JSErrorReport* UNUSED(report))
 {
@@ -101,8 +13,8 @@ static void report_js_error(JSContext* js, const char* message, JSErrorReport* U
   VALUE self = (VALUE)JS_GetContextPrivate(js);
 
   // then we find our bridge
-  OurContext* context;
-  Data_Get_Struct(self, OurContext, context);
+  JohnsonContext* context;
+  Data_Get_Struct(self, JohnsonContext, context);
 
   // NOTE: SpiderMonkey REALLY doesn't like being interrupted. If we
   // jump over to Ruby and raise here, segfaults and such ensue.
@@ -124,80 +36,52 @@ static JSBool branch_callback(JSContext* js, JSScript* UNUSED(script))
 
 /*
  * call-seq:
- *   debugger=(debugger)
+ *   native_initialize(options={})
  *
- * Sets a debugger object
+ * Initializes the native spidermonkey values.
  */
 static VALUE
-set_debugger(VALUE self, VALUE debugger)
+initialize_native(VALUE self, VALUE rb_runtime, VALUE UNUSED(options))
 {
-  OurContext* context;
-  JSDebugHooks* debug_hooks;
+  JohnsonContext* context;
+  JohnsonRuntime* runtime;
 
-  Data_Get_Struct(self, OurContext, context);
-  Data_Get_Struct(debugger, JSDebugHooks, debug_hooks);
+  Data_Get_Struct(self, JohnsonContext, context);
+  Data_Get_Struct(rb_runtime, JohnsonRuntime, runtime);
 
-  JS_SetContextDebugHooks(context-&gt;js, debug_hooks);
+  if ((context-&gt;js = JS_NewContext(runtime-&gt;js, 8192)))
+  {
+    // See if the runtime already has a shared global object.
+    JSObject* global = runtime-&gt;global;
 
-  return debugger;
-}
+    // If it does, use it. If not,
+    if (!global)
+      // create one of our global objects.
+      global = johnson_create_global_object(context-&gt;js);
 
-/*
- * call-seq:
- *   native_initialize(options={})
- *
- * Initializes the native spidermonkey values.
- */
-static VALUE
-initialize_native(VALUE self, VALUE UNUSED(options))
-{
-  OurContext* context;
-  bool gthings_rooted_p = false;
-
-  Data_Get_Struct(self, OurContext, context);
-
-  if ((context-&gt;runtime = JS_NewRuntime(0x100000))
-    &amp;&amp; (context-&gt;js = JS_NewContext(context-&gt;runtime, 8192))
-    &amp;&amp; (context-&gt;jsids = create_id_hash())
-    &amp;&amp; (context-&gt;rbids = create_id_hash())
-    &amp;&amp; (context-&gt;gcthings = JS_NewObject(context-&gt;js, NULL, 0, 0))
-    &amp;&amp; (gthings_rooted_p = JS_AddNamedRoot(context-&gt;js, &amp;(context-&gt;gcthings), &quot;context-&gt;gcthings&quot;))
-    &amp;&amp; (context-&gt;global = create_global_object(context))
-    &amp;&amp; (JS_AddNamedRoot(context-&gt;js, &amp;(context-&gt;global), &quot;context-&gt;global&quot;)))
-  {
+    // Manually set the context's global object.
+    JS_SetGlobalObject(context-&gt;js, global);
     JS_SetErrorReporter(context-&gt;js, report_js_error);
     JS_SetBranchCallback(context-&gt;js, branch_callback);
     JS_SetContextPrivate(context-&gt;js, (void *)self);
 
     JS_SetOptions(context-&gt;js, JS_GetOptions(context-&gt;js)
 #ifdef JSOPTION_DONT_REPORT_UNCAUGHT
-      | JSOPTION_DONT_REPORT_UNCAUGHT
+        | JSOPTION_DONT_REPORT_UNCAUGHT
 #endif
 #ifdef JSOPTION_VAROBJFIX
-      | JSOPTION_VAROBJFIX
+        | JSOPTION_VAROBJFIX
 #endif
 #ifdef JSOPTION_XML
-      | JSOPTION_XML
+        | JSOPTION_XML
 #endif
-    );
+        );
 
+    // Success.
     return init_spidermonkey_extensions(context, self);
   }
 
-  if (gthings_rooted_p)
-    JS_RemoveRoot(context-&gt;js, &amp;(context-&gt;gcthings));
-
-  if (context-&gt;rbids)
-    JS_HashTableDestroy(context-&gt;rbids);
-
-  if (context-&gt;jsids)
-    JS_HashTableDestroy(context-&gt;jsids);
-
-  if (context-&gt;js)
-    JS_DestroyContext(context-&gt;js);
-
-  if (context-&gt;runtime)
-    JS_DestroyRuntime(context-&gt;runtime);
+  if (context-&gt;js) JS_DestroyContext(context-&gt;js);
 
   rb_raise(rb_eRuntimeError, &quot;Failed to initialize SpiderMonkey context&quot;);
 }
@@ -206,27 +90,16 @@ initialize_native(VALUE self, VALUE UNUSED(options))
 //// INFRASTRUCTURE BELOW HERE ////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////
 
-static void deallocate(OurContext* context)
+static void deallocate(JohnsonContext* context)
 {
   JS_SetContextPrivate(context-&gt;js, 0);
-
-  JS_RemoveRoot(context-&gt;js, &amp;(context-&gt;global));
-  JS_RemoveRoot(context-&gt;js, &amp;(context-&gt;gcthings));
-  JS_HashTableDestroy(context-&gt;rbids);
-  JS_HashTableDestroy(context-&gt;jsids);
-
-  context-&gt;jsids = 0;
-  context-&gt;rbids = 0;
-
   JS_DestroyContext(context-&gt;js);
-  JS_DestroyRuntime(context-&gt;runtime);
-
   free(context);
 }
 
 static VALUE allocate(VALUE klass)
 {
-  OurContext* context = calloc(1, sizeof(OurContext));
+  JohnsonContext* context = calloc(1, sizeof(JohnsonContext));
   return Data_Wrap_Struct(klass, 0, deallocate, context);
 }
 
@@ -241,11 +114,7 @@ void init_Johnson_SpiderMonkey_Context(VALUE spidermonkey)
   VALUE context = rb_define_class_under(spidermonkey, &quot;Context&quot;, rb_cObject);
 
   rb_define_alloc_func(context, allocate);
-  rb_define_private_method(context, &quot;initialize_native&quot;, initialize_native, 1);
-
-  rb_define_method(context, &quot;global&quot;, global, 0);
-  rb_define_method(context, &quot;evaluate&quot;, evaluate, -1);
-  rb_define_method(context, &quot;debugger=&quot;, set_debugger, 1);
+  rb_define_private_method(context, &quot;initialize_native&quot;, initialize_native, 2);
 }
 
 VALUE Johnson_SpiderMonkey_JSLandProxy()</diff>
      <filename>ext/spidermonkey/context.c</filename>
    </modified>
    <modified>
      <diff>@@ -7,17 +7,11 @@
 
 typedef struct {
   JSContext *js;
-  JSObject *global;
-  JSRuntime *runtime;
-  
-  JSHashTable *jsids; // jsid -&gt; rbid
-  JSHashTable *rbids; // rbid -&gt; jsid
-  JSObject *gcthings;
   
   jsval ex; // an exception value
   char msg[MAX_EXCEPTION_MESSAGE_SIZE]; // the 'backup' message
   
-} OurContext;
+} JohnsonContext;
 
 void init_Johnson_SpiderMonkey_Context(VALUE spidermonkey);
 VALUE Johnson_SpiderMonkey_JSLandProxy();</diff>
      <filename>ext/spidermonkey/context.h</filename>
    </modified>
    <modified>
      <diff>@@ -3,7 +3,7 @@
 #include &quot;ruby_land_proxy.h&quot;
 #include &quot;error.h&quot;
 
-DEFINE_RUBY_WRAPPER(convert_to_ruby, convert_to_ruby, ARGLIST2(context, js_value))
+DEFINE_RUBY_WRAPPER(convert_to_ruby, convert_to_ruby, ARGLIST2(runtime, js_value))
 
 DECLARE_RUBY_WRAPPER(rb_funcall_0, VALUE obj; ID sym; int argc)
 DEFINE_RUBY_WRAPPER(rb_funcall_0, rb_funcall, ARGLIST3(obj, sym, argc))
@@ -11,37 +11,40 @@ DEFINE_RUBY_WRAPPER(rb_funcall_0, rb_funcall, ARGLIST3(obj, sym, argc))
 DECLARE_RUBY_WRAPPER(rb_funcall_2, VALUE obj; ID sym; int argc; VALUE a; VALUE b)
 DEFINE_RUBY_WRAPPER(rb_funcall_2, rb_funcall, ARGLIST5(obj, sym, argc, a, b))
 
-static JSBool convert_float_or_bignum_to_js(OurContext* context, VALUE float_or_bignum, jsval* retval)
+static JSBool convert_float_or_bignum_to_js(JohnsonRuntime* runtime, VALUE float_or_bignum, jsval* retval)
 {
-  return JS_NewDoubleValue(context-&gt;js, NUM2DBL(float_or_bignum), retval);
+  JSContext * context = johnson_get_current_context(runtime);
+  return JS_NewDoubleValue(context, NUM2DBL(float_or_bignum), retval);
 }
 
-static JSBool convert_symbol_to_js(OurContext* context, VALUE symbol, jsval* retval)
+static JSBool convert_symbol_to_js(JohnsonRuntime* runtime, VALUE symbol, jsval* retval)
 {
+  JSContext * context = johnson_get_current_context(runtime);
   PREPARE_JROOTS(context, 2);
 
   VALUE to_s = CALL_RUBY_WRAPPER(rb_funcall_0, symbol, rb_intern(&quot;to_s&quot;), 0);
-  jsval name = STRING_TO_JSVAL(JS_NewStringCopyN(context-&gt;js, StringValuePtr(to_s), (unsigned) StringValueLen(to_s)));
+  jsval name = STRING_TO_JSVAL(JS_NewStringCopyN(context, StringValuePtr(to_s), (unsigned) StringValueLen(to_s)));
 
   JROOT(name);
 
   // calls Johnson.symbolize(name) in JS-land. See lib/prelude.js
 
   jsval nsJohnson;    
-  JCHECK(JS_GetProperty(context-&gt;js, context-&gt;global, &quot;Johnson&quot;, &amp;nsJohnson));
+  JCHECK(JS_GetProperty(context, runtime-&gt;global, &quot;Johnson&quot;, &amp;nsJohnson));
   JROOT(nsJohnson);
 
-  JCHECK(JS_CallFunctionName(context-&gt;js, JSVAL_TO_OBJECT(nsJohnson), &quot;symbolize&quot;, 1, &amp;name, retval));
+  JCHECK(JS_CallFunctionName(context, JSVAL_TO_OBJECT(nsJohnson), &quot;symbolize&quot;, 1, &amp;name, retval));
 
   JRETURN;
 }
 
-static JSBool convert_regexp_to_js(OurContext* context, VALUE regexp, jsval* retval)
+static JSBool convert_regexp_to_js(JohnsonRuntime* runtime, VALUE regexp, jsval* retval)
 {
+  JSContext * context = johnson_get_current_context(runtime);
   VALUE source = rb_funcall(regexp, rb_intern(&quot;source&quot;), 0);
   int options = NUM2INT(rb_funcall(regexp, rb_intern(&quot;options&quot;), 0));
 
-  JSObject* obj = JS_NewRegExpObject(context-&gt;js,
+  JSObject* obj = JS_NewRegExpObject(context,
         StringValuePtr(source),
         (unsigned) StringValueLen(source),
         (unsigned) options);
@@ -54,8 +57,9 @@ static JSBool convert_regexp_to_js(OurContext* context, VALUE regexp, jsval* ret
   }
 }
 
-JSBool convert_to_js(OurContext* context, VALUE ruby, jsval* retval)
+JSBool convert_to_js(JohnsonRuntime* runtime, VALUE ruby, jsval* retval)
 {
+  JSContext * context = johnson_get_current_context(runtime);
   switch(TYPE(ruby))
   {
     case T_NIL:
@@ -72,7 +76,7 @@ JSBool convert_to_js(OurContext* context, VALUE ruby, jsval* retval)
 
     case T_STRING:
       {
-        JSString* str = JS_NewStringCopyN(context-&gt;js, StringValuePtr(ruby), (unsigned) StringValueLen(ruby));
+        JSString* str = JS_NewStringCopyN(context, StringValuePtr(ruby), (unsigned) StringValueLen(ruby));
         if (str) {
           *retval = STRING_TO_JSVAL(str);
           return JS_TRUE;
@@ -87,10 +91,10 @@ JSBool convert_to_js(OurContext* context, VALUE ruby, jsval* retval)
 
     case T_FLOAT:
     case T_BIGNUM:
-      return convert_float_or_bignum_to_js(context, ruby, retval);
+      return convert_float_or_bignum_to_js(runtime, ruby, retval);
 
     case T_SYMBOL:
-      return convert_symbol_to_js(context, ruby, retval);
+      return convert_symbol_to_js(runtime, ruby, retval);
 
     case T_CLASS:
     case T_ARRAY:
@@ -99,17 +103,17 @@ JSBool convert_to_js(OurContext* context, VALUE ruby, jsval* retval)
     case T_FILE:
     case T_STRUCT:
     case T_OBJECT:
-      return make_js_land_proxy(context, ruby, retval);
+      return make_js_land_proxy(runtime, ruby, retval);
       
     case T_REGEXP:
-      return convert_regexp_to_js(context, ruby, retval);
+      return convert_regexp_to_js(runtime, ruby, retval);
 
     case T_DATA: // HEY! keep T_DATA last for fall-through
       if (ruby_value_is_proxy(ruby))
-        return unwrap_ruby_land_proxy(context, ruby, retval);
+        return unwrap_ruby_land_proxy(runtime, ruby, retval);
 
       // If we can't identify the object, just wrap it
-      return make_js_land_proxy(context, ruby, retval);
+      return make_js_land_proxy(runtime, ruby, retval);
     
     default:
       Johnson_Error_raise(&quot;unknown ruby type in switch&quot;);
@@ -119,8 +123,9 @@ JSBool convert_to_js(OurContext* context, VALUE ruby, jsval* retval)
   return JS_TRUE;
 }
 
-VALUE convert_jsstring_to_ruby(OurContext* context, JSString* str)
+VALUE convert_js_string_to_ruby(JohnsonRuntime* runtime, JSString* str)
 {
+  JSContext * context = johnson_get_current_context(runtime);
   PREPARE_RUBY_JROOTS(context, 1);
   JROOT(str);
   char* bytes = JS_GetStringBytes(str);
@@ -128,55 +133,60 @@ VALUE convert_jsstring_to_ruby(OurContext* context, JSString* str)
   JRETURN_RUBY(rb_str_new(bytes, (signed)JS_GetStringLength(str)));
 }
 
-static VALUE convert_regexp_to_ruby(OurContext* context, jsval regexp)
+static VALUE convert_regexp_to_ruby(JohnsonRuntime* runtime, jsval regexp)
 {
+  JSContext * context = johnson_get_current_context(runtime);
   PREPARE_RUBY_JROOTS(context, 1);
   JROOT(regexp);
-  JSRegExp* re = (JSRegExp*)JS_GetPrivate(context-&gt;js, JSVAL_TO_OBJECT(regexp));
+  JSRegExp* re = (JSRegExp*)JS_GetPrivate(context, JSVAL_TO_OBJECT(regexp));
 
   JRETURN_RUBY(CALL_RUBY_WRAPPER(rb_funcall_2, rb_cRegexp, rb_intern(&quot;new&quot;), 2,
-    convert_jsstring_to_ruby(context, re-&gt;source),
+    convert_js_string_to_ruby(runtime, re-&gt;source),
     INT2NUM(re-&gt;flags)));
 }
 
-static bool js_value_is_regexp(OurContext* context, jsval maybe_regexp)
+static bool js_value_is_regexp(JohnsonRuntime* runtime, jsval maybe_regexp)
 {
+  JSContext * context = johnson_get_current_context(runtime);
   PREPARE_RUBY_JROOTS(context, 1);
   JROOT(maybe_regexp);
-  JSBool result = JS_InstanceOf(context-&gt;js, JSVAL_TO_OBJECT(maybe_regexp), &amp;js_RegExpClass, NULL);
+  JSBool result = JS_InstanceOf(context, JSVAL_TO_OBJECT(maybe_regexp), &amp;js_RegExpClass, NULL);
   JRETURN_RUBY(result ? true : false);
 }
 
-static bool js_value_is_symbol(OurContext* context, jsval maybe_symbol)
+static bool js_value_is_symbol(JohnsonRuntime* runtime, jsval maybe_symbol)
 {
   jsval nsJohnson, cSymbol;
+  JSContext * context = johnson_get_current_context(runtime);
 
   PREPARE_RUBY_JROOTS(context, 3);
   JROOT(maybe_symbol);
 
-  JCHECK(JS_GetProperty(context-&gt;js, context-&gt;global, &quot;Johnson&quot;, &amp;nsJohnson));
+  JCHECK(JS_GetProperty(context, runtime-&gt;global, &quot;Johnson&quot;, &amp;nsJohnson));
   if (!JSVAL_IS_OBJECT(nsJohnson))
     JERROR(&quot;Unable to retrieve Johnson from JSLand&quot;);
   JROOT(nsJohnson);
 
-  JCHECK(JS_GetProperty(context-&gt;js, JSVAL_TO_OBJECT(nsJohnson), &quot;Symbol&quot;, &amp;cSymbol));
+  JCHECK(JS_GetProperty(context, JSVAL_TO_OBJECT(nsJohnson), &quot;Symbol&quot;, &amp;cSymbol));
   if (!JSVAL_IS_OBJECT(cSymbol))
     JERROR(&quot;Unable to retrieve Johnson.Symbol from JSLand&quot;);
   JROOT(cSymbol);
 
   JSBool is_a_symbol;
-  JCHECK(JS_HasInstance(context-&gt;js, JSVAL_TO_OBJECT(cSymbol), maybe_symbol, &amp;is_a_symbol));
+  JCHECK(JS_HasInstance(context, JSVAL_TO_OBJECT(cSymbol), maybe_symbol, &amp;is_a_symbol));
 
   JRETURN_RUBY(is_a_symbol != JS_FALSE);
 }
 
-VALUE convert_to_ruby(OurContext* context, jsval js)
+VALUE convert_to_ruby(JohnsonRuntime* runtime, jsval js)
 {
   if (JSVAL_NULL == js) return Qnil;
 
+  JSContext * context = johnson_get_current_context(runtime);
+
   PREPARE_RUBY_JROOTS(context, 1);
   
-  switch (JS_TypeOfValue(context-&gt;js, js))
+  switch (JS_TypeOfValue(context, js))
   {
     case JSTYPE_VOID:
       JRETURN_RUBY(Qnil);
@@ -185,27 +195,27 @@ VALUE convert_to_ruby(OurContext* context, jsval js)
     case JSTYPE_OBJECT:
       JROOT(js);
 
-      if (OBJECT_TO_JSVAL(context-&gt;global) == js)
+      if (OBJECT_TO_JSVAL(runtime-&gt;global) == js)
         // global gets special treatment, since the Prelude might not be loaded
-        JRETURN_RUBY(make_ruby_land_proxy(context, js));
+        JRETURN_RUBY(make_ruby_land_proxy(runtime, js));
       
       // this conditional requires the Prelude
-      if (js_value_is_symbol(context, js))
-        JRETURN_RUBY(ID2SYM(rb_intern(JS_GetStringBytes(JS_ValueToString(context-&gt;js, js)))));
+      if (js_value_is_symbol(runtime, js))
+        JRETURN_RUBY(ID2SYM(rb_intern(JS_GetStringBytes(JS_ValueToString(context, js)))));
     
-      if (js_value_is_proxy(context, js))
-        JRETURN_RUBY(unwrap_js_land_proxy(context, js));
+      if (js_value_is_proxy(runtime, js))
+        JRETURN_RUBY(unwrap_js_land_proxy(runtime, js));
 
-      if (js_value_is_regexp(context, js))
-        JRETURN_RUBY(convert_regexp_to_ruby(context, js));
+      if (js_value_is_regexp(runtime, js))
+        JRETURN_RUBY(convert_regexp_to_ruby(runtime, js));
     
-      JRETURN_RUBY(make_ruby_land_proxy(context, js));
+      JRETURN_RUBY(make_ruby_land_proxy(runtime, js));
         
     case JSTYPE_BOOLEAN:
       JRETURN_RUBY(JSVAL_TRUE == js ? Qtrue : Qfalse);
       
     case JSTYPE_STRING:
-      JRETURN_RUBY(convert_jsstring_to_ruby(context, JSVAL_TO_STRING(js)));
+      JRETURN_RUBY(convert_js_string_to_ruby(runtime, JSVAL_TO_STRING(js)));
       
     case JSTYPE_NUMBER:
       if (JSVAL_IS_INT(js)) JRETURN_RUBY(INT2FIX(JSVAL_TO_INT(js)));
@@ -218,32 +228,35 @@ VALUE convert_to_ruby(OurContext* context, jsval js)
   JRETURN_RUBY(Qnil);
 }
 
-NORETURN(void) raise_js_error_in_ruby(OurContext* context)
+NORETURN(void) raise_js_error_in_ruby(JohnsonRuntime* runtime)
 {
-  if (JS_IsExceptionPending(context-&gt;js))
+  JSContext * context = johnson_get_current_context(runtime);
+  JohnsonContext * johnson_context = OUR_CONTEXT(context);
+  if (JS_IsExceptionPending(context))
   {
-    assert(JS_GetPendingException(context-&gt;js, &amp;(context-&gt;ex)));
-    JS_AddNamedRoot(context-&gt;js, &amp;(context-&gt;ex), &quot;raise_js_error_in_ruby&quot;);
-    JS_ClearPendingException(context-&gt;js);
-    JS_RemoveRoot(context-&gt;js, &amp;(context-&gt;ex));
+    assert(JS_GetPendingException(context, &amp;(johnson_context-&gt;ex)));
+    JS_AddNamedRoot(context, &amp;(johnson_context-&gt;ex), &quot;raise_js_error_in_ruby&quot;);
+    JS_ClearPendingException(context);
+    JS_RemoveRoot(context, &amp;(johnson_context-&gt;ex));
   }
 
-  VALUE ruby_context = (VALUE)JS_GetContextPrivate(context-&gt;js);
-  if (context-&gt;ex)
+  VALUE ruby_context = (VALUE)JS_GetContextPrivate(context);
+  if (johnson_context-&gt;ex)
     rb_funcall(ruby_context, rb_intern(&quot;handle_js_exception&quot;),
-      1, convert_to_ruby(context, context-&gt;ex));
+      1, convert_to_ruby(runtime, johnson_context-&gt;ex));
 
-  if (!context-&gt;msg)
+  if (!johnson_context-&gt;msg)
     Johnson_Error_raise(&quot;Unknown JavaScript Error&quot;);
 
-  Johnson_Error_raise(context-&gt;msg);
+  Johnson_Error_raise(johnson_context-&gt;msg);
 }
 
 #define TAG_RAISE 0x6
 #define TAG_THROW 0x7
 
-JSBool report_ruby_error_in_js(OurContext* context, int state, VALUE old_errinfo)
+JSBool report_ruby_error_in_js(JohnsonRuntime* runtime, int state, VALUE old_errinfo)
 {
+  JSContext * context = johnson_get_current_context(runtime);
   assert(state);
   switch (state)
   {
@@ -252,9 +265,9 @@ JSBool report_ruby_error_in_js(OurContext* context, int state, VALUE old_errinfo
         VALUE local_error = ruby_errinfo;
         jsval js_err;
         ruby_errinfo = old_errinfo;
-        if (!convert_to_js(context, local_error, &amp;js_err))
+        if (!convert_to_js(runtime, local_error, &amp;js_err))
           return JS_FALSE;
-        JS_SetPendingException(context-&gt;js, js_err);
+        JS_SetPendingException(context, js_err);
         return JS_FALSE;
       }
 
@@ -263,9 +276,9 @@ JSBool report_ruby_error_in_js(OurContext* context, int state, VALUE old_errinfo
 
     default:
       {
-        JSString* str = JS_NewStringCopyZ(context-&gt;js, &quot;Unexpected longjmp from ruby!&quot;);
+        JSString* str = JS_NewStringCopyZ(context, &quot;Unexpected longjmp from ruby!&quot;);
         if (str)
-          JS_SetPendingException(context-&gt;js, STRING_TO_JSVAL(str));
+          JS_SetPendingException(context, STRING_TO_JSVAL(str));
         return JS_FALSE;
       }
   }</diff>
      <filename>ext/spidermonkey/conversions.c</filename>
    </modified>
    <modified>
      <diff>@@ -3,15 +3,16 @@
 
 #include &quot;spidermonkey.h&quot;
 #include &quot;context.h&quot;
+#include &quot;runtime.h&quot;
 
-DECLARE_RUBY_WRAPPER(convert_to_ruby, OurContext* context; jsval js_value)
-#define CONVERT_TO_RUBY(context, js) CALL_RUBY_WRAPPER(convert_to_ruby, context, js)
+DECLARE_RUBY_WRAPPER(convert_to_ruby, JohnsonRuntime* runtime; jsval js_value)
+#define CONVERT_TO_RUBY(runtime, js) CALL_RUBY_WRAPPER(convert_to_ruby, runtime, js)
 
-JSBool convert_to_js(OurContext* context, VALUE ruby, jsval* retval);
-VALUE convert_to_ruby(OurContext* context, jsval js);
-VALUE convert_jsstring_to_ruby(OurContext* context, JSString* str);
+JSBool convert_to_js(JohnsonRuntime* runtime, VALUE ruby, jsval* retval);
+VALUE convert_to_ruby(JohnsonRuntime* runtime, jsval js);
+VALUE convert_js_string_to_ruby(JohnsonRuntime* runtime, JSString* str);
 
-NORETURN(void raise_js_error_in_ruby(OurContext* context));
-JSBool report_ruby_error_in_js(OurContext* context, int state, VALUE old_errinfo);
+NORETURN(void raise_js_error_in_ruby(JohnsonRuntime* runtime));
+JSBool report_ruby_error_in_js(JohnsonRuntime* runtime, int state, VALUE old_errinfo);
 
 #endif</diff>
      <filename>ext/spidermonkey/conversions.h</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,7 @@ static JSTrapStatus interrupt_handler(JSContext *js, JSScript *UNUSED(script),
 {
   VALUE self = (VALUE)rb;
   VALUE rb_bytecode = jsop_to_symbol(*pc);
-  VALUE rb_rval = convert_to_ruby(OUR_CONTEXT(js), *rval);
+  VALUE rb_rval = convert_to_ruby(OUR_RUNTIME(js), *rval);
   return NUM2INT(rb_funcall(self, rb_intern(&quot;interrupt_handler&quot;), 2, rb_bytecode, rb_rval));
 }
 
@@ -40,7 +40,7 @@ static JSTrapStatus debugger_handler(JSContext *js, JSScript *UNUSED(script),
 {
   VALUE self = (VALUE)rb;
   VALUE rb_bytecode = jsop_to_symbol(*pc);
-  VALUE rb_rval = convert_to_ruby(OUR_CONTEXT(js), *rval);
+  VALUE rb_rval = convert_to_ruby(OUR_RUNTIME(js), *rval);
   return NUM2INT(rb_funcall(self, rb_intern(&quot;debugger_handler&quot;), 2, rb_bytecode, rb_rval));
 }
 
@@ -82,7 +82,7 @@ static void object_hook(JSContext *js, JSObject *obj, JSBool isNew, void *rb)
 {
   VALUE self = (VALUE)rb;
 
-  VALUE rb_obj = convert_to_ruby(OUR_CONTEXT(js), OBJECT_TO_JSVAL(obj));
+  VALUE rb_obj = convert_to_ruby(OUR_RUNTIME(js), OBJECT_TO_JSVAL(obj));
   VALUE rb_is_new = isNew ? Qtrue : Qfalse;
 
   rb_funcall(self, rb_intern(&quot;object_hook&quot;), 2, rb_obj, rb_is_new);
@@ -93,7 +93,7 @@ static JSTrapStatus throw_hook(JSContext *js, JSScript *UNUSED(script),
 {
   VALUE self = (VALUE)rb;
   VALUE rb_bytecode = jsop_to_symbol(*pc);
-  VALUE rb_rval = convert_to_ruby(OUR_CONTEXT(js), *rval);
+  VALUE rb_rval = convert_to_ruby(OUR_RUNTIME(js), *rval);
   return NUM2INT(rb_funcall(self, rb_intern(&quot;throw_hook&quot;), 2, rb_bytecode, rb_rval));
 }
 </diff>
      <filename>ext/spidermonkey/debugger.c</filename>
    </modified>
    <modified>
      <diff>@@ -12,12 +12,13 @@ define_property(JSContext *js_context, JSObject* UNUSED(obj), uintN argc, jsval
   return JS_DefineProperty(js_context, JSVAL_TO_OBJECT(argv[0]), name, argc &gt; 2 ? argv[2] : JSVAL_VOID, NULL, NULL, flags);
 }
 
-VALUE init_spidermonkey_extensions(OurContext* context, VALUE self)
+VALUE init_spidermonkey_extensions(JohnsonContext* context, VALUE self)
 {
-  PREPARE_RUBY_JROOTS(context, 1);
+  PREPARE_RUBY_JROOTS(context-&gt;js, 1);
   
   jsval Object;
-  JCHECK(JS_GetProperty(context-&gt;js, context-&gt;global, &quot;Object&quot;, &amp;Object));
+  JSObject * global = JS_GetGlobalObject(context-&gt;js);
+  JCHECK(JS_GetProperty(context-&gt;js, global, &quot;Object&quot;, &amp;Object));
   JROOT(Object);
 
   JCHECK(JS_DefineFunction(context-&gt;js, JSVAL_TO_OBJECT(Object),</diff>
      <filename>ext/spidermonkey/extensions.c</filename>
    </modified>
    <modified>
      <diff>@@ -5,6 +5,8 @@
 #include &quot;context.h&quot;
 #include &quot;conversions.h&quot;
 
-VALUE init_spidermonkey_extensions(OurContext* context, VALUE self);
+// A context is passed here because there might not be a current context
+// for the runtime when the function is called.
+VALUE init_spidermonkey_extensions(JohnsonContext* context, VALUE self);
 
 #endif</diff>
      <filename>ext/spidermonkey/extensions.h</filename>
    </modified>
    <modified>
      <diff>@@ -34,12 +34,7 @@ static JSClass OurGlobalClass = {
   JSCLASS_NO_OPTIONAL_MEMBERS
 };
 
-JSObject* create_global_object(OurContext* context)
-{
-  return JS_NewObject(context-&gt;js, &amp;OurGlobalClass, NULL, NULL);
-}
-
 JSObject* johnson_create_global_object(JSContext* context)
 {
   return JS_NewObject(context, &amp;OurGlobalClass, NULL, NULL);
-}
\ No newline at end of file
+}</diff>
      <filename>ext/spidermonkey/global.c</filename>
    </modified>
    <modified>
      <diff>@@ -5,8 +5,6 @@
 #include &quot;context.h&quot;
 #include &quot;runtime.h&quot;
 
-JSObject* create_global_object(OurContext* context); // FIXME: remove or rename
-
 // NOTE: one of the FEW places a context should be passed around
 JSObject* johnson_create_global_object(JSContext* context);
 </diff>
      <filename>ext/spidermonkey/global.h</filename>
    </modified>
    <modified>
      <diff>@@ -8,18 +8,28 @@
 
 #define OUR_CONTEXT(js_context) \
   ({ \
-    OurContext* _context; \
+    JohnsonContext* _context; \
     const VALUE _ruby_context = (VALUE)JS_GetContextPrivate(js_context); \
-    Data_Get_Struct(_ruby_context, OurContext, _context); \
+    Data_Get_Struct(_ruby_context, JohnsonContext, _context); \
     _context; \
   })
 
+#define OUR_RUNTIME(js_context) \
+  ({ \
+    JohnsonRuntime* _johnson_runtime; \
+    JSRuntime * _js_runtime = JS_GetRuntime(js_context);\
+    const VALUE _ruby_runtime = (VALUE)JS_GetRuntimePrivate(_js_runtime); \
+    Data_Get_Struct(_ruby_runtime, JohnsonRuntime, _johnson_runtime); \
+    _johnson_runtime; \
+   })
+    
+
 #define _PREPARE_JROOTS(rb, context, cleancount) \
   const bool _jroot_ruby = (rb); \
   const int _jroot_cleans = (cleancount); \
-  void (*_jroot_cleanup[_jroot_cleans])(OurContext*, void*); \
+  void (*_jroot_cleanup[_jroot_cleans])(JSContext*, void*); \
   void* _jroot_cleanup_data[_jroot_cleans]; \
-  OurContext* const _jroot_context = (context); \
+  JSContext* const _jroot_context = (context); \
   int _jroot_cleanidx = 0;
 
 #define PREPARE_JROOTS(context, cleancount) \
@@ -44,7 +54,7 @@
     void* const _root = (ptr); \
     if (*_name == '\0') \
       snprintf(_name, _JROOT_NAMESIZE, &quot;%s[%d]:%s: %s&quot;, __FILE__, __LINE__, __func__, (name)); \
-    JCHECK(JS_AddNamedRoot(_jroot_context-&gt;js, _root, _name)); \
+    JCHECK(JS_AddNamedRoot(_jroot_context, _root, _name)); \
     JCLEANUP(_JROOT_ROOT, _root); \
   } while(0)
 
@@ -59,7 +69,7 @@
     for (_jroot_i = _jroot_cleanidx - 1; _jroot_i &gt;= 0; _jroot_i--) \
       if (_jroot_cleanup[_jroot_i] == _JROOT_ROOT &amp;&amp; _jroot_cleanup_data[_jroot_i] == _jroot_match) \
       { \
-        JS_RemoveRoot(_jroot_context-&gt;js, _jroot_cleanup_data[_jroot_i]); \
+        JS_RemoveRoot(_jroot_context, _jroot_cleanup_data[_jroot_i]); \
         if (_jroot_i == _jroot_cleanidx - 1) _jroot_cleanidx--; \
         _jroot_cleanup[_jroot_i] = NULL; \
       } \
@@ -72,7 +82,7 @@
     for (_jroot_i = _jroot_cleanidx - 1; _jroot_i &gt;= 0; _jroot_i--) \
     { \
       if (_jroot_cleanup[_jroot_i] == _JROOT_ROOT) \
-        JS_RemoveRoot(_jroot_context-&gt;js, _jroot_cleanup_data[_jroot_i]); \
+        JS_RemoveRoot(_jroot_context, _jroot_cleanup_data[_jroot_i]); \
       else if (_jroot_cleanup[_jroot_i]) \
         (_jroot_cleanup[_jroot_i])(_jroot_context, _jroot_cleanup_data[_jroot_i]); \
     } \
@@ -85,7 +95,7 @@
     if (!(cond)) \
     { \
       REMOVE_JROOTS; \
-      raise_js_error_in_ruby(_jroot_context); \
+      raise_js_error_in_ruby(OUR_RUNTIME(_jroot_context)); \
     } \
   } while (0)
 
@@ -96,7 +106,7 @@
     { \
       REMOVE_JROOTS; \
       if (_jroot_ruby) \
-        raise_js_error_in_ruby(_jroot_context); \
+        raise_js_error_in_ruby(OUR_RUNTIME(_jroot_context)); \
       else \
         return JS_FALSE; \
     } \
@@ -113,7 +123,7 @@
       if (_jroot_ruby) \
         rb_jump_tag(_state); \
       else \
-        return report_ruby_error_in_js(_jroot_context, _state, _old_errinfo); \
+        return report_ruby_error_in_js(OUR_RUNTIME(_jroot_context), _state, _old_errinfo); \
     } \
     _result; \
   })
@@ -145,8 +155,8 @@
       Johnson_Error_raise(_jroot_msg); \
     else \
     { \
-      JSString* _jroot_err_str = JS_NewStringCopyZ(_jroot_context-&gt;js, _jroot_msg); \
-      if (_jroot_err_str) JS_SetPendingException(_jroot_context-&gt;js, STRING_TO_JSVAL(_jroot_err_str)); \
+      JSString* _jroot_err_str = JS_NewStringCopyZ(_jroot_context, _jroot_msg); \
+      if (_jroot_err_str) JS_SetPendingException(_jroot_context, STRING_TO_JSVAL(_jroot_err_str)); \
       return JS_FALSE; \
     } \
   } while(0)</diff>
      <filename>ext/spidermonkey/jroot.h</filename>
    </modified>
    <modified>
      <diff>@@ -58,7 +58,7 @@ static VALUE call_ruby_from_js_invoke(VALUE args)
   return rb_apply(self, SYM2ID(id), args);
 }
 
-JSBool call_ruby_from_js_va(OurContext* context, VALUE* result, VALUE self, ID id, int argc, va_list va)
+JSBool call_ruby_from_js_va(JohnsonRuntime* runtime, VALUE* result, VALUE self, ID id, int argc, va_list va)
 {
   VALUE old_errinfo = ruby_errinfo;
   VALUE args = rb_ary_new2(argc + 2);
@@ -74,27 +74,27 @@ JSBool call_ruby_from_js_va(OurContext* context, VALUE* result, VALUE self, ID i
   *result = rb_protect(call_ruby_from_js_invoke, args, &amp;state);
 
   if (state)
-    return report_ruby_error_in_js(context, state, old_errinfo);
+    return report_ruby_error_in_js(runtime, state, old_errinfo);
 
   return JS_TRUE;
 }
 
-JSBool call_ruby_from_js(OurContext* context, jsval* retval, VALUE self, ID id, int argc, ...)
+JSBool call_ruby_from_js(JohnsonRuntime* runtime, jsval* retval, VALUE self, ID id, int argc, ...)
 {
   VALUE result;
   va_list va;
   va_start(va, argc);
-  JSBool okay = call_ruby_from_js_va(context, &amp;result, self, id, argc, va);
+  JSBool okay = call_ruby_from_js_va(runtime, &amp;result, self, id, argc, va);
   va_end(va);
   if (!okay) return JS_FALSE;
-  return retval ? convert_to_js(context, result, retval) : JS_TRUE;
+  return retval ? convert_to_js(runtime, result, retval) : JS_TRUE;
 }
 
-JSBool call_ruby_from_js2(OurContext* context, VALUE* retval, VALUE self, ID id, int argc, ...)
+JSBool call_ruby_from_js2(JohnsonRuntime* runtime, VALUE* retval, VALUE self, ID id, int argc, ...)
 {
   va_list va;
   va_start(va, argc);
-  JSBool okay = call_ruby_from_js_va(context, retval, self, id, argc, va);
+  JSBool okay = call_ruby_from_js_va(runtime, retval, self, id, argc, va);
   va_end(va);
   return okay;
 }
@@ -163,8 +163,8 @@ static bool respond_to_p(JSContext* js_context, JSObject* obj, char* name)
 {
   VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);
 
-  OurContext* context;
-  Data_Get_Struct(ruby_context, OurContext, context);
+  JohnsonContext* context;
+  Data_Get_Struct(ruby_context, JohnsonContext, context);
 
   VALUE self = (VALUE)JS_GetInstancePrivate(
     context-&gt;js, obj, JS_GET_CLASS(context-&gt;js, obj), NULL);
@@ -179,8 +179,9 @@ static bool respond_to_p(JSContext* js_context, JSObject* obj, char* name)
     || has_key_p(self, name);
 }
 
-static jsval evaluate_js_property_expression(OurContext * context, const char * property, jsval* retval) {
-  return JS_EvaluateScript(context-&gt;js, context-&gt;global,
+static jsval evaluate_js_property_expression(JohnsonRuntime * runtime, const char * property, jsval* retval) {
+  JSContext * context = johnson_get_current_context(runtime);
+  return JS_EvaluateScript(context, runtime-&gt;global,
       property, strlen(property), &quot;johnson:evaluate_js_property_expression&quot;, 1,
       retval);
 }
@@ -193,10 +194,14 @@ static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
   
   // get our struct, which is embedded in ruby_context
   
-  OurContext* context;
-  Data_Get_Struct(ruby_context, OurContext, context);
+  JohnsonContext* context;
+  JohnsonRuntime* runtime;
+  Data_Get_Struct(ruby_context, JohnsonContext, context);
 
-  PREPARE_JROOTS(context, 1);
+  VALUE ruby_runtime = (VALUE)JS_GetRuntimePrivate(JS_GetRuntime(js_context));
+  Data_Get_Struct(ruby_runtime, JohnsonRuntime, runtime);
+
+  PREPARE_JROOTS(js_context, 1);
   JROOT(id);
     
   // get the Ruby object that backs this proxy
@@ -209,7 +214,7 @@ static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
   {
     if (indexable_p(self)) {
       VALUE idx = INT2FIX(JSVAL_TO_INT(id));
-      JCHECK(call_ruby_from_js(context, retval, self, rb_intern(&quot;[]&quot;), 1, idx));
+      JCHECK(call_ruby_from_js(runtime, retval, self, rb_intern(&quot;[]&quot;), 1, idx));
     }
     
     JRETURN;
@@ -221,7 +226,7 @@ static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
   // FIXME: we should probably just JS_DefineProperty this, and it shouldn't be enumerable
   
   if (!strcasecmp(&quot;__iterator__&quot;, name)) {
-    JCHECK(evaluate_js_property_expression(context, &quot;Johnson.Generator.create&quot;, retval));
+    JCHECK(evaluate_js_property_expression(runtime, &quot;Johnson.Generator.create&quot;, retval));
   }
   
   // if the Ruby object has a dynamic js property with a key
@@ -230,7 +235,7 @@ static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
   
   else if (autovivified_p(ruby_context, self, name))
   {
-    JCHECK(call_ruby_from_js(context, retval, Johnson_SpiderMonkey_JSLandProxy(),
+    JCHECK(call_ruby_from_js(runtime, retval, Johnson_SpiderMonkey_JSLandProxy(),
       rb_intern(&quot;autovivified&quot;), 2, self, rb_str_new2(name)));
   }
 
@@ -239,14 +244,14 @@ static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
   
   else if (const_p(self, name))
   {
-    JCHECK(call_ruby_from_js(context, retval, self, rb_intern(&quot;const_get&quot;),
+    JCHECK(call_ruby_from_js(runtime, retval, self, rb_intern(&quot;const_get&quot;),
       1, ID2SYM(ruby_id)));
   }  
 
   // otherwise, if it's a global, return the global
   else if (global_p(name))
   {
-    JCHECK(convert_to_js(context, rb_gv_get(name), retval));
+    JCHECK(convert_to_js(runtime, rb_gv_get(name), retval));
   }
   
   // otherwise, if the Ruby object has a an attribute method matching
@@ -254,7 +259,7 @@ static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
   
   else if (attribute_p(self, name))
   {
-    JCHECK(call_ruby_from_js(context, retval, self, ruby_id, 0));
+    JCHECK(call_ruby_from_js(runtime, retval, self, ruby_id, 0));
   }
 
   // otherwise, if the Ruby object quacks sorta like a hash (it responds to
@@ -262,7 +267,7 @@ static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
   
   else if (has_key_p(self, name))
   {
-    JCHECK(call_ruby_from_js(context, retval, self, rb_intern(&quot;[]&quot;), 1, rb_str_new2(name)));
+    JCHECK(call_ruby_from_js(runtime, retval, self, rb_intern(&quot;[]&quot;), 1, rb_str_new2(name)));
   }
   
   // otherwise, it's a method being accessed as a property, which means
@@ -273,7 +278,7 @@ static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
   
   else if (method_p(self, name))
   {
-    JCHECK(call_ruby_from_js(context, retval, self, rb_intern(&quot;method&quot;), 1, rb_str_new2(name)));
+    JCHECK(call_ruby_from_js(runtime, retval, self, rb_intern(&quot;method&quot;), 1, rb_str_new2(name)));
   }
 
   // else it's undefined (JS_VOID) by default
@@ -284,7 +289,7 @@ static JSBool get(JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
 static JSBool get_and_destroy_resolved_property(
   JSContext* js_context, JSObject* obj, jsval id, jsval* retval)
 {
-  PREPARE_JROOTS(OUR_CONTEXT(js_context), 1);
+  PREPARE_JROOTS(js_context, 1);
   JROOT(id);
   char* name = JS_GetStringBytes(JSVAL_TO_STRING(id));
   JCHECK(JS_DeleteProperty(js_context, obj, name));
@@ -296,10 +301,14 @@ static JSBool set(JSContext* js_context, JSObject* obj, jsval id, jsval* value)
 {
   VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);
   
-  OurContext* context;
-  Data_Get_Struct(ruby_context, OurContext, context);
+  JohnsonContext* context;
+  JohnsonRuntime* runtime;
+  Data_Get_Struct(ruby_context, JohnsonContext, context);
+
+  VALUE ruby_runtime = (VALUE)JS_GetRuntimePrivate(JS_GetRuntime(js_context));
+  Data_Get_Struct(ruby_runtime, JohnsonRuntime, runtime);
 
-  PREPARE_JROOTS(context, 2);
+  PREPARE_JROOTS(js_context, 2);
   JROOT(id);
   JROOT_PTR(value);
     
@@ -312,46 +321,46 @@ static JSBool set(JSContext* js_context, JSObject* obj, jsval id, jsval* value)
     if (indexable_p(self))
     {
       VALUE idx = INT2FIX(JSVAL_TO_INT(id));
-      VALUE val = CONVERT_TO_RUBY(context, *value);
+      VALUE val = CONVERT_TO_RUBY(runtime, *value);
 
-      JCHECK(call_ruby_from_js(context, NULL, self, rb_intern(&quot;[]=&quot;), 2, idx, val));
+      JCHECK(call_ruby_from_js(runtime, NULL, self, rb_intern(&quot;[]=&quot;), 2, idx, val));
     }
 
     JRETURN;
   }
   
-  VALUE ruby_key = CONVERT_TO_RUBY(context, id);
-  VALUE ruby_value = CONVERT_TO_RUBY(context, *value);
+  VALUE ruby_key = CONVERT_TO_RUBY(runtime, id);
+  VALUE ruby_value = CONVERT_TO_RUBY(runtime, *value);
 
   VALUE setter = rb_str_append(rb_str_new3(ruby_key), rb_str_new2(&quot;=&quot;));
   VALUE setter_id = rb_intern(StringValueCStr(setter));
   
   VALUE settable_p, indexable_p;
-  JCHECK(call_ruby_from_js2(context, &amp;settable_p, self, rb_intern(&quot;respond_to?&quot;), 1, ID2SYM(setter_id)));
-  JCHECK(call_ruby_from_js2(context, &amp;indexable_p, self, rb_intern(&quot;respond_to?&quot;), 1, ID2SYM(rb_intern(&quot;[]=&quot;))));
+  JCHECK(call_ruby_from_js2(runtime, &amp;settable_p, self, rb_intern(&quot;respond_to?&quot;), 1, ID2SYM(setter_id)));
+  JCHECK(call_ruby_from_js2(runtime, &amp;indexable_p, self, rb_intern(&quot;respond_to?&quot;), 1, ID2SYM(rb_intern(&quot;[]=&quot;))));
   
   if (settable_p)
   {
     VALUE method, arity;
-    JCHECK(call_ruby_from_js2(context, &amp;method, self, rb_intern(&quot;method&quot;), 1, ID2SYM(setter_id)));
-    JCHECK(call_ruby_from_js2(context, &amp;arity, method, rb_intern(&quot;arity&quot;), 0));
+    JCHECK(call_ruby_from_js2(runtime, &amp;method, self, rb_intern(&quot;method&quot;), 1, ID2SYM(setter_id)));
+    JCHECK(call_ruby_from_js2(runtime, &amp;arity, method, rb_intern(&quot;arity&quot;), 0));
 
     // if the Ruby object has a 1-arity method named &quot;property=&quot;,
     // call it with the converted value
     
     if (NUM2INT(arity) == 1)
-      JCHECK(call_ruby_from_js(context, NULL, self, setter_id, 1, ruby_value));
+      JCHECK(call_ruby_from_js(runtime, NULL, self, setter_id, 1, ruby_value));
   }
   else if(indexable_p)
   {
     // otherwise, if the Ruby object quacks sorta like a hash for assignment
     // (it responds to &quot;[]=&quot;), assign it by key
     
-    JCHECK(call_ruby_from_js(context, NULL, self, rb_intern(&quot;[]=&quot;), 2, ruby_key, ruby_value));
+    JCHECK(call_ruby_from_js(runtime, NULL, self, rb_intern(&quot;[]=&quot;), 2, ruby_key, ruby_value));
   }
   else
   {
-    JCHECK(call_ruby_from_js(context, NULL, Johnson_SpiderMonkey_JSLandProxy(), rb_intern(&quot;autovivify&quot;), 
+    JCHECK(call_ruby_from_js(runtime, NULL, Johnson_SpiderMonkey_JSLandProxy(), rb_intern(&quot;autovivify&quot;), 
       3, self, ruby_key, ruby_value));
   }
 
@@ -362,19 +371,23 @@ static JSBool construct(JSContext* js_context, JSObject* UNUSED(obj), uintN argc
 {
   VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);
   
-  OurContext* context;
-  Data_Get_Struct(ruby_context, OurContext, context);
+  JohnsonContext* context;
+  JohnsonRuntime* runtime;
+  Data_Get_Struct(ruby_context, JohnsonContext, context);
 
-  PREPARE_JROOTS(context, 0);
+  VALUE ruby_runtime = (VALUE)JS_GetRuntimePrivate(JS_GetRuntime(js_context));
+  Data_Get_Struct(ruby_runtime, JohnsonRuntime, runtime);
 
-  VALUE klass = CONVERT_TO_RUBY(context, JS_ARGV_CALLEE(argv));
+  PREPARE_JROOTS(js_context, 0);
+
+  VALUE klass = CONVERT_TO_RUBY(runtime, JS_ARGV_CALLEE(argv));
   VALUE args = rb_ary_new();
 
   uintN i;
   for (i = 0; i &lt; argc; ++i)
-    rb_ary_push(args, CONVERT_TO_RUBY(context, argv[i]));
+    rb_ary_push(args, CONVERT_TO_RUBY(runtime, argv[i]));
     
-  JCHECK(call_ruby_from_js(context, retval, Johnson_SpiderMonkey_JSLandProxy(),
+  JCHECK(call_ruby_from_js(runtime, retval, Johnson_SpiderMonkey_JSLandProxy(),
     rb_intern(&quot;send_with_possible_block&quot;), 3, klass, ID2SYM(rb_intern(&quot;new&quot;)), args));
   JRETURN;
 }
@@ -383,10 +396,10 @@ static JSBool resolve(JSContext *js_context, JSObject *obj, jsval id, uintN UNUS
 {
   VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);
   
-  OurContext* context;
-  Data_Get_Struct(ruby_context, OurContext, context);
+  JohnsonContext* context;
+  Data_Get_Struct(ruby_context, JohnsonContext, context);
 
-  PREPARE_JROOTS(context, 1);
+  PREPARE_JROOTS(js_context, 1);
   JROOT(id);
   
   char* name = JS_GetStringBytes(JS_ValueToString(js_context, id));
@@ -406,14 +419,18 @@ static JSBool to_string(JSContext* js_context, JSObject* obj, uintN UNUSED(argc)
 {
   VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);
 
-  OurContext* context;
-  Data_Get_Struct(ruby_context, OurContext, context);
+  JohnsonContext* context;
+  JohnsonRuntime* runtime;
+  Data_Get_Struct(ruby_context, JohnsonContext, context);
+
+  VALUE ruby_runtime = (VALUE)JS_GetRuntimePrivate(JS_GetRuntime(js_context));
+  Data_Get_Struct(ruby_runtime, JohnsonRuntime, runtime);
 
-  PREPARE_JROOTS(context, 0);
+  PREPARE_JROOTS(js_context, 0);
 
   VALUE self = (VALUE)JS_GetInstancePrivate(context-&gt;js, obj, JS_GET_CLASS(context-&gt;js, obj), NULL);
 
-  JCHECK(call_ruby_from_js(context, retval, self, rb_intern(&quot;to_s&quot;), 0));
+  JCHECK(call_ruby_from_js(runtime, retval, self, rb_intern(&quot;to_s&quot;), 0));
   JRETURN;
 }
 
@@ -421,14 +438,18 @@ static JSBool to_array(JSContext* js_context, JSObject* obj, uintN UNUSED(argc),
 {
   VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);
 
-  OurContext* context;
-  Data_Get_Struct(ruby_context, OurContext, context);
+  JohnsonContext* context;
+  JohnsonRuntime* runtime;
+  Data_Get_Struct(ruby_context, JohnsonContext, context);
 
-  PREPARE_JROOTS(context, 0);
+  VALUE ruby_runtime = (VALUE)JS_GetRuntimePrivate(JS_GetRuntime(js_context));
+  Data_Get_Struct(ruby_runtime, JohnsonRuntime, runtime);
+
+  PREPARE_JROOTS(js_context, 0);
 
   VALUE self = (VALUE)JS_GetInstancePrivate(context-&gt;js, obj, JS_GET_CLASS(context-&gt;js, obj), NULL);
 
-  JCHECK(call_ruby_from_js(context, retval, self, rb_intern(&quot;to_a&quot;), 0));
+  JCHECK(call_ruby_from_js(runtime, retval, self, rb_intern(&quot;to_a&quot;), 0));
   JRETURN;
 }
 
@@ -436,10 +457,14 @@ static JSBool method_missing(JSContext* js_context, JSObject* obj, uintN argc, j
 {
   VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);
   
-  OurContext* context;
-  Data_Get_Struct(ruby_context, OurContext, context);
+  JohnsonContext* context;
+  JohnsonRuntime* runtime;
+  Data_Get_Struct(ruby_context, JohnsonContext, context);
+
+  VALUE ruby_runtime = (VALUE)JS_GetRuntimePrivate(JS_GetRuntime(js_context));
+  Data_Get_Struct(ruby_runtime, JohnsonRuntime, runtime);
 
-  PREPARE_JROOTS(context, 0);
+  PREPARE_JROOTS(js_context, 0);
     
   VALUE self = (VALUE)JS_GetInstancePrivate(context-&gt;js, obj, JS_GET_CLASS(context-&gt;js, obj), NULL);
   
@@ -450,9 +475,9 @@ static JSBool method_missing(JSContext* js_context, JSObject* obj, uintN argc, j
   
   // FIXME: this is horrible and lazy, to_a comes from enumerable on proxy (argv[1] is a JSArray)
   VALUE args;
-  JCHECK(call_ruby_from_js2(context, &amp;args, CONVERT_TO_RUBY(context, argv[1]), rb_intern(&quot;to_a&quot;), 0));
+  JCHECK(call_ruby_from_js2(runtime, &amp;args, CONVERT_TO_RUBY(runtime, argv[1]), rb_intern(&quot;to_a&quot;), 0));
 
-  JCHECK(call_ruby_from_js(context, retval, Johnson_SpiderMonkey_JSLandProxy(),
+  JCHECK(call_ruby_from_js(runtime, retval, Johnson_SpiderMonkey_JSLandProxy(),
     rb_intern(&quot;send_with_possible_block&quot;), 3, self, ID2SYM(ruby_id), args));
 
   JRETURN;
@@ -462,10 +487,14 @@ static JSBool call(JSContext* js_context, JSObject* UNUSED(obj), uintN argc, jsv
 {
   VALUE ruby_context = (VALUE)JS_GetContextPrivate(js_context);
   
-  OurContext* context;
-  Data_Get_Struct(ruby_context, OurContext, context);
+  JohnsonContext* context;
+  JohnsonRuntime* runtime;
+  Data_Get_Struct(ruby_context, JohnsonContext, context);
 
-  PREPARE_JROOTS(context, 0);
+  VALUE ruby_runtime = (VALUE)JS_GetRuntimePrivate(JS_GetRuntime(js_context));
+  Data_Get_Struct(ruby_runtime, JohnsonRuntime, runtime);
+
+  PREPARE_JROOTS(js_context, 0);
   
   VALUE self = (VALUE)JS_GetInstancePrivate(context-&gt;js, JSVAL_TO_OBJECT(JS_ARGV_CALLEE(argv)), &amp;JSLandCallableProxyClass, NULL);
   
@@ -473,29 +502,32 @@ static JSBool call(JSContext* js_context, JSObject* UNUSED(obj), uintN argc, jsv
 
   uintN i;
   for (i = 0; i &lt; argc; ++i)
-    rb_ary_push(args, CONVERT_TO_RUBY(context, argv[i]));
+    rb_ary_push(args, CONVERT_TO_RUBY(runtime, argv[i]));
   
-  JCHECK(call_ruby_from_js(context, retval, Johnson_SpiderMonkey_JSLandProxy(),
+  JCHECK(call_ruby_from_js(runtime, retval, Johnson_SpiderMonkey_JSLandProxy(),
     rb_intern(&quot;send_with_possible_block&quot;), 3, self, ID2SYM(rb_intern(&quot;call&quot;)), args));
   JRETURN;
 }
 
-bool js_value_is_proxy(OurContext* MAYBE_UNUSED(context), jsval maybe_proxy)
+bool js_value_is_proxy(JohnsonRuntime* MAYBE_UNUSED(runtime), jsval maybe_proxy)
 {
-  JSClass* klass = JS_GET_CLASS(context-&gt;js, JSVAL_TO_OBJECT(maybe_proxy));  
+  JSClass* klass = JS_GET_CLASS(
+      johnson_get_current_context(runtime),
+      JSVAL_TO_OBJECT(maybe_proxy));  
   
   return &amp;JSLandProxyClass == klass
     || &amp;JSLandClassProxyClass == klass
     || &amp;JSLandCallableProxyClass == klass;
 }
 
-VALUE unwrap_js_land_proxy(OurContext* context, jsval proxy)
+VALUE unwrap_js_land_proxy(JohnsonRuntime* runtime, jsval proxy)
 {
   VALUE value;
   JSObject *proxy_object = JSVAL_TO_OBJECT(proxy);
+  JSContext * context = johnson_get_current_context(runtime);
   
-  value = (VALUE)JS_GetInstancePrivate(context-&gt;js, proxy_object,
-          JS_GET_CLASS(context-&gt;js, proxy_object), NULL);
+  value = (VALUE)JS_GetInstancePrivate(context, proxy_object,
+          JS_GET_CLASS(context, proxy_object), NULL);
   
   return value;
 }
@@ -506,27 +538,32 @@ static void finalize(JSContext* js_context, JSObject* obj)
   
   if (ruby_context)
   {
-    OurContext* context;
-    Data_Get_Struct(ruby_context, OurContext, context);
+    JohnsonContext* context;
+    JohnsonRuntime* runtime;
+    Data_Get_Struct(ruby_context, JohnsonContext, context);
+
+    VALUE ruby_runtime = (VALUE)JS_GetRuntimePrivate(JS_GetRuntime(js_context));
+    Data_Get_Struct(ruby_runtime, JohnsonRuntime, runtime);
     
     VALUE self = (VALUE)JS_GetInstancePrivate(context-&gt;js, obj,
             JS_GET_CLASS(context-&gt;js, obj), NULL);
     
     // remove the proxy OID from the id map
-    JS_HashTableRemove(context-&gt;rbids, (void *)rb_obj_id(self));
+    JS_HashTableRemove(runtime-&gt;rbids, (void *)rb_obj_id(self));
     
     // free up the ruby value for GC
-    call_ruby_from_js(context, NULL, ruby_context, rb_intern(&quot;remove_gcthing&quot;), 1, self);
+    call_ruby_from_js(runtime, NULL, ruby_context, rb_intern(&quot;remove_gcthing&quot;), 1, self);
   }  
 }
 
-JSBool make_js_land_proxy(OurContext* context, VALUE value, jsval* retval)
+JSBool make_js_land_proxy(JohnsonRuntime* runtime, VALUE value, jsval* retval)
 {
-  jsid id = (jsid)JS_HashTableLookup(context-&gt;rbids, (void *)rb_obj_id(value));
+  JSContext * context = johnson_get_current_context(runtime);
+  jsid id = (jsid)JS_HashTableLookup(runtime-&gt;rbids, (void *)rb_obj_id(value));
   
   if (id)
   {
-    return JS_IdToValue(context-&gt;js, id, retval);
+    return JS_IdToValue(context, id, retval);
   }
   else
   {
@@ -548,26 +585,26 @@ JSBool make_js_land_proxy(OurContext* context, VALUE value, jsval* retval)
     if (callable_p)
       klass = &amp;JSLandCallableProxyClass;
         
-    JCHECK((jsobj = JS_NewObject(context-&gt;js, klass, NULL, NULL)));
+    JCHECK((jsobj = JS_NewObject(context, klass, NULL, NULL)));
     JROOT(jsobj);
     
-    JCHECK(JS_SetPrivate(context-&gt;js, jsobj, (void*)value));
+    JCHECK(JS_SetPrivate(context, jsobj, (void*)value));
 
-    JCHECK(JS_DefineFunction(context-&gt;js, jsobj, &quot;__noSuchMethod__&quot;, method_missing, 2, 0));
+    JCHECK(JS_DefineFunction(context, jsobj, &quot;__noSuchMethod__&quot;, method_missing, 2, 0));
 
-    JCHECK(JS_DefineFunction(context-&gt;js, jsobj, &quot;toArray&quot;, to_array, 0, 0));
-    JCHECK(JS_DefineFunction(context-&gt;js, jsobj, &quot;toString&quot;, to_string, 0, 0));
+    JCHECK(JS_DefineFunction(context, jsobj, &quot;toArray&quot;, to_array, 0, 0));
+    JCHECK(JS_DefineFunction(context, jsobj, &quot;toString&quot;, to_string, 0, 0));
 
     *retval = OBJECT_TO_JSVAL(jsobj);
 
     jsval newid;
-    JCHECK(JS_ValueToId(context-&gt;js, *retval, &amp;newid));
+    JCHECK(JS_ValueToId(context, *retval, &amp;newid));
   
     // put the proxy OID in the id map
-    JCHECK(JS_HashTableAdd(context-&gt;rbids, (void *)rb_obj_id(value), (void *)newid));
+    JCHECK(JS_HashTableAdd(runtime-&gt;rbids, (void *)rb_obj_id(value), (void *)newid));
     
     // root the ruby value for GC
-    VALUE ruby_context = (VALUE)JS_GetContextPrivate(context-&gt;js);
+    VALUE ruby_context = (VALUE)JS_GetContextPrivate(context);
     rb_funcall(ruby_context, rb_intern(&quot;add_gcthing&quot;), 1, value);
 
     JRETURN;</diff>
      <filename>ext/spidermonkey/js_land_proxy.c</filename>
    </modified>
    <modified>
      <diff>@@ -2,11 +2,11 @@
 #define JOHNSON_SPIDERMONKEY_JS_LAND_PROXY_H
 
 #include &quot;spidermonkey.h&quot;
-#include &quot;context.h&quot;
+#include &quot;runtime.h&quot;
 
-bool js_value_is_proxy(OurContext* context, jsval maybe_proxy);
-VALUE unwrap_js_land_proxy(OurContext* context, jsval proxy);
-JSBool make_js_land_proxy(OurContext* context, VALUE value, jsval* retval);
+bool js_value_is_proxy(JohnsonRuntime* runtime, jsval maybe_proxy);
+VALUE unwrap_js_land_proxy(JohnsonRuntime* runtime, jsval proxy);
+JSBool make_js_land_proxy(JohnsonRuntime* runtime, VALUE value, jsval* retval);
 
 #include &quot;node.h&quot;
 typedef struct {</diff>
      <filename>ext/spidermonkey/js_land_proxy.h</filename>
    </modified>
    <modified>
      <diff>@@ -12,24 +12,26 @@ static VALUE proxy_class = Qnil;
 
 static JSBool get_jsval_for_proxy(RubyLandProxy* proxy, jsval* jv)
 {
-  PREPARE_JROOTS(proxy-&gt;context, 0);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
+  PREPARE_JROOTS(context, 0);
 
   // FIXME: this is totally lame
   char global_key[10];
-  sprintf(global_key, &quot;%x&quot;, (int)proxy-&gt;context-&gt;global);
+  sprintf(global_key, &quot;%x&quot;, (int)proxy-&gt;runtime-&gt;global);
   
   if (0 == strcmp(global_key, proxy-&gt;key))
   {
-    *jv = OBJECT_TO_JSVAL(proxy-&gt;context-&gt;global);
+    *jv = OBJECT_TO_JSVAL(proxy-&gt;runtime-&gt;global);
     JRETURN;
   }
   
-  JCHECK(JS_GetProperty(proxy-&gt;context-&gt;js, proxy-&gt;context-&gt;gcthings, proxy-&gt;key, jv));
+  JCHECK(JS_GetProperty(context, proxy-&gt;runtime-&gt;gcthings, proxy-&gt;key, jv));
   JRETURN;
 }
 
-static VALUE call_js_function_value(OurContext* context, jsval target, jsval function, int argc, VALUE* argv)
+static VALUE call_js_function_value(JohnsonRuntime* runtime, jsval target, jsval function, int argc, VALUE* argv)
 {
+  JSContext * context = johnson_get_current_context(runtime);
   PREPARE_RUBY_JROOTS(context, argc + 2);
 
   JROOT(target);
@@ -43,14 +45,14 @@ static VALUE call_js_function_value(OurContext* context, jsval target, jsval fun
   int i;
   for(i = 0; i &lt; argc; ++i)
   {
-    JCHECK(convert_to_js(context, argv[i], &amp;(args[i])));
+    JCHECK(convert_to_js(runtime, argv[i], &amp;(args[i])));
     JROOT(args[i]);
   }
 
-  JCHECK(JS_CallFunctionValue(context-&gt;js,
+  JCHECK(JS_CallFunctionValue(context,
     JSVAL_TO_OBJECT(target), function, (unsigned) argc, args, &amp;result));
 
-  JRETURN_RUBY(CONVERT_TO_RUBY(context, result));
+  JRETURN_RUBY(CONVERT_TO_RUBY(runtime, result));
 }
 
 /*
@@ -65,7 +67,8 @@ get(VALUE self, VALUE name)
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
 
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 1);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
+  PREPARE_RUBY_JROOTS(context, 1);
   
   jsval proxy_value;
   JCHECK(get_jsval_for_proxy(proxy, &amp;proxy_value));
@@ -75,17 +78,17 @@ get(VALUE self, VALUE name)
 
   switch(TYPE(name)) {
     case T_FIXNUM:
-      JCHECK(JS_GetElement(proxy-&gt;context-&gt;js,
+      JCHECK(JS_GetElement(context,
           JSVAL_TO_OBJECT(proxy_value), NUM2INT(name), &amp;js_value));
       break;
     default:
       Check_Type(name, T_STRING);
-      JCHECK(JS_GetProperty(proxy-&gt;context-&gt;js,
+      JCHECK(JS_GetProperty(context,
           JSVAL_TO_OBJECT(proxy_value), StringValueCStr(name), &amp;js_value));
       break;
   }
 
-  JRETURN_RUBY(CONVERT_TO_RUBY(proxy-&gt;context, js_value));
+  JRETURN_RUBY(CONVERT_TO_RUBY(proxy-&gt;runtime, js_value));
 }
 
 /*
@@ -99,26 +102,27 @@ set(VALUE self, VALUE name, VALUE value)
 {
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
   
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 2);
+  PREPARE_RUBY_JROOTS(context, 2);
   
   jsval proxy_value;
   JCHECK(get_jsval_for_proxy(proxy, &amp;proxy_value));
   JROOT(proxy_value);
 
   jsval js_value;
-  JCHECK(convert_to_js(proxy-&gt;context, value, &amp;js_value));
+  JCHECK(convert_to_js(proxy-&gt;runtime, value, &amp;js_value));
   
   JROOT(js_value);
 
   switch(TYPE(name)) {
     case T_FIXNUM:
-      JCHECK(JS_SetElement(proxy-&gt;context-&gt;js,
+      JCHECK(JS_SetElement(context,
               JSVAL_TO_OBJECT(proxy_value), NUM2INT(name), &amp;js_value));
       break;
     default:
       Check_Type(name, T_STRING);
-      JCHECK(JS_SetProperty(proxy-&gt;context-&gt;js,
+      JCHECK(JS_SetProperty(context,
             JSVAL_TO_OBJECT(proxy_value), StringValueCStr(name), &amp;js_value));
       break;
   }
@@ -137,10 +141,11 @@ function_p(VALUE self)
 {
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 0);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
+  PREPARE_RUBY_JROOTS(context, 0);
   jsval proxy_value;
   JCHECK(get_jsval_for_proxy(proxy, &amp;proxy_value));
-  JRETURN_RUBY(JS_TypeOfValue(proxy-&gt;context-&gt;js, proxy_value) == JSTYPE_FUNCTION ? Qtrue : Qfalse);
+  JRETURN_RUBY(JS_TypeOfValue(context, proxy_value) == JSTYPE_FUNCTION ? Qtrue : Qfalse);
 }
 
 /*
@@ -155,7 +160,8 @@ respond_to_p(VALUE self, VALUE sym)
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
 
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 2);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
+  PREPARE_RUBY_JROOTS(context, 2);
   
   char* name = rb_id2name(SYM2ID(sym));
   
@@ -170,10 +176,10 @@ respond_to_p(VALUE self, VALUE sym)
   JSObject *obj;
   JSBool found;
   
-  JCHECK(JS_ValueToObject(proxy-&gt;context-&gt;js, proxy_value, &amp;obj));
+  JCHECK(JS_ValueToObject(context, proxy_value, &amp;obj));
   JROOT(obj);
 
-  JCHECK(JS_HasProperty(proxy-&gt;context-&gt;js, obj, name, &amp;found));
+  JCHECK(JS_HasProperty(context, obj, name, &amp;found));
 
   JRETURN_RUBY(found ? Qtrue : CALL_RUBY_WRAPPER(rb_call_super, 1, &amp;sym));
 }
@@ -195,23 +201,24 @@ native_call(int argc, VALUE* argv, VALUE self)
 
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
   
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 1);
+  PREPARE_RUBY_JROOTS(context, 1);
   
   jsval proxy_value;
   JCHECK(get_jsval_for_proxy(proxy, &amp;proxy_value));
   JROOT(proxy_value);
 
   jsval global;
-  JCHECK(convert_to_js(proxy-&gt;context, argv[0], &amp;global));
+  JCHECK(convert_to_js(proxy-&gt;runtime, argv[0], &amp;global));
 
-  JRETURN_RUBY(call_js_function_value(proxy-&gt;context, global, proxy_value, argc - 1, &amp;(argv[1])));
+  JRETURN_RUBY(call_js_function_value(proxy-&gt;runtime, global, proxy_value, argc - 1, &amp;(argv[1])));
 }
 
 static void
-destroy_id_array(OurContext* context, void* data)
+destroy_id_array(JSContext* context, void* data)
 {
-  JS_DestroyIdArray(context-&gt;js, (JSIdArray*)data);
+  JS_DestroyIdArray(context, (JSIdArray*)data);
 }
 
 /*
@@ -225,8 +232,9 @@ each(VALUE self)
 {
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
   
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 5);
+  PREPARE_RUBY_JROOTS(context, 5);
   
   jsval proxy_value;
   JCHECK(get_jsval_for_proxy(proxy, &amp;proxy_value));
@@ -236,23 +244,23 @@ each(VALUE self)
   JROOT(value);
   
   // arrays behave like you'd expect, indexes in order
-  if (JS_IsArrayObject(proxy-&gt;context-&gt;js, value))
+  if (JS_IsArrayObject(context, value))
   {
     jsuint length;
-    JCHECK(JS_GetArrayLength(proxy-&gt;context-&gt;js, value, &amp;length));
+    JCHECK(JS_GetArrayLength(context, value, &amp;length));
     
     jsuint i = 0;
     for (i = 0; i &lt; length; ++i)
     {
       jsval element;
-      JCHECK(JS_GetElement(proxy-&gt;context-&gt;js, value, (signed) i, &amp;element));
-      CALL_RUBY_WRAPPER(rb_yield, convert_to_ruby(proxy-&gt;context, element));
+      JCHECK(JS_GetElement(context, value, (signed) i, &amp;element));
+      CALL_RUBY_WRAPPER(rb_yield, convert_to_ruby(proxy-&gt;runtime, element));
     }
   }
   else
   {
     // not an array? behave like each on Hash; yield [key, value]
-    JSIdArray* ids = JS_Enumerate(proxy-&gt;context-&gt;js, value);
+    JSIdArray* ids = JS_Enumerate(context, value);
     JCHECK(ids);
 
     JCLEANUP(destroy_id_array, ids);
@@ -262,25 +270,25 @@ each(VALUE self)
     {
       jsval js_key, js_value;
 
-      JCHECK(JS_IdToValue(proxy-&gt;context-&gt;js, ids-&gt;vector[i], &amp;js_key));
+      JCHECK(JS_IdToValue(context, ids-&gt;vector[i], &amp;js_key));
       JROOT(js_key);
 
       if (JSVAL_IS_STRING(js_key))
       {
         // regular properties have string keys
-        JCHECK(JS_GetProperty(proxy-&gt;context-&gt;js, value,
+        JCHECK(JS_GetProperty(context, value,
           JS_GetStringBytes(JSVAL_TO_STRING(js_key)), &amp;js_value));
       }
       else
       {
         // it's a numeric property, use array access
-        JCHECK(JS_GetElement(proxy-&gt;context-&gt;js, value,
+        JCHECK(JS_GetElement(context, value,
           JSVAL_TO_INT(js_key), &amp;js_value));
       }
       JROOT(js_value);
 
-      VALUE key = CONVERT_TO_RUBY(proxy-&gt;context, js_key);
-      VALUE value = CONVERT_TO_RUBY(proxy-&gt;context, js_value);
+      VALUE key = CONVERT_TO_RUBY(proxy-&gt;runtime, js_key);
+      VALUE value = CONVERT_TO_RUBY(proxy-&gt;runtime, js_value);
 
       CALL_RUBY_WRAPPER(rb_yield, rb_ary_new3(2, key, value));
 
@@ -303,8 +311,9 @@ length(VALUE self)
 {
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
 
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 2);
+  PREPARE_RUBY_JROOTS(context, 2);
   
   jsval proxy_value;
   JCHECK(get_jsval_for_proxy(proxy, &amp;proxy_value));
@@ -313,20 +322,20 @@ length(VALUE self)
   JSObject* value = JSVAL_TO_OBJECT(proxy_value);
   JROOT(value);
   
-  if (JS_IsArrayObject(proxy-&gt;context-&gt;js, value))
+  if (JS_IsArrayObject(context, value))
   {
     jsuint length;
-    JCHECK(JS_GetArrayLength(proxy-&gt;context-&gt;js, value, &amp;length));
+    JCHECK(JS_GetArrayLength(context, value, &amp;length));
 
     JRETURN_RUBY(INT2FIX(length));
   }
   else
   {
-    JSIdArray* ids = JS_Enumerate(proxy-&gt;context-&gt;js, value);
+    JSIdArray* ids = JS_Enumerate(context, value);
     JCHECK(ids);
     VALUE length = INT2FIX(ids-&gt;length);
     
-    JS_DestroyIdArray(proxy-&gt;context-&gt;js, ids);
+    JS_DestroyIdArray(context, ids);
 
     JRETURN_RUBY(length);
   }
@@ -334,16 +343,16 @@ length(VALUE self)
 
 /*
  * call-seq:
- *   context
+ *   runtime
  *
- * Returns context.
+ * Returns runtime.
  */
 static VALUE
-context(VALUE self)
+runtime(VALUE self)
 {
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
-  return (VALUE)JS_GetContextPrivate(proxy-&gt;context-&gt;js);
+  return (VALUE)JS_GetRuntimePrivate(proxy-&gt;runtime-&gt;js);
 }
 
 /*
@@ -359,8 +368,9 @@ function_property_p(VALUE self, VALUE name)
   
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
 
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 2);
+  PREPARE_RUBY_JROOTS(context, 2);
 
   jsval proxy_value;
   JCHECK(get_jsval_for_proxy(proxy, &amp;proxy_value));
@@ -368,12 +378,12 @@ function_property_p(VALUE self, VALUE name)
 
   jsval js_value;  
 
-  JCHECK(JS_GetProperty(proxy-&gt;context-&gt;js,
+  JCHECK(JS_GetProperty(context,
       JSVAL_TO_OBJECT(proxy_value), StringValueCStr(name), &amp;js_value));
 
   JROOT(js_value);
 
-  JSType type = JS_TypeOfValue(proxy-&gt;context-&gt;js, js_value);
+  JSType type = JS_TypeOfValue(context, js_value);
 
   JRETURN_RUBY(type == JSTYPE_FUNCTION ? Qtrue : Qfalse);
 }
@@ -389,11 +399,12 @@ call_function_property(int argc, VALUE* argv, VALUE self)
 {
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
 
   if (argc &lt; 1)
     rb_raise(rb_eArgError, &quot;Function name required&quot;);
 
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 2);
+  PREPARE_RUBY_JROOTS(context, 2);
   
   jsval proxy_value;
   JCHECK(get_jsval_for_proxy(proxy, &amp;proxy_value));
@@ -401,18 +412,18 @@ call_function_property(int argc, VALUE* argv, VALUE self)
 
   jsval function;
   
-  JCHECK(JS_GetProperty(proxy-&gt;context-&gt;js,
+  JCHECK(JS_GetProperty(context,
     JSVAL_TO_OBJECT(proxy_value), StringValueCStr(argv[0]), &amp;function));
 
   JROOT(function);
 
-  JSType funtype = JS_TypeOfValue(proxy-&gt;context-&gt;js, function);
+  JSType funtype = JS_TypeOfValue(context, function);
   
   // should never be anything but a function
   if (funtype != JSTYPE_FUNCTION)
     JERROR(&quot;Specified property \&quot;%s\&quot; isn't a function.&quot;, StringValueCStr(argv[0]));
 
-  JRETURN_RUBY(call_js_function_value(proxy-&gt;context, proxy_value, function, argc - 1, &amp;(argv[1])));
+  JRETURN_RUBY(call_js_function_value(proxy-&gt;runtime, proxy_value, function, argc - 1, &amp;(argv[1])));
 }
 
 /*
@@ -425,15 +436,16 @@ static VALUE to_s(VALUE self)
 {
   RubyLandProxy* proxy;
   Data_Get_Struct(self, RubyLandProxy, proxy);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
 
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 1);
+  PREPARE_RUBY_JROOTS(context, 1);
   
   jsval proxy_value;
   JCHECK(get_jsval_for_proxy(proxy, &amp;proxy_value));
   JROOT(proxy_value);
   
-  JSString* str = JS_ValueToString(proxy-&gt;context-&gt;js, proxy_value);
-  JRETURN_RUBY(convert_jsstring_to_ruby(proxy-&gt;context, str));
+  JSString* str = JS_ValueToString(context, proxy_value);
+  JRETURN_RUBY(convert_js_string_to_ruby(proxy-&gt;runtime, str));
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -442,20 +454,21 @@ static VALUE to_s(VALUE self)
 
 static void finalize(RubyLandProxy* proxy)
 {
-  PREPARE_RUBY_JROOTS(proxy-&gt;context, 0);
+  JSContext * context = johnson_get_current_context(proxy-&gt;runtime);
+  PREPARE_RUBY_JROOTS(context, 0);
   jsval proxy_value;
   JCHECK_RUBY(get_jsval_for_proxy(proxy, &amp;proxy_value));
   
   // could get finalized after the context has been freed
-  if (proxy-&gt;context &amp;&amp; proxy-&gt;context-&gt;jsids)
+  if (proxy-&gt;runtime &amp;&amp; proxy-&gt;runtime-&gt;jsids)
   {
     // remove this proxy from the OID map
-    JS_HashTableRemove(proxy-&gt;context-&gt;jsids, (void *)proxy_value);
+    JS_HashTableRemove(proxy-&gt;runtime-&gt;jsids, (void *)proxy_value);
   
     // remove our GC handle on the JS value
-    JS_DeleteProperty(proxy-&gt;context-&gt;js, proxy-&gt;context-&gt;gcthings, proxy-&gt;key);
+    JS_DeleteProperty(context, proxy-&gt;runtime-&gt;gcthings, proxy-&gt;key);
     
-    proxy-&gt;context = 0;
+    proxy-&gt;runtime = 0;
   }
   
   free(proxy);
@@ -466,8 +479,9 @@ bool ruby_value_is_proxy(VALUE maybe_proxy)
   return proxy_class == CLASS_OF(maybe_proxy); 
 }
 
-JSBool unwrap_ruby_land_proxy(OurContext* context, VALUE wrapped, jsval* retval)
+JSBool unwrap_ruby_land_proxy(JohnsonRuntime* runtime, VALUE wrapped, jsval* retval)
 {
+  JSContext * context = johnson_get_current_context(runtime);
   assert(ruby_value_is_proxy(wrapped));
   
   PREPARE_JROOTS(context, 0);
@@ -479,9 +493,10 @@ JSBool unwrap_ruby_land_proxy(OurContext* context, VALUE wrapped, jsval* retval)
   JRETURN;
 }
 
-VALUE make_ruby_land_proxy(OurContext* context, jsval value)
+VALUE make_ruby_land_proxy(JohnsonRuntime* runtime, jsval value)
 {
-  VALUE id = (VALUE)JS_HashTableLookup(context-&gt;jsids, (void *)value);
+  VALUE id = (VALUE)JS_HashTableLookup(runtime-&gt;jsids, (void *)value);
+  JSContext * context = johnson_get_current_context(runtime);
   
   if (id)
   {
@@ -501,12 +516,12 @@ VALUE make_ruby_land_proxy(OurContext* context, jsval value)
     // root the value for JS GC and lookups
     sprintf(our_proxy-&gt;key, &quot;%x&quot;, (int)value);
     
-    JCHECK(JS_SetProperty(context-&gt;js, context-&gt;gcthings, our_proxy-&gt;key, &amp;value));
+    JCHECK(JS_SetProperty(context, runtime-&gt;gcthings, our_proxy-&gt;key, &amp;value));
 
-    our_proxy-&gt;context = context;
+    our_proxy-&gt;runtime = runtime;
 
     // put the proxy OID in the id map
-    JCHECK(JS_HashTableAdd(context-&gt;jsids, (void *)value, (void *)rb_obj_id(proxy)));
+    JCHECK(JS_HashTableAdd(runtime-&gt;jsids, (void *)value, (void *)rb_obj_id(proxy)));
     
     JRETURN_RUBY(proxy);
   }
@@ -531,7 +546,7 @@ void init_Johnson_SpiderMonkey_Proxy(VALUE spidermonkey)
   rb_define_method(proxy_class, &quot;to_s&quot;, to_s, 0);
 
   rb_define_private_method(proxy_class, &quot;native_call&quot;, native_call, -1);
-  rb_define_private_method(proxy_class, &quot;context&quot;, context, 0);
+  rb_define_private_method(proxy_class, &quot;runtime&quot;, runtime, 0);
   rb_define_private_method(proxy_class, &quot;function_property?&quot;, function_property_p, 1);
   rb_define_private_method(proxy_class, &quot;call_function_property&quot;, call_function_property, -1);
 }</diff>
      <filename>ext/spidermonkey/ruby_land_proxy.c</filename>
    </modified>
    <modified>
      <diff>@@ -2,16 +2,16 @@
 #define JOHNSON_SPIDERMONKEY_RUBY_LAND_PROXY_H
 
 #include &quot;spidermonkey.h&quot;
-#include &quot;context.h&quot;
+#include &quot;runtime.h&quot;
 
 typedef struct {
   char key[10];
-  OurContext* context;
+  JohnsonRuntime* runtime;
 } RubyLandProxy;
 
 bool ruby_value_is_proxy(VALUE maybe_proxy);
-JSBool unwrap_ruby_land_proxy(OurContext* context, VALUE proxy, jsval* retval);
-VALUE make_ruby_land_proxy(OurContext* context, jsval value);
+JSBool unwrap_ruby_land_proxy(JohnsonRuntime* runtime, VALUE proxy, jsval* retval);
+VALUE make_ruby_land_proxy(JohnsonRuntime* runtime, jsval value);
 void init_Johnson_SpiderMonkey_Proxy(VALUE spidermonkey);
 
 #endif</diff>
      <filename>ext/spidermonkey/ruby_land_proxy.h</filename>
    </modified>
    <modified>
      <diff>@@ -2,47 +2,151 @@
 #include &quot;error.h&quot;
 #include &quot;global.h&quot;
 #include &quot;idhash.h&quot;
+#include &quot;conversions.h&quot;
+#include &quot;jsdbgapi.h&quot;
 
-JSContext* johnson_get_current_context(JohnsonRuntime* runtime)
+/*
+ * call-seq:
+ *   global
+ *
+ * Returns the global object used for this context.
+ */
+static VALUE global(VALUE self)
 {
-  // First, see if we already have a context for the current thread.
-  JSContext* context = (JSContext*)JS_HashTableLookup(runtime-&gt;contexts, (void*)rb_thread_current());
-  
-  // If not,
-  if (!context)
+  JohnsonRuntime* runtime;
+  Data_Get_Struct(self, JohnsonRuntime, runtime);
+  return convert_to_ruby(runtime, OBJECT_TO_JSVAL(runtime-&gt;global));
+}
+
+/*
+ * call-seq:
+ *   evaluate(script, filename=nil, linenum=nil)
+ *
+ * Evaluate +script+ with +filename+ using +linenum+
+ */
+static VALUE evaluate(int argc, VALUE* argv, VALUE self)
+{
+  VALUE script, filename, linenum;
+
+  JohnsonRuntime* runtime;
+  Data_Get_Struct(self, JohnsonRuntime, runtime);
+
+  JSContext * context = johnson_get_current_context(runtime);
+  JohnsonContext * johnson_context = OUR_CONTEXT(context);
+  rb_scan_args( argc, argv, &quot;12&quot;, &amp;script, &amp;filename, &amp;linenum );
+
+  // clean things up first
+  johnson_context-&gt;ex = 0;
+  memset(johnson_context-&gt;msg, 0, MAX_EXCEPTION_MESSAGE_SIZE);
+
+  const char* filenamez = RTEST(filename) ? StringValueCStr(filename) : &quot;none&quot;;
+  int linenumi = RTEST(linenum) ? NUM2INT(linenum) : 1;
+
+  jsval js;
+
+  // FIXME: should be able to pass in the 'file' name
+  JSBool ok = JS_EvaluateScript(context, runtime-&gt;global,
+    StringValuePtr(script), (unsigned)StringValueLen(script), filenamez, (unsigned)linenumi, &amp;js);
+
+  if (!ok)
   {
-    // try and create one.
-    if ((context = JS_NewContext(runtime-&gt;js, 8192)))
+    if (JS_IsExceptionPending(context))
     {
-      // See if the runtime already has a shared global object.
-      JSObject* global = runtime-&gt;global;
-      
-      // If it does, use it. If not,
-      if (!global)
-        // create one of our global objects.
-        global = johnson_create_global_object(context);
+      // If there's an exception pending here, it's a syntax error.
+      JS_GetPendingException(context, &amp;johnson_context-&gt;ex);
+      JS_ClearPendingException(context);
+    }
 
-      // Manually set the context's global object.
-      JS_SetGlobalObject(context, global);
-      
-      // Register this context (thread -&gt; context) for lookup next time.
-      JS_HashTableAdd(runtime-&gt;contexts, (void*)rb_thread_current(), (void*) context);
+    if (johnson_context-&gt;ex)
+    {
+      return rb_funcall(self, rb_intern(&quot;handle_js_exception&quot;),
+        1, convert_to_ruby(runtime, johnson_context-&gt;ex));
       
-      // Success.
-      return context;
+      // VALUE message, file, line, stack;
+      // 
+      // jsval js_message;
+      // assert(JS_GetProperty(context-&gt;js, JSVAL_TO_OBJECT(context-&gt;ex), &quot;message&quot;, &amp;js_message));
+      // message = convert_to_ruby(context, js_message);
+      // 
+      // jsval js_file;
+      // assert(JS_GetProperty(context-&gt;js, JSVAL_TO_OBJECT(context-&gt;ex), &quot;fileName&quot;, &amp;js_file));
+      // file = convert_to_ruby(context, js_file);
+      // 
+      // jsval js_line;
+      // assert(JS_GetProperty(context-&gt;js, JSVAL_TO_OBJECT(context-&gt;ex), &quot;lineNumber&quot;, &amp;js_line));
+      // line = convert_to_ruby(context, js_line);
+      // 
+      // jsval js_stack;
+      // assert(JS_GetProperty(context-&gt;js, JSVAL_TO_OBJECT(context-&gt;ex), &quot;stack&quot;, &amp;js_stack));
+      // stack = convert_to_ruby(context, js_stack);
+      // 
+      // return rb_funcall(self, rb_intern(&quot;handle_js_exception&quot;),
+      //   4, message, file, line, stack);
     }
-
-    // Something went wrong! If a context was created,
-    if (context)
-      // destroy it safely.
-      JS_DestroyContext(context);
     
-    // Scream for help.
-    Johnson_Error_raise(&quot;Unable to create Johnson::SpiderMonkey::Runtime!&quot;);
+    char* msg = johnson_context-&gt;msg;
+
+    // toString() whatever the exception object is (if we have one)
+    if (johnson_context-&gt;ex)
+      msg = JS_GetStringBytes(JS_ValueToString(context, johnson_context-&gt;ex));
+
+    return Johnson_Error_raise(msg);
   }
-  
-  // Success. Already had a context for the current thread.
-  return context;
+
+  return convert_to_ruby(runtime, js);
+}
+
+/*
+ * call-seq:
+ *   debugger=(debugger)
+ *
+ * Sets a debugger object
+ */
+static VALUE
+set_debugger(VALUE self, VALUE debugger)
+{
+  JohnsonRuntime* runtime;
+  JSDebugHooks* debug_hooks;
+
+  Data_Get_Struct(self, JohnsonRuntime, runtime);
+  Data_Get_Struct(debugger, JSDebugHooks, debug_hooks);
+
+  JSContext * context = johnson_get_current_context(runtime);
+
+  JS_SetInterrupt(          runtime-&gt;js,
+                            debug_hooks-&gt;interruptHandler,
+                            debug_hooks-&gt;interruptHandlerData);
+  JS_SetNewScriptHook(      runtime-&gt;js,
+                            debug_hooks-&gt;newScriptHook,
+                            debug_hooks-&gt;newScriptHookData);
+  JS_SetDestroyScriptHook(  runtime-&gt;js,
+                            debug_hooks-&gt;destroyScriptHook,
+                            debug_hooks-&gt;destroyScriptHookData);
+  JS_SetDebuggerHandler(    runtime-&gt;js,
+                            debug_hooks-&gt;debuggerHandler,
+                            debug_hooks-&gt;debuggerHandlerData);
+  JS_SetSourceHandler(      runtime-&gt;js,
+                            debug_hooks-&gt;sourceHandler,
+                            debug_hooks-&gt;sourceHandlerData);
+  JS_SetExecuteHook(        runtime-&gt;js,
+                            debug_hooks-&gt;executeHook,
+                            debug_hooks-&gt;executeHookData);
+  JS_SetCallHook(           runtime-&gt;js,
+                            debug_hooks-&gt;callHook,
+                            debug_hooks-&gt;callHookData);
+  JS_SetObjectHook(         runtime-&gt;js,
+                            debug_hooks-&gt;objectHook,
+                            debug_hooks-&gt;objectHookData);
+  JS_SetThrowHook(          runtime-&gt;js,
+                            debug_hooks-&gt;throwHook,
+                            debug_hooks-&gt;throwHookData);
+  JS_SetDebugErrorHook(     runtime-&gt;js,
+                            debug_hooks-&gt;debugErrorHook,
+                            debug_hooks-&gt;debugErrorHookData);
+
+  JS_SetContextDebugHooks(context, debug_hooks);
+
+  return debugger;
 }
 
 static VALUE
@@ -51,32 +155,51 @@ initialize_native(VALUE self, VALUE UNUSED(options))
   JohnsonRuntime* runtime;
   Data_Get_Struct(self, JohnsonRuntime, runtime);
   
+  bool gcthings_rooted_p = false;
+
   if ((runtime-&gt;js = JS_NewRuntime(0x100000))
-    &amp;&amp; (runtime-&gt;contexts = create_id_hash()))
+    &amp;&amp; (runtime-&gt;jsids = create_id_hash())
+    &amp;&amp; (runtime-&gt;rbids = create_id_hash())
+  )
   {
+    JS_SetRuntimePrivate(runtime-&gt;js, (void *)self);
     JSContext* context = johnson_get_current_context(runtime);
-    runtime-&gt;global = JS_GetGlobalObject(context);    
-    JS_AddNamedRoot(context, &amp;(runtime-&gt;global), &quot;runtime-&gt;global&quot;);
-    
-    return self;
+    if(
+        (runtime-&gt;gcthings = JS_NewObject(context, NULL, 0, 0))
+        &amp;&amp;(runtime-&gt;global = JS_GetGlobalObject(context))
+        &amp;&amp;(gcthings_rooted_p = JS_AddNamedRoot(context, &amp;(runtime-&gt;global), &quot;runtime-&gt;global&quot;))
+    ) {
+      return self;
+    }
+    if (gcthings_rooted_p)
+      JS_RemoveRoot(context, &amp;(runtime-&gt;gcthings));
   }
-  
-  if (runtime-&gt;contexts)
-    JS_HashTableDestroy(runtime-&gt;contexts);
-  
+
+
+  if (runtime-&gt;rbids)
+    JS_HashTableDestroy(runtime-&gt;rbids);
+
+  if (runtime-&gt;jsids)
+    JS_HashTableDestroy(runtime-&gt;jsids);
+
   if (runtime-&gt;js)
     JS_DestroyRuntime(runtime-&gt;js);
     
   return Johnson_Error_raise(&quot;Couldn't initialize the runtime!&quot;);
 }
 
+JSContext* johnson_get_current_context(JohnsonRuntime * runtime)
+{
+  JohnsonContext * context = NULL;
+  VALUE self = (VALUE)JS_GetRuntimePrivate(runtime-&gt;js);
+  Data_Get_Struct(rb_funcall(self, rb_intern(&quot;current_context&quot;), 0), JohnsonContext, context);
+  return context-&gt;js;
+}
+
 static void deallocate(JohnsonRuntime* runtime)
 {
   JS_RemoveRoot(johnson_get_current_context(runtime), &amp;(runtime-&gt;global));
   
-  JS_HashTableDestroy(runtime-&gt;contexts);
-  runtime-&gt;contexts = 0;
-  
   JSContext *context;
   JSContext *iterator = NULL;
 
@@ -99,4 +222,8 @@ void init_Johnson_SpiderMonkey_Runtime(VALUE spidermonkey)
 
   rb_define_alloc_func(klass, allocate);
   rb_define_private_method(klass, &quot;initialize_native&quot;, initialize_native, 1);
+
+  rb_define_method(klass, &quot;global&quot;, global, 0);
+  rb_define_method(klass, &quot;evaluate&quot;, evaluate, -1);
+  rb_define_method(klass, &quot;debugger=&quot;, set_debugger, 1);
 }</diff>
      <filename>ext/spidermonkey/runtime.c</filename>
    </modified>
    <modified>
      <diff>@@ -4,9 +4,12 @@
 #include &quot;spidermonkey.h&quot;
 
 typedef struct {
-  JSHashTable* contexts;
   JSObject* global;
   JSRuntime* js;
+
+  JSHashTable *jsids; // jsid -&gt; rbid
+  JSHashTable *rbids; // rbid -&gt; jsid
+  JSObject *gcthings;
 } JohnsonRuntime;
 
 JSContext* johnson_get_current_context(JohnsonRuntime* runtime);</diff>
      <filename>ext/spidermonkey/runtime.h</filename>
    </modified>
    <modified>
      <diff>@@ -62,7 +62,7 @@ Johnson.require = function(file) {
     
     if(Ruby.File.send(&quot;file?&quot;, path)) {
       Johnson.required[file] = true;
-      Johnson.currentContext.load(path);
+      Johnson.runtime.load(path);
       
       return true;
     }</diff>
      <filename>js/johnson/prelude.js</filename>
    </modified>
    <modified>
      <diff>@@ -24,7 +24,7 @@ require &quot;johnson/spidermonkey/debugger&quot;
 require &quot;johnson/spidermonkey/immutable_node&quot;
 
 # the 'public' interface
-require &quot;johnson/context&quot;
+require &quot;johnson/runtime&quot;
 require &quot;johnson/parser&quot;
 
 $LOAD_PATH.push(File.expand_path(&quot;#{File.dirname(__FILE__)}/../js&quot;))
@@ -33,10 +33,10 @@ module Johnson
   PRELUDE = IO.read(File.dirname(__FILE__) + &quot;/../js/johnson/prelude.js&quot;)
   
   def self.evaluate(expression, vars={})
-    context = Johnson::Context.new
-    vars.each { |key, value| context[key] = value }
+    runtime = Johnson::Runtime.new
+    vars.each { |key, value| runtime[key] = value }
     
-    context.evaluate(expression)
+    runtime.evaluate(expression)
   end
   
   def self.parse(js, *args)</diff>
      <filename>lib/johnson.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,37 +1,10 @@
 module Johnson #:nodoc:
   module SpiderMonkey #:nodoc:
     class Context # native
-      def initialize(options={})
-        initialize_native(options)
+      def initialize(runtime, options={})
+        @runtime = runtime
+        initialize_native(runtime, options)
         @gcthings = {}
-        self[&quot;Ruby&quot;] = Object
-      end
-      
-      def [](key)
-        global[key]
-      end
-      
-      def []=(key, value)
-        global[key] = value
-      end
-            
-      protected
-      
-      def handle_js_exception(jsex)
-        raise jsex if Exception === jsex
-        raise Johnson::Error.new(jsex.to_s) unless Johnson::SpiderMonkey::RubyLandProxy === jsex
-        
-        # FIXME: sanitize stack traces
-        stack = jsex.stack rescue nil
-        
-        ex = Johnson::Error.new(jsex)
-        if stack
-          ex.set_backtrace(stack.split(&quot;\n&quot;) + caller)
-        else
-          ex.set_backtrace(caller)
-        end
-        
-        raise ex
       end
       
       # called from js_land_proxy.c:make_js_land_proxy</diff>
      <filename>lib/johnson/spidermonkey/context.rb</filename>
    </modified>
    <modified>
      <diff>@@ -16,7 +16,7 @@ module Johnson #:nodoc:
       end
 
       def call(*args)
-        call_using(context.global, *args)
+        call_using(runtime.global, *args)
       end
 
       def call_using(this, *args)</diff>
      <filename>lib/johnson/spidermonkey/ruby_land_proxy.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,6 +3,39 @@ module Johnson #:nodoc:
     class Runtime # native
       def initialize(options={})
         initialize_native(options)
+        self[&quot;Ruby&quot;] = Object
+      end
+
+      def current_context
+        contexts = (Thread.current[:johson_context_map] ||= {})
+        contexts[self.object_id] ||= Context.new(self)
+      end
+
+      def [](key)
+        global[key]
+      end
+      
+      def []=(key, value)
+        global[key] = value
+      end
+
+      protected
+      
+      def handle_js_exception(jsex)
+        raise jsex if Exception === jsex
+        raise Johnson::Error.new(jsex.to_s) unless Johnson::SpiderMonkey::RubyLandProxy === jsex
+        
+        # FIXME: sanitize stack traces
+        stack = jsex.stack rescue nil
+        
+        ex = Johnson::Error.new(jsex)
+        if stack
+          ex.set_backtrace(stack.split(&quot;\n&quot;) + caller)
+        else
+          ex.set_backtrace(caller)
+        end
+        
+        raise ex
       end
     end
   end</diff>
      <filename>lib/johnson/spidermonkey/runtime.rb</filename>
    </modified>
    <modified>
      <diff>@@ -21,14 +21,14 @@ module Johnson
     undef :default_test
     
     def assert_js(expression, options={})
-      context = options[:context] || @context
-      assert(context.evaluate(expression), &quot;Expected JS expression [#{expression}] to be true.&quot;)
+      runtime = options[:runtime] || @runtime
+      assert(runtime.evaluate(expression), &quot;Expected JS expression [#{expression}] to be true.&quot;)
     end
     
     def assert_js_equal(expected, expression, options={})
-      context = options.delete(:context) || @context
-      options.each { |k, v| context[k.to_s] = v }
-      assert_equal(expected, context.evaluate(expression))
+      runtime = options.delete(:runtime) || @runtime
+      options.each { |k, v| runtime[k.to_s] = v }
+      assert_equal(expected, runtime.evaluate(expression))
     end
   end
 </diff>
      <filename>test/helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,15 +3,15 @@ require File.expand_path(File.join(File.dirname(__FILE__), &quot;/../helper&quot;))
 module Johnson
   class BrowserTest &lt; Johnson::TestCase
     def setup
-      @context = Johnson::Context.new
-      @context.evaluate('Johnson.require(&quot;johnson/browser&quot;);')
+      @runtime = Johnson::Runtime.new
+      @runtime.evaluate('Johnson.require(&quot;johnson/browser&quot;);')
     end
 
     def test_set_location_returns_location
       filename = &quot;file://#{File.expand_path(__FILE__)}&quot;
-      @context.evaluate(&quot;window.location = '#{filename}'&quot;)
+      @runtime.evaluate(&quot;window.location = '#{filename}'&quot;)
       uri = URI.parse(filename)
-      assert_equal(uri.to_s, @context.evaluate('window.location').to_s)
+      assert_equal(uri.to_s, @runtime.evaluate('window.location').to_s)
     end
   end
 end</diff>
      <filename>test/johnson/browser_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,32 +4,32 @@ module Johnson
   module Conversions
     class ArrayTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
       
       def test_array_index_get
-        @context[:list] = [1, 2, 3, 4]
-        assert_equal(1, @context.evaluate(&quot;list[0]&quot;))
+        @runtime[:list] = [1, 2, 3, 4]
+        assert_equal(1, @runtime.evaluate(&quot;list[0]&quot;))
       end
 
       def test_array_index_set
-        @context[:list] = []
-        @context.evaluate(&quot;list[0] = 42&quot;)
-        assert_equal(42, @context[:list][0])
+        @runtime[:list] = []
+        @runtime.evaluate(&quot;list[0] = 42&quot;)
+        assert_equal(42, @runtime[:list][0])
       end
 
       def test_array_works_with_for_in
         list = [1, 2, 3, 4]
 
-        @context['alert'] = lambda { |x| p x }
-        @context['list'] = list
-        @context.evaluate(&quot;
+        @runtime['alert'] = lambda { |x| p x }
+        @runtime['list'] = list
+        @runtime.evaluate(&quot;
           var new_list = [];
           for(x in list) {
             new_list.push(x + 1);
           }
         &quot;)
-        assert_equal(list.map { |x| x + 1}, @context['new_list'].to_a)
+        assert_equal(list.map { |x| x + 1}, @runtime['new_list'].to_a)
       end
     end
   end</diff>
      <filename>test/johnson/conversions/array_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,17 +4,17 @@ module Johnson
   module Conversions
     class BooleanTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
       
       def test_truthiness
-        @context[:v] = true
-        assert_same(true, @context.evaluate(&quot;v === true&quot;))
+        @runtime[:v] = true
+        assert_same(true, @runtime.evaluate(&quot;v === true&quot;))
       end
 
       def test_dirty_lies
-        @context[:v] = false
-        assert_same(false, @context.evaluate(&quot;v === true&quot;))
+        @runtime[:v] = false
+        assert_same(false, @runtime.evaluate(&quot;v === true&quot;))
       end
     end
   end</diff>
      <filename>test/johnson/conversions/boolean_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,22 +4,22 @@ module Johnson
   module Conversions
     class CallableTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
       
       def test_proc_works_in_jsland
-        @context[:squared] = Proc.new { |x| x * x }
+        @runtime[:squared] = Proc.new { |x| x * x }
         assert_js_equal(4, &quot;squared(2)&quot;)
       end
       
       def test_procs_roundtrip
-        @context[:k] = k = lambda { |x| x }
-        assert_same(k, @context.evaluate(&quot;k&quot;))
+        @runtime[:k] = k = lambda { |x| x }
+        assert_same(k, @runtime.evaluate(&quot;k&quot;))
       end
       
       def test_proc_js_function_proxy_gets_reused
-        @context[:k] = k = lambda { |x| x }
-        @context[:kk] = k
+        @runtime[:k] = k = lambda { |x| x }
+        @runtime[:kk] = k
         assert_js(&quot;k === kk&quot;)
       end
       
@@ -30,7 +30,7 @@ module Johnson
       end
       
       def test_anything_with_a_call_method_can_be_called_as_a_method
-        @context[:c] = CallableThing.new
+        @runtime[:c] = CallableThing.new
         assert_js_equal(&quot;foo&quot;, &quot;c()&quot;)
       end
     end</diff>
      <filename>test/johnson/conversions/callable_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,14 +4,14 @@ module Johnson
   module Conversions
     class FileTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
 
       def test_read_file
         File.open(__FILE__, 'rb') { |f|
-          @context[:foo] = f
-          assert_equal(f, @context.evaluate(&quot;foo&quot;))
-          assert_equal(File.read(__FILE__), @context.evaluate(&quot;foo.read()&quot;))
+          @runtime[:foo] = f
+          assert_equal(f, @runtime.evaluate(&quot;foo&quot;))
+          assert_equal(File.read(__FILE__), @runtime.evaluate(&quot;foo.read()&quot;))
         }
       end
     end</diff>
      <filename>test/johnson/conversions/file_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,20 +4,20 @@ module Johnson
   module Conversions
     class NilTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
       
       def test_ruby_nil_is_js_null
-        @context[:v] = nil
-        assert_equal(true, @context.evaluate(&quot;v == null&quot;))
+        @runtime[:v] = nil
+        assert_equal(true, @runtime.evaluate(&quot;v == null&quot;))
       end
 
       def test_js_null_is_ruby_nil
-        assert_nil(@context.evaluate(&quot;null&quot;))
+        assert_nil(@runtime.evaluate(&quot;null&quot;))
       end
 
       def test_js_undefined_is_ruby_nil
-        assert_nil(@context.evaluate(&quot;undefined&quot;))
+        assert_nil(@runtime.evaluate(&quot;undefined&quot;))
       end
     end
   end</diff>
      <filename>test/johnson/conversions/nil_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,34 +4,34 @@ module Johnson
   module Conversions
     class NumberTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
       
       def test_ruby_fixnum_in_js
-        @context[:v] = 42
+        @runtime[:v] = 42
         
         assert_js(&quot;v == 42&quot;)
         assert_js_equal(42, &quot;v&quot;)
-        assert_equal(42, @context[:v])
+        assert_equal(42, @runtime[:v])
       end
       
       def test_js_fixnum_in_ruby
-        fix = @context.evaluate(&quot;42&quot;)
+        fix = @runtime.evaluate(&quot;42&quot;)
         assert_equal(42, fix)
         assert_kind_of(Fixnum, fix)
       end
 
       def test_ruby_float_in_js
-        @context[:pi] = pi = 3.141592654
+        @runtime[:pi] = pi = 3.141592654
         assert_js_equal(pi, &quot;pi&quot;)
-        assert_in_delta(pi, @context.evaluate(&quot;pi&quot;), 2 ** -20)
+        assert_in_delta(pi, @runtime.evaluate(&quot;pi&quot;), 2 ** -20)
       end
       
       def test_ruby_bignum_in_js
-        @context[:big] = big = 2 ** 200        
+        @runtime[:big] = big = 2 ** 200        
         
         assert_js_equal(big, &quot;big&quot;)
-        assert_kind_of(Float, @context.evaluate(&quot;big&quot;))
+        assert_kind_of(Float, @runtime.evaluate(&quot;big&quot;))
       end
     end
   end</diff>
      <filename>test/johnson/conversions/number_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,24 +4,24 @@ module Johnson
   module Conversions
     class RegexpTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
 
       def test_regex_converts
-        @context[:x] = /aaron/
-        @context[:y] = /john/i
-        assert @context.evaluate('&quot;aaron&quot;.match(x)')
-        assert !@context.evaluate('&quot;Aaron&quot;.match(x)')
-        assert @context.evaluate('&quot;john&quot;.match(y)')
-        assert @context.evaluate('&quot;John&quot;.match(y)')
+        @runtime[:x] = /aaron/
+        @runtime[:y] = /john/i
+        assert @runtime.evaluate('&quot;aaron&quot;.match(x)')
+        assert !@runtime.evaluate('&quot;Aaron&quot;.match(x)')
+        assert @runtime.evaluate('&quot;john&quot;.match(y)')
+        assert @runtime.evaluate('&quot;John&quot;.match(y)')
       end
 
       def test_regex_roundtrips
-        @context[:x] = /aaron/
-        assert_equal(/aaron/, @context.evaluate('x'))
+        @runtime[:x] = /aaron/
+        assert_equal(/aaron/, @runtime.evaluate('x'))
 
-        @context[:x] = /aaron/m
-        assert_equal(/aaron/m, @context.evaluate('x'))
+        @runtime[:x] = /aaron/m
+        assert_equal(/aaron/m, @runtime.evaluate('x'))
       end
     end
   end</diff>
      <filename>test/johnson/conversions/regexp_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,26 +4,26 @@ module Johnson
   module Conversions
     class StringTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
       
       def test_ruby_string_in_js
-        @context[:v] = &quot;foo&quot;
+        @runtime[:v] = &quot;foo&quot;
         assert_js(&quot;'foo' == v&quot;)
       end
 
       def test_js_string_in_ruby
-        assert_equal(&quot;foo&quot;, @context.evaluate(&quot;'foo'&quot;))
+        assert_equal(&quot;foo&quot;, @runtime.evaluate(&quot;'foo'&quot;))
       end
 
       def test_roundtrip
-        @context[:v] = v = &quot;hola&quot;
-        assert_equal(v, @context.evaluate(&quot;v&quot;))
+        @runtime[:v] = v = &quot;hola&quot;
+        assert_equal(v, @runtime.evaluate(&quot;v&quot;))
       end
       
       def test_strings_are_copies
-        @context[:v] = v = &quot;hola&quot;
-        assert_not_same(v, @context.evaluate(&quot;v&quot;))
+        @runtime[:v] = v = &quot;hola&quot;
+        assert_not_same(v, @runtime.evaluate(&quot;v&quot;))
       end
     end
   end</diff>
      <filename>test/johnson/conversions/string_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,15 +4,15 @@ module Johnson
   module Conversions
     class StructTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
 
       def test_use_struct
         f = Struct.new(:phil_collins).new
         f.phil_collins = 'awesome'
-        @context[:foo] = f
-        assert_equal(f, @context.evaluate('foo'))
-        assert_equal('awesome', @context.evaluate('foo.phil_collins'))
+        @runtime[:foo] = f
+        assert_equal(f, @runtime.evaluate('foo'))
+        assert_equal('awesome', @runtime.evaluate('foo.phil_collins'))
       end
     end
   end</diff>
      <filename>test/johnson/conversions/struct_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,19 +4,19 @@ module Johnson
   module Conversions
     class SymbolTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
 
       def test_symbols_are_interned
-        @context[:v] = :symbol
-        @context[:x] = :symbol
+        @runtime[:v] = :symbol
+        @runtime[:x] = :symbol
 
-        assert(@context.evaluate(&quot;v !== null &amp;&amp; v === x&quot;))
+        assert(@runtime.evaluate(&quot;v !== null &amp;&amp; v === x&quot;))
       end
 
       def test_ruby_symbol_roundtrips
-        @context[:v] = :foo
-        assert_equal(:foo, @context.evaluate(&quot;v&quot;))
+        @runtime[:v] = :foo
+        assert_equal(:foo, @runtime.evaluate(&quot;v&quot;))
       end
     end
   end</diff>
      <filename>test/johnson/conversions/symbol_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,14 +4,25 @@ module Johnson
   module Conversions
     class ThreadTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
+        @runtime = Johnson::Runtime.new
       end
 
       def test_manipulate_thread
         thread = Thread.new { }
-        @context['thread'] = thread
+        @runtime['thread'] = thread
         assert_js_equal(false, &quot;thread.send('alive?')&quot;)
       end
+
+      def test_new_js_thread
+        @runtime.evaluate('function testing() { Ruby.sleep(10); }')
+        @runtime.evaluate('new Ruby.Thread(function() { testing(); })')
+      end
+
+      def test_js_thread_read_file
+        @runtime['filename'] = File.expand_path(__FILE__)
+        @runtime.evaluate('function testing() { Ruby.File.read(filename); }')
+        @runtime.evaluate('new Ruby.Thread(function() { testing(); })')
+      end
     end
   end
 end</diff>
      <filename>test/johnson/conversions/thread_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,18 +4,18 @@ module Johnson
   module Extensions
     class DefinePropertyTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new
-        @context.evaluate(&quot;x = {}&quot;)
+        @runtime = Johnson::Runtime.new
+        @runtime.evaluate(&quot;x = {}&quot;)
       end      
       
       def test_object_can_define_property
-        @context.evaluate(&quot;Object.defineProperty(x, 'answer', 42)&quot;)
+        @runtime.evaluate(&quot;Object.defineProperty(x, 'answer', 42)&quot;)
         assert_js_equal(42, &quot;x.answer&quot;)
       end
       
       def test_object_can_define_unenumerable_property
-        @context.evaluate(&quot;Object.defineProperty(x, 'answer', 42)&quot;)
-        @context.evaluate &lt;&lt;-JS
+        @runtime.evaluate(&quot;Object.defineProperty(x, 'answer', 42)&quot;)
+        @runtime.evaluate &lt;&lt;-JS
           y = [];
           for(prop in x) if(prop == &quot;answer&quot;) y.push(prop)
         JS
@@ -23,8 +23,8 @@ module Johnson
       end
       
       def test_object_can_define_enumerable_property
-        @context.evaluate(&quot;Object.defineProperty(x, 'answer', 42, Object.ITERABLE)&quot;)
-        @context.evaluate &lt;&lt;-JS
+        @runtime.evaluate(&quot;Object.defineProperty(x, 'answer', 42, Object.ITERABLE)&quot;)
+        @runtime.evaluate &lt;&lt;-JS
           y = [];
           for(prop in x) if(prop == &quot;answer&quot;) y.push(prop)
         JS
@@ -32,22 +32,22 @@ module Johnson
       end
       
       def test_object_can_define_read_only_property
-        @context.evaluate(&quot;Object.defineProperty(x, 'answer', 42, Object.READ_ONLY)&quot;)
-        @context.evaluate(&quot;x.answer = 47&quot;)
+        @runtime.evaluate(&quot;Object.defineProperty(x, 'answer', 42, Object.READ_ONLY)&quot;)
+        @runtime.evaluate(&quot;x.answer = 47&quot;)
         assert_js_equal(42, &quot;x.answer&quot;)
       end
       
       def test_object_can_define_non_deletable_property
-        @context.evaluate(&quot;Object.defineProperty(x, 'answer', 42, Object.NON_DELETABLE)&quot;)
-        @context.evaluate(&quot;r = (delete x.answer)&quot;)
+        @runtime.evaluate(&quot;Object.defineProperty(x, 'answer', 42, Object.NON_DELETABLE)&quot;)
+        @runtime.evaluate(&quot;r = (delete x.answer)&quot;)
         assert_js_equal(false, &quot;r&quot;)
         assert_js_equal(42, &quot;x.answer&quot;)
       end
       
       def test_object_can_define_mixed_property
-        @context.evaluate(&quot;Object.defineProperty(x, 'answer', 42, Object.NON_DELETABLE | Object.READ_ONLY)&quot;)
-        @context.evaluate(&quot;r = (delete x.answer)&quot;)
-        @context.evaluate(&quot;x.answer = 47&quot;)
+        @runtime.evaluate(&quot;Object.defineProperty(x, 'answer', 42, Object.NON_DELETABLE | Object.READ_ONLY)&quot;)
+        @runtime.evaluate(&quot;r = (delete x.answer)&quot;)
+        @runtime.evaluate(&quot;x.answer = 47&quot;)
         assert_js_equal(false, &quot;r&quot;)
         assert_js_equal(42, &quot;x.answer&quot;)
       end      </diff>
      <filename>test/johnson/extensions_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -3,11 +3,11 @@ require File.expand_path(File.join(File.dirname(__FILE__), &quot;/../helper&quot;))
 module Johnson
   class PreludeTest &lt; Johnson::TestCase
     def setup
-      @context = Johnson::Context.new
+      @runtime = Johnson::Runtime.new
     end
     
     def test_symbols_are_interned
-      assert(@context.evaluate(&quot;Johnson.symbolize('foo') === Johnson.symbolize('foo')&quot;))
+      assert(@runtime.evaluate(&quot;Johnson.symbolize('foo') === Johnson.symbolize('foo')&quot;))
     end
     
     def test_strings_had_a_to_symbol_method
@@ -15,7 +15,7 @@ module Johnson
     end
     
     def test_string_to_symbol_is_not_enumerable
-      assert(!@context.evaluate(&lt;&lt;-END))
+      assert(!@runtime.evaluate(&lt;&lt;-END))
         var flag = false;
         for (x in &quot;foo&quot;) { if (x == 'toSymbol') flag = true }
         flag
@@ -23,18 +23,18 @@ module Johnson
     end
     
     def test_symbol_to_string
-      assert_equal(&quot;monkey&quot;, @context.evaluate(&quot;Johnson.symbolize('monkey').toString()&quot;))
+      assert_equal(&quot;monkey&quot;, @runtime.evaluate(&quot;Johnson.symbolize('monkey').toString()&quot;))
     end
 
     def test_symbol_inspect
-      assert_equal(&quot;:monkey&quot;, @context.evaluate(&quot;Johnson.symbolize('monkey').inspect()&quot;))
+      assert_equal(&quot;:monkey&quot;, @runtime.evaluate(&quot;Johnson.symbolize('monkey').inspect()&quot;))
     end
     
     def test_all_of_ruby_is_available
-      assert_raise(Johnson::Error) { @context.evaluate(&quot;Ruby.Set.new()&quot;) }
+      assert_raise(Johnson::Error) { @runtime.evaluate(&quot;Ruby.Set.new()&quot;) }
       
-      @context.evaluate(&quot;Ruby.require('set')&quot;)
-      assert_kind_of(Set, @context.evaluate(&quot;Ruby.Set.new()&quot;))
+      @runtime.evaluate(&quot;Ruby.require('set')&quot;)
+      assert_kind_of(Set, @runtime.evaluate(&quot;Ruby.Set.new()&quot;))
     end
     
     def test_require_an_existing_js_file_without_extension
@@ -43,7 +43,7 @@ module Johnson
     
     def test_require_returns_false_the_second_time_around
       assert_js(&quot;Johnson.require('johnson/template')&quot;)
-      assert(!@context.evaluate(&quot;Johnson.require('johnson/template')&quot;))
+      assert(!@runtime.evaluate(&quot;Johnson.require('johnson/template')&quot;))
     end
     
     def test_missing_requires_throw_LoadError</diff>
      <filename>test/johnson/prelude_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,17 +4,17 @@ module Johnson
   module SpiderMonkey
     class ContextTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new(Johnson::SpiderMonkey::Context)
+        @runtime = Johnson::Runtime.new(Johnson::SpiderMonkey::Runtime)
       end
       
       def test_wraps_global_unfuckedly
-        assert_same(@context.global, @context.evaluate(&quot;this&quot;))
+        assert_same(@runtime.global, @runtime.evaluate(&quot;this&quot;))
       end
       
-      def test_provides_basic_context_interface
-        assert(@context.respond_to?(:evaluate))
-        assert(@context.respond_to?(:[]))
-        assert(@context.respond_to?(:[]=))
+      def test_provides_basic_runtime_interface
+        assert(@runtime.respond_to?(:evaluate))
+        assert(@runtime.respond_to?(:[]))
+        assert(@runtime.respond_to?(:[]=))
       end
     end
   end</diff>
      <filename>test/johnson/spidermonkey/context_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -58,7 +58,7 @@ module Johnson
       end
 
       def setup
-        @context = Johnson::Context.new(Johnson::SpiderMonkey::Context)
+        @runtime = Johnson::Runtime.new(Johnson::SpiderMonkey::Runtime)
       end
 
       def test_find_constants
@@ -66,14 +66,14 @@ module Johnson
       end
 
       def test_proxies_get_reused
-        @context[&quot;foo&quot;] = @context[&quot;bar&quot;] = Foo.new
+        @runtime[&quot;foo&quot;] = @runtime[&quot;bar&quot;] = Foo.new
         assert_js_equal(true, &quot;foo === bar&quot;)
       end
 
       def test_attributes_get_added_to_ruby
-        foo = @context[&quot;foo&quot;] = Foo.new
+        foo = @runtime[&quot;foo&quot;] = Foo.new
         assert !foo.respond_to?(:johnson)
-        @context.evaluate(&quot;foo.johnson = 'explode';&quot;)
+        @runtime.evaluate(&quot;foo.johnson = 'explode';&quot;)
         assert foo.respond_to?(:johnson)
         assert_equal('explode', foo.johnson)
         assert_js_equal('explode', 'foo.johnson')
@@ -81,9 +81,9 @@ module Johnson
       end
 
       def test_assign_function_as_attribute
-        foo = @context[&quot;foo&quot;] = Foo.new
+        foo = @runtime[&quot;foo&quot;] = Foo.new
         assert !foo.respond_to?(:johnson)
-        f = @context.evaluate(&quot;foo.johnson = function() { return 'explode'; }&quot;)
+        f = @runtime.evaluate(&quot;foo.johnson = function() { return 'explode'; }&quot;)
         assert foo.respond_to?(:johnson)
         assert_equal('explode', foo.johnson)
         assert_js_equal('explode', 'foo.johnson()')
@@ -92,115 +92,115 @@ module Johnson
       end
 
       def test_assign_function_as_attribute_with_this
-        foo = @context[&quot;foo&quot;] = Foo.new
-        @context.evaluate(&quot;foo.ex_squared = function(x) { return this.x2(x); }&quot;)
+        foo = @runtime[&quot;foo&quot;] = Foo.new
+        @runtime.evaluate(&quot;foo.ex_squared = function(x) { return this.x2(x); }&quot;)
         assert_equal(4, foo.ex_squared(2))
-        @context.evaluate(&quot;foo.ex_squared = 20;&quot;)
+        @runtime.evaluate(&quot;foo.ex_squared = 20;&quot;)
         assert_equal(20, foo.ex_squared)
       end
 
       def test_use_ruby_global_object
-        func = @context.evaluate(&quot;function(x) { return this.x2(x); }&quot;)
+        func = @runtime.evaluate(&quot;function(x) { return this.x2(x); }&quot;)
         foo  = Foo.new
         assert_equal(4, func.call_using(foo, 2))
       end
       
       def test_proxies_roundtrip
-        @context[&quot;foo&quot;] = foo = Foo.new
-        assert_same(foo, @context.evaluate(&quot;foo&quot;))
+        @runtime[&quot;foo&quot;] = foo = Foo.new
+        assert_same(foo, @runtime.evaluate(&quot;foo&quot;))
       end
       
       def test_proxies_classes
-        @context[&quot;Foo&quot;] = Foo
-        assert_same(Foo, @context.evaluate(&quot;Foo&quot;))
+        @runtime[&quot;Foo&quot;] = Foo
+        assert_same(Foo, @runtime.evaluate(&quot;Foo&quot;))
       end
       
       def test_proxies_modules
-        @context[&quot;AModule&quot;] = AModule
-        assert_same(AModule, @context.evaluate(&quot;AModule&quot;))
+        @runtime[&quot;AModule&quot;] = AModule
+        assert_same(AModule, @runtime.evaluate(&quot;AModule&quot;))
       end
       
       def test_proxies_hashes
-        @context[&quot;beatles&quot;] = { &quot;george&quot; =&gt; &quot;guitar&quot; }
-        assert_equal(&quot;guitar&quot;, @context.evaluate(&quot;beatles['george']&quot;))
+        @runtime[&quot;beatles&quot;] = { &quot;george&quot; =&gt; &quot;guitar&quot; }
+        assert_equal(&quot;guitar&quot;, @runtime.evaluate(&quot;beatles['george']&quot;))
       end
       
       def test_getter_calls_0_arity_method
-        @context[&quot;foo&quot;] = Foo.new
+        @runtime[&quot;foo&quot;] = Foo.new
         assert_js_equal(10, &quot;foo.bar&quot;)
       end
       
       def test_getter_calls_indexer
-        @context[&quot;foo&quot;] = indexable = Indexable.new
+        @runtime[&quot;foo&quot;] = indexable = Indexable.new
         indexable[&quot;bar&quot;] = 10
         
         assert_js_equal(10, &quot;foo.bar&quot;)
       end
       
       def test_getter_returns_nil_for_unknown_properties
-        @context[&quot;foo&quot;] = Foo.new
+        @runtime[&quot;foo&quot;] = Foo.new
         assert_js_equal(nil, &quot;foo.quux&quot;)
       end
 
       def test_setter_calls_key=
-        @context[&quot;foo&quot;] = foo = Foo.new
+        @runtime[&quot;foo&quot;] = foo = Foo.new
         assert_js_equal(42, &quot;foo.bar = 42&quot;)
         assert_equal(42, foo.bar)
       end
       
       def test_setter_calls_indexer
-        @context[&quot;foo&quot;] = indexable = Indexable.new
+        @runtime[&quot;foo&quot;] = indexable = Indexable.new
         assert_js_equal(42, &quot;foo.monkey = 42&quot;)
         assert_equal(42, indexable[&quot;monkey&quot;])
       end
       
       def test_calls_attr_reader
-        @context[&quot;foo&quot;] = Foo.new
+        @runtime[&quot;foo&quot;] = Foo.new
         assert_js_equal(10, &quot;foo.bar&quot;)
       end
       
       def test_calls_1_arity_method
-        @context[&quot;foo&quot;] = Foo.new
+        @runtime[&quot;foo&quot;] = Foo.new
         assert_js_equal(10, &quot;foo.x2(5)&quot;)
       end
       
       def test_calls_n_arity_method
-        @context[&quot;foo&quot;] = Foo.new
+        @runtime[&quot;foo&quot;] = Foo.new
         assert_js_equal(10, &quot;foo.add(4, 2, 2, 1, 1)&quot;)
       end
       
       def test_calls_class_method
-        @context[&quot;Foo&quot;] = Foo
+        @runtime[&quot;Foo&quot;] = Foo
         assert_js_equal(Foo.bar, &quot;Foo.bar()&quot;)
       end
       
       def test_accesses_consts
-        @context[&quot;Foo&quot;] = Foo
-        assert_same(Foo::Inner, @context.evaluate(&quot;Foo.Inner&quot;))
+        @runtime[&quot;Foo&quot;] = Foo
+        assert_same(Foo::Inner, @runtime.evaluate(&quot;Foo.Inner&quot;))
       end
             
       def test_can_create_new_instances_in_js
-        @context[&quot;AClass&quot;] = AClass
-        foo = @context.evaluate(&quot;AClass.new()&quot;)
+        @runtime[&quot;AClass&quot;] = AClass
+        foo = @runtime.evaluate(&quot;AClass.new()&quot;)
         assert_kind_of(AClass, foo)
       end
       
       def test_class_proxies_provide_a_ctor
-        @context[&quot;AClass&quot;] = AClass
-        foo = @context.evaluate(&quot;new AClass()&quot;)
+        @runtime[&quot;AClass&quot;] = AClass
+        foo = @runtime.evaluate(&quot;new AClass()&quot;)
         assert_kind_of(AClass, foo)
         
-        bar = @context.evaluate(&quot;new AClass(1, 2, 3)&quot;)
+        bar = @runtime.evaluate(&quot;new AClass(1, 2, 3)&quot;)
         assert_equal([1, 2, 3], bar.args)
       end
       
       def test_dwims_blocks
-        @context[&quot;foo&quot;] = Foo.new
+        @runtime[&quot;foo&quot;] = Foo.new
         assert_js_equal(4, &quot;foo.xform(2, function(x) { return x * 2 })&quot;)
       end
       
       def test_dwims_blocks_for_0_arity_methods
-        @context[:arr] = [1, 2, 3]
+        @runtime[:arr] = [1, 2, 3]
         assert_js_equal([2, 4, 6], &quot;arr.collect(function(x) { return x * 2 })&quot;)
       end
       
@@ -221,15 +221,15 @@ module Johnson
       end
 
       def test_raises_string_to_ruby
-        assert_raise(Johnson::Error) { @context.evaluate(&quot;throw 'my string';&quot;) }
+        assert_raise(Johnson::Error) { @runtime.evaluate(&quot;throw 'my string';&quot;) }
       end
 
       def test_raises_object_to_ruby
-        assert_raise(Johnson::Error) { @context.evaluate(&quot;throw { bad: true };&quot;) }
+        assert_raise(Johnson::Error) { @runtime.evaluate(&quot;throw { bad: true };&quot;) }
       end
 
       def test_raises_exception_to_ruby
-        assert_raise(Johnson::Error) { @context.evaluate(&quot;undefinedValue();&quot;) }
+        assert_raise(Johnson::Error) { @runtime.evaluate(&quot;undefinedValue();&quot;) }
       end
     end
   end</diff>
      <filename>test/johnson/spidermonkey/js_land_proxy_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ module Johnson
   module SpiderMonkey
     class RubyLandProxyTest &lt; Johnson::TestCase
       def setup
-        @context = Johnson::Context.new(Johnson::SpiderMonkey::Context)
+        @runtime = Johnson::Runtime.new(Johnson::SpiderMonkey::Runtime)
       end
       
       def test_constructing_a_proxy_directly_asplodes
@@ -12,18 +12,18 @@ module Johnson
       end
       
       def test_objects_get_wrapped_as_proxies
-        assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, @context.evaluate(&quot;x = {}&quot;))
-        assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, @context.evaluate(&quot;new Object()&quot;))
+        assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, @runtime.evaluate(&quot;x = {}&quot;))
+        assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, @runtime.evaluate(&quot;new Object()&quot;))
       end
       
       def test_proxies_get_unwrapped_when_roundtripping
-        proxy = @context.evaluate(&quot;x = {}&quot;)
-        @context[&quot;y&quot;] = proxy
-        assert(@context.evaluate(&quot;x === y&quot;))
+        proxy = @runtime.evaluate(&quot;x = {}&quot;)
+        @runtime[&quot;y&quot;] = proxy
+        assert(@runtime.evaluate(&quot;x === y&quot;))
       end
       
       def test_array_indexable
-        proxy = @context.evaluate(&quot;var x = [1,2,3]; x&quot;)
+        proxy = @runtime.evaluate(&quot;var x = [1,2,3]; x&quot;)
         assert_equal(1, proxy[0])
         assert_equal(1, proxy['0'])
 
@@ -32,7 +32,7 @@ module Johnson
       end
       
       def test_hash_indexable
-        proxy = @context.evaluate(&quot;var x = { 0: 1, 1: 2, 2: 3 }; x&quot;)
+        proxy = @runtime.evaluate(&quot;var x = { 0: 1, 1: 2, 2: 3 }; x&quot;)
         assert_equal(1, proxy[0])
         assert_equal(1, proxy['0'])
 
@@ -41,49 +41,49 @@ module Johnson
       end
 
       def test_functions_get_wrapped_as_proxies
-        f = @context.evaluate(&quot;function() {}&quot;)
+        f = @runtime.evaluate(&quot;function() {}&quot;)
         assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, f)
         assert(f.function?)
       end
 
       def test_function?
-        f = @context.evaluate(&quot;function() {}&quot;)
+        f = @runtime.evaluate(&quot;function() {}&quot;)
         assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, f)
         assert(f.function?)
 
-        f = @context.evaluate(&quot;new Object()&quot;)
+        f = @runtime.evaluate(&quot;new Object()&quot;)
         assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, f)
         assert(!f.function?)
       end
       
       def test_calling_non_functions_complains
-        assert_raise(Johnson::Error) { @context.evaluate(&quot;new Object()&quot;).call }
+        assert_raise(Johnson::Error) { @runtime.evaluate(&quot;new Object()&quot;).call }
       end
       
       def test_functions_can_be_called
-        f = @context.evaluate(&quot;function() { return 42; }&quot;)
+        f = @runtime.evaluate(&quot;function() { return 42; }&quot;)
         assert_equal(42, f.call)
       end
       
       def test_functions_can_be_called_with_args
-        f = @context.evaluate(&quot;function(x) { return x * 2; }&quot;)
+        f = @runtime.evaluate(&quot;function(x) { return x * 2; }&quot;)
         assert_equal(84, f.call(42))
       end
       
       def test_functions_can_be_used_as_procs
-        f = @context.evaluate(&quot;function(x) { return x * 2; }&quot;)
+        f = @runtime.evaluate(&quot;function(x) { return x * 2; }&quot;)
         a = [1, 2, 3]
         
         assert_equal([2, 4, 6], a.collect(&amp;f))
       end
       
       def test_function_proxies_are_called_with_a_global_this
-        f = @context.evaluate(&quot;x = 42; function() { return this.x; }&quot;)
+        f = @runtime.evaluate(&quot;x = 42; function() { return this.x; }&quot;)
         assert_equal(42, f.call)
       end
       
       def test_can_be_indexed_by_string
-        proxy = @context.evaluate(&quot;x = { foo: 42 }&quot;)
+        proxy = @runtime.evaluate(&quot;x = { foo: 42 }&quot;)
         assert_kind_of(Johnson::SpiderMonkey::RubyLandProxy, proxy)
         
         assert_equal(42, proxy[&quot;foo&quot;])
@@ -97,29 +97,29 @@ module Johnson
       end
       
       def test_multilevel_indexing_works
-        proxy = @context.evaluate(&quot;x = { foo: { bar: 42 , baz: function() { return 42 } } }&quot;)
+        proxy = @runtime.evaluate(&quot;x = { foo: { bar: 42 , baz: function() { return 42 } } }&quot;)
         assert_equal(42, proxy[&quot;foo&quot;][&quot;bar&quot;])
         assert_equal(42, proxy[&quot;foo&quot;][&quot;baz&quot;].call)
       end
       
       def test_respond_to_works
-        proxy = @context.evaluate(&quot;x = { foo: 42 }&quot;)
+        proxy = @runtime.evaluate(&quot;x = { foo: 42 }&quot;)
         assert(!proxy.respond_to?(:bar))
         assert(proxy.respond_to?(:foo))
       end
       
       def test_respond_to_always_returns_true_for_assignment
-        proxy = @context.evaluate(&quot;x = {}&quot;)
+        proxy = @runtime.evaluate(&quot;x = {}&quot;)
         assert(proxy.respond_to?(:bar=))
       end
       
       def test_accessor
-        proxy = @context.evaluate(&quot;x = { foo: 42 }&quot;)
+        proxy = @runtime.evaluate(&quot;x = { foo: 42 }&quot;)
         assert_equal(42, proxy.foo)
       end
       
       def test_mutator
-        proxy = @context.evaluate(&quot;x = {}&quot;)
+        proxy = @runtime.evaluate(&quot;x = {}&quot;)
         proxy.foo = 42
         
         assert_js_equal(42, &quot;x.foo&quot;)
@@ -127,22 +127,22 @@ module Johnson
       end
       
       def test_method_with_no_arguments
-        proxy = @context.evaluate(&quot;x = { foo: function() { return 42 } }&quot;)
+        proxy = @runtime.evaluate(&quot;x = { foo: function() { return 42 } }&quot;)
         assert_equal(42, proxy.foo)
       end
       
       def test_method_with_one_argument
-        proxy = @context.evaluate(&quot;f = { f: function(x) { return x * 2 } }&quot;)
+        proxy = @runtime.evaluate(&quot;f = { f: function(x) { return x * 2 } }&quot;)
         assert_equal(84, proxy.f(42))
       end
       
       def test_method_with_multiple_arguments
-        proxy = @context.evaluate(&quot;x = { add: function(x, y) { return x + y } }&quot;)
+        proxy = @runtime.evaluate(&quot;x = { add: function(x, y) { return x + y } }&quot;)
         assert_equal(42, proxy.add(40, 2))
       end
       
       def test_supports_each_on_arrays
-        proxy = @context.evaluate(&quot;[1, 2, 3]&quot;)
+        proxy = @runtime.evaluate(&quot;[1, 2, 3]&quot;)
         values = []
         
         proxy.each { |n| values &lt;&lt; n }
@@ -150,7 +150,7 @@ module Johnson
       end
       
       def test_supports_each_on_things_that_arent_arrays
-        proxy = @context.evaluate(&quot;x = { foo: 'fooval', bar: 'barval' }; x[0] = 42; x&quot;)
+        proxy = @runtime.evaluate(&quot;x = { foo: 'fooval', bar: 'barval' }; x[0] = 42; x&quot;)
         values = {}
         
         proxy.each { |k, v| values[k] = v }
@@ -158,7 +158,7 @@ module Johnson
       end
       
       def test_each_passes_an_exception
-        proxy = @context.evaluate(&quot;x = { foo: 'fooval', bar: 'barval' }; x[0] = 42; x&quot;)
+        proxy = @runtime.evaluate(&quot;x = { foo: 'fooval', bar: 'barval' }; x[0] = 42; x&quot;)
         values = {}
         
         assert_raise(RuntimeError) do
@@ -171,29 +171,29 @@ module Johnson
       end
       
       def test_is_enumerable
-        proxy = @context.evaluate(&quot;[1, 2, 3]&quot;)
+        proxy = @runtime.evaluate(&quot;[1, 2, 3]&quot;)
         assert_kind_of(Enumerable, proxy)
         
         assert_equal([2, 4, 6], proxy.collect { |n| n * 2 })
       end
       
       def test_has_a_length
-        proxy = @context.evaluate(&quot;[1, 2, 3]&quot;)
+        proxy = @runtime.evaluate(&quot;[1, 2, 3]&quot;)
         assert_equal(3, proxy.length)
       end
       
       def test_length_is_aliased_as_size
-        proxy = @context.evaluate(&quot;[1, 2, 3]&quot;)
+        proxy = @runtime.evaluate(&quot;[1, 2, 3]&quot;)
         assert_equal(3, proxy.size)
       end
       
       def test_length_for_arrays_ignores_non_numeric_properties
-        proxy = @context.evaluate(&quot;x = [1, 2, 3]; x['foo'] = 'bar'; x&quot;)
+        proxy = @runtime.evaluate(&quot;x = [1, 2, 3]; x['foo'] = 'bar'; x&quot;)
         assert_equal(3, proxy.length)
       end
       
       def test_length_for_objects_includes_all_properties
-        proxy = @context.evaluate(&quot;x = { foo: 'foo', bar: 'bar', 0: 42 }&quot;)
+        proxy = @runtime.evaluate(&quot;x = { foo: 'foo', bar: 'bar', 0: 42 }&quot;)
         assert_equal(3, proxy.length)
       end
 </diff>
      <filename>test/johnson/spidermonkey/ruby_land_proxy_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,7 +8,9 @@ module Johnson
       end
       
       def test_can_create_more_than_one_without_barfing
-        Johnson::SpiderMonkey::Runtime.new
+        assert_nothing_raised {
+          Johnson::SpiderMonkey::Runtime.new
+        }
       end
     end
   end</diff>
      <filename>test/johnson/spidermonkey/runtime_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,7 +9,7 @@ class JohnsonTest &lt; Test::Unit::TestCase
     assert_equal(4, Johnson.evaluate(&quot;2 + foo&quot;, :foo =&gt; 2))
   end
   
-  def test_evaluate_uses_a_new_context_each_time
+  def test_evaluate_uses_a_new_runtime_each_time
     assert_equal(4, Johnson.evaluate(&quot;foo&quot;, :foo =&gt; 4))
     assert_raise(Johnson::Error) { Johnson.evaluate(&quot;foo&quot;) }
   end</diff>
      <filename>test/johnson_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,6 @@ require 'stringio'
 class ParserTest &lt; Test::Unit::TestCase
   include Johnson::Nodes
   def setup
-    @context = Johnson::Context.new
     @parser = Johnson::Parser
   end
 </diff>
      <filename>test/parser_test.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>lib/johnson/context.rb</filename>
    </removed>
    <removed>
      <filename>test/johnson/context_test.rb</filename>
    </removed>
    <removed>
      <filename>todo/threading_test.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>794e0ac850a2b7e90feeb27c48267194e1c99be8</id>
    </parent>
  </parents>
  <author>
    <name>John Barnette</name>
    <email>jbarnette@gmail.com</email>
  </author>
  <url>http://github.com/jbarnette/johnson/commit/ae3584f2d4e47d82c063c89631bcd8b23acfd9db</url>
  <id>ae3584f2d4e47d82c063c89631bcd8b23acfd9db</id>
  <committed-date>2008-05-30T17:18:16-07:00</committed-date>
  <authored-date>2008-05-30T17:18:16-07:00</authored-date>
  <message>Runtime is the new Context. One context per Ruby thread.</message>
  <tree>019aa9a9739d6de9d366bad61e894779f48d5a2a</tree>
  <committer>
    <name>John Barnette</name>
    <email>jbarnette@gmail.com</email>
  </committer>
</commit>
