bug 678830 - Use JSScript, not script objects, in compile/evaluate API. r=jorendorff
authorIgor Bukanov <igor@mir2.org>
Fri, 02 Sep 2011 08:46:00 +0200
changeset 77181 5a3e49205389d413ed5201a51399300d035b7bf1
parent 77180 ceafc572c5ad64d7cdf7fc6567cfddb3b13e687e
child 77182 09b9a80097637fdb58f01a45d225553a1eeaa446
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersjorendorff
bugs678830
milestone9.0a1
bug 678830 - Use JSScript, not script objects, in compile/evaluate API. r=jorendorff
content/base/src/nsFrameMessageManager.cpp
content/base/src/nsFrameMessageManager.h
dom/base/nsJSEnvironment.cpp
ipc/testshell/XPCShellEnvironment.cpp
js/jsd/jsd_xpc.cpp
js/src/jsapi-tests/testScriptInfo.cpp
js/src/jsapi-tests/testScriptObject.cpp
js/src/jsapi-tests/testTrap.cpp
js/src/jsapi-tests/testVersion.cpp
js/src/jsapi-tests/testXDR.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsdbgapi.h
js/src/jsprvtd.h
js/src/jspubtd.h
js/src/jsxdrapi.cpp
js/src/jsxdrapi.h
js/src/shell/js.cpp
js/src/shell/jsworkers.cpp
js/src/xpconnect/loader/mozJSComponentLoader.cpp
js/src/xpconnect/loader/mozJSLoaderUtils.cpp
js/src/xpconnect/loader/mozJSLoaderUtils.h
js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
js/src/xpconnect/loader/mozJSSubScriptLoader.h
js/src/xpconnect/shell/xpcshell.cpp
js/src/xpconnect/src/nsXPConnect.cpp
js/src/xpconnect/tests/TestXPC.cpp
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -645,27 +645,27 @@ ContentScriptErrorReporter(JSContext* aC
     error.Append(aMessage);
   }
 
   fprintf(stderr, "%s\n", error.get());
   fflush(stderr);
 #endif
 }
 
-nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>*
+nsDataHashtable<nsStringHashKey, nsFrameJSScriptExecutorHolder*>*
   nsFrameScriptExecutor::sCachedScripts = nsnull;
 nsRefPtr<nsScriptCacheCleaner> nsFrameScriptExecutor::sScriptCacheCleaner;
 
 void
 nsFrameScriptExecutor::DidCreateCx()
 {
   NS_ASSERTION(mCx, "Should have mCx!");
   if (!sCachedScripts) {
     sCachedScripts =
-      new nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>;
+      new nsDataHashtable<nsStringHashKey, nsFrameJSScriptExecutorHolder*>;
     sCachedScripts->Init();
 
     sScriptCacheCleaner = new nsScriptCacheCleaner();
   }
 }
 
 void
 nsFrameScriptExecutor::DestroyCx()
@@ -684,21 +684,21 @@ nsFrameScriptExecutor::DestroyCx()
     }
   }
   mCx = nsnull;
   mGlobal = nsnull;
 }
 
 static PLDHashOperator
 CachedScriptUnrooter(const nsAString& aKey,
-                       nsFrameScriptExecutorJSObjectHolder*& aData,
+                       nsFrameJSScriptExecutorHolder*& aData,
                        void* aUserArg)
 {
   JSContext* cx = static_cast<JSContext*>(aUserArg);
-  JS_RemoveObjectRoot(cx, &(aData->mObject));
+  JS_RemoveScriptRoot(cx, &(aData->mScript));
   delete aData;
   return PL_DHASH_REMOVE;
 }
 
 // static
 void
 nsFrameScriptExecutor::Shutdown()
 {
@@ -725,27 +725,27 @@ nsFrameScriptExecutor::Shutdown()
 
 void
 nsFrameScriptExecutor::LoadFrameScriptInternal(const nsAString& aURL)
 {
   if (!mGlobal || !mCx || !sCachedScripts) {
     return;
   }
 
-  nsFrameScriptExecutorJSObjectHolder* holder = sCachedScripts->Get(aURL);
+  nsFrameJSScriptExecutorHolder* holder = sCachedScripts->Get(aURL);
   if (holder) {
     nsContentUtils::ThreadJSContextStack()->Push(mCx);
     {
       // Need to scope JSAutoRequest to happen after Push but before Pop,
       // at least for now. See bug 584673.
       JSAutoRequest ar(mCx);
       JSObject* global = nsnull;
       mGlobal->GetJSObject(&global);
       if (global) {
-        (void) JS_ExecuteScript(mCx, global, holder->mObject, nsnull);
+        (void) JS_ExecuteScript(mCx, global, holder->mScript, nsnull);
       }
     }
     JSContext* unused;
     nsContentUtils::ThreadJSContextStack()->Pop(&unused);
     return;
   }
 
   nsCString url = NS_ConvertUTF16toUTF8(aURL);
@@ -793,37 +793,37 @@ nsFrameScriptExecutor::LoadFrameScriptIn
       mGlobal->GetJSObject(&global);
       if (global) {
         JSPrincipals* jsprin = nsnull;
         mPrincipal->GetJSPrincipals(mCx, &jsprin);
 
         uint32 oldopts = JS_GetOptions(mCx);
         JS_SetOptions(mCx, oldopts | JSOPTION_NO_SCRIPT_RVAL);
 
-        JSObject* scriptObj =
+        JSScript* script =
           JS_CompileUCScriptForPrincipals(mCx, nsnull, jsprin,
                                          (jschar*)dataString.get(),
                                           dataString.Length(),
                                           url.get(), 1);
 
         JS_SetOptions(mCx, oldopts);
 
-        if (scriptObj) {
+        if (script) {
           nsCAutoString scheme;
           uri->GetScheme(scheme);
           // We don't cache data: scripts!
           if (!scheme.EqualsLiteral("data")) {
-            nsFrameScriptExecutorJSObjectHolder* holder =
-              new nsFrameScriptExecutorJSObjectHolder(scriptObj);
+            nsFrameJSScriptExecutorHolder* holder =
+              new nsFrameJSScriptExecutorHolder(script);
             // Root the object also for caching.
-            JS_AddNamedObjectRoot(mCx, &(holder->mObject),
+            JS_AddNamedScriptRoot(mCx, &(holder->mScript),
                                   "Cached message manager script");
             sCachedScripts->Put(aURL, holder);
           }
-          (void) JS_ExecuteScript(mCx, global, scriptObj, nsnull);
+          (void) JS_ExecuteScript(mCx, global, script, nsnull);
         }
         //XXX Argh, JSPrincipals are manually refcounted!
         JSPRINCIPALS_DROP(mCx, jsprin);
       }
     } 
     JSContext* unused;
     nsContentUtils::ThreadJSContextStack()->Pop(&unused);
   }
--- a/content/base/src/nsFrameMessageManager.h
+++ b/content/base/src/nsFrameMessageManager.h
@@ -192,23 +192,23 @@ public:
 
 void
 ContentScriptErrorReporter(JSContext* aCx,
                            const char* aMessage,
                            JSErrorReport* aReport);
 
 class nsScriptCacheCleaner;
 
-struct nsFrameScriptExecutorJSObjectHolder
+struct nsFrameJSScriptExecutorHolder
 {
-  nsFrameScriptExecutorJSObjectHolder(JSObject* aObject) : mObject(aObject)
-  { MOZ_COUNT_CTOR(nsFrameScriptExecutorJSObjectHolder); }
-  ~nsFrameScriptExecutorJSObjectHolder()
-  { MOZ_COUNT_DTOR(nsFrameScriptExecutorJSObjectHolder); }
-  JSObject* mObject;
+  nsFrameJSScriptExecutorHolder(JSScript* aScript) : mScript(aScript)
+  { MOZ_COUNT_CTOR(nsFrameJSScriptExecutorHolder); }
+  ~nsFrameJSScriptExecutorHolder()
+  { MOZ_COUNT_DTOR(nsFrameJSScriptExecutorHolder); }
+  JSScript* mScript;
 };
 
 class nsFrameScriptExecutor
 {
 public:
   static void Shutdown();
 protected:
   friend class nsFrameScriptCx;
@@ -223,17 +223,17 @@ protected:
   void LoadFrameScriptInternal(const nsAString& aURL);
   static void Traverse(nsFrameScriptExecutor *tmp,
                        nsCycleCollectionTraversalCallback &cb);
   nsCOMPtr<nsIXPConnectJSObjectHolder> mGlobal;
   JSContext* mCx;
   PRUint32 mCxStackRefCnt;
   PRPackedBool mDelayedCxDestroy;
   nsCOMPtr<nsIPrincipal> mPrincipal;
-  static nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>* sCachedScripts;
+  static nsDataHashtable<nsStringHashKey, nsFrameJSScriptExecutorHolder*>* sCachedScripts;
   static nsRefPtr<nsScriptCacheCleaner> sScriptCacheCleaner;
 };
 
 class nsFrameScriptCx
 {
 public:
   nsFrameScriptCx(nsISupports* aOwner, nsFrameScriptExecutor* aExec)
   : mOwner(aOwner), mExec(aExec)
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -1553,29 +1553,29 @@ nsJSContext::CompileScript(const PRUnich
   aScriptObject.drop(); // ensure old object not used on failure...
 
   // SecurityManager said "ok", but don't compile if aVersion is unknown.
   // Since the caller is responsible for parsing the version strings, we just
   // check it isn't JSVERSION_UNKNOWN.
   if (ok && ((JSVersion)aVersion) != JSVERSION_UNKNOWN) {
     JSAutoRequest ar(mContext);
 
-    JSObject* scriptObj =
+    JSScript* script =
         ::JS_CompileUCScriptForPrincipalsVersion(mContext,
                                                  (JSObject *)aScopeObject,
                                                  jsprin,
                                                  (jschar*) aText,
                                                  aTextLength,
                                                  aURL,
                                                  aLineNo,
                                                  JSVersion(aVersion));
-    if (scriptObj) {
+    if (script) {
       NS_ASSERTION(aScriptObject.getScriptTypeID()==JAVASCRIPT,
                    "Expecting JS script object holder");
-      rv = aScriptObject.set(scriptObj);
+      rv = aScriptObject.set(script);
     } else {
       rv = NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   // Whew!  Finally done.
   JSPRINCIPALS_DROP(mContext, jsprin);
   return rv;
@@ -1615,29 +1615,31 @@ nsJSContext::ExecuteScript(void *aScript
   }
 
   // The result of evaluation, used only if there were no errors.  This need
   // not be a GC root currently, provided we run the GC only from the
   // operation callback or from ScriptEvaluated.
   jsval val;
   JSBool ok;
 
-  JSObject *scriptObj = (JSObject*)aScriptObject;
+  JSScript *script = static_cast<JSScript *>(aScriptObject);
   nsCOMPtr<nsIPrincipal> principal;
 
-  rv = sSecurityManager->GetObjectPrincipal(mContext, scriptObj, getter_AddRefs(principal));
+  rv = sSecurityManager->GetObjectPrincipal(mContext,
+                                            JS_GetObjectFromScript(script),
+                                            getter_AddRefs(principal));
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = sSecurityManager->PushContextPrincipal(mContext, nsnull, principal);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsJSContext::TerminationFuncHolder holder(this);
   JSAutoRequest ar(mContext);
   ++mExecuteDepth;
-  ok = ::JS_ExecuteScript(mContext, (JSObject *)aScopeObject, scriptObj, &val);
+  ok = ::JS_ExecuteScript(mContext, (JSObject *)aScopeObject, script, &val);
 
   if (ok) {
     // If all went well, convert val to a string (XXXbe unless undefined?).
     rv = JSValueToAString(mContext, val, aRetValue, aIsUndefined);
   } else {
     ReportPendingException();
 
     if (aIsUndefined) {
@@ -2005,30 +2007,30 @@ nsJSContext::BindCompiledEventHandler(ns
 
   return rv;
 }
 
 // serialization
 nsresult
 nsJSContext::Serialize(nsIObjectOutputStream* aStream, void *aScriptObject)
 {
-    JSObject *mJSObject = (JSObject *)aScriptObject;
-    if (!mJSObject)
+    JSScript *script = static_cast<JSScript *>(aScriptObject);
+    if (!script)
         return NS_ERROR_FAILURE;
 
     nsresult rv;
 
     JSContext* cx = mContext;
     JSXDRState *xdr = ::JS_XDRNewMem(cx, JSXDR_ENCODE);
     if (! xdr)
         return NS_ERROR_OUT_OF_MEMORY;
     xdr->userdata = (void*) aStream;
 
     JSAutoRequest ar(cx);
-    if (! ::JS_XDRScriptObject(xdr, &mJSObject)) {
+    if (! ::JS_XDRScript(xdr, &script)) {
         rv = NS_ERROR_FAILURE;  // likely to be a principals serialization error
     } else {
         // Get the encoded JSXDRState data and write it.  The JSXDRState owns
         // this buffer memory and will free it beneath ::JS_XDRDestroy.
         //
         // If an XPCOM object needs to be written in the midst of the JS XDR
         // encoding process, the C++ code called back from the JS engine (e.g.,
         // nsEncodeJSPrincipals in caps/src/nsJSPrincipals.cpp) will flush data
@@ -2055,17 +2057,17 @@ nsJSContext::Serialize(nsIObjectOutputSt
 
     return rv;
 }
 
 nsresult
 nsJSContext::Deserialize(nsIObjectInputStream* aStream,
                          nsScriptObjectHolder &aResult)
 {
-    JSObject *result = nsnull;
+    JSScript *result = nsnull;
     nsresult rv;
 
     NS_TIME_FUNCTION_MIN(1.0);
 
     PRUint32 size;
     rv = aStream->Read32(&size);
     if (NS_FAILED(rv)) return rv;
 
@@ -2078,17 +2080,17 @@ nsJSContext::Deserialize(nsIObjectInputS
     JSXDRState *xdr = ::JS_XDRNewMem(cx, JSXDR_DECODE);
     if (! xdr) {
         rv = NS_ERROR_OUT_OF_MEMORY;
     } else {
         xdr->userdata = (void*) aStream;
         JSAutoRequest ar(cx);
         ::JS_XDRMemSetData(xdr, data, size);
 
-        if (! ::JS_XDRScriptObject(xdr, &result)) {
+        if (! ::JS_XDRScript(xdr, &result)) {
             rv = NS_ERROR_FAILURE;  // principals deserialization error?
         }
 
         // Update data in case ::JS_XDRScript called back into C++ code to
         // read an XPCOM object.
         //
         // In that case, the serialization process must have flushed a run
         // of counted bytes containing JS data at the point where the XPCOM
--- a/ipc/testshell/XPCShellEnvironment.cpp
+++ b/ipc/testshell/XPCShellEnvironment.cpp
@@ -306,17 +306,17 @@ Dump(JSContext *cx,
 
 static JSBool
 Load(JSContext *cx,
      uintN argc,
      jsval *vp)
 {
     uintN i;
     JSString *str;
-    JSObject *scriptObj;
+    JSScript *script;
     jsval result;
     FILE *file;
 
     JSObject *obj = JS_THIS_OBJECT(cx, vp);
     if (!obj)
         return JS_FALSE;
 
     jsval *argv = JS_ARGV(cx, vp);
@@ -328,24 +328,24 @@ Load(JSContext *cx,
         JSAutoByteString filename(cx, str);
         if (!filename)
             return JS_FALSE;
         file = fopen(filename.ptr(), "r");
         if (!file) {
             JS_ReportError(cx, "cannot open file '%s' for reading", filename.ptr());
             return JS_FALSE;
         }
-        scriptObj = JS_CompileFileHandleForPrincipals(cx, obj, filename.ptr(), file,
-                                                      Environment(cx)->GetPrincipal());
+        script = JS_CompileFileHandleForPrincipals(cx, obj, filename.ptr(), file,
+                                                   Environment(cx)->GetPrincipal());
         fclose(file);
-        if (!scriptObj)
+        if (!script)
             return JS_FALSE;
 
         if (!Environment(cx)->ShouldCompileOnly() &&
-            !JS_ExecuteScript(cx, obj, scriptObj, &result)) {
+            !JS_ExecuteScript(cx, obj, script, &result)) {
             return JS_FALSE;
         }
     }
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSBool
@@ -577,17 +577,17 @@ ProcessFile(JSContext *cx,
             JSObject *obj,
             const char *filename,
             FILE *file,
             JSBool forceTTY)
 {
     XPCShellEnvironment* env = Environment(cx);
     XPCShellEnvironment::AutoContextPusher pusher(env);
 
-    JSObject *scriptObj;
+    JSScript *script;
     jsval result;
     int lineno, startline;
     JSBool ok, hitEOF;
     char *bufp, buffer[4096];
     JSString *str;
 
     if (forceTTY) {
         file = stdin;
@@ -617,21 +617,21 @@ ProcessFile(JSContext *cx,
         JSAutoRequest ar(cx);
 
         JSAutoEnterCompartment ac;
         if (!ac.enter(cx, obj)) {
             NS_ERROR("Failed to enter compartment!");
             return;
         }
 
-        JSObject* scriptObj =
+        JSScript* script =
             JS_CompileFileHandleForPrincipals(cx, obj, filename, file,
                                               env->GetPrincipal());
-        if (scriptObj && !env->ShouldCompileOnly())
-            (void)JS_ExecuteScript(cx, obj, scriptObj, &result);
+        if (script && !env->ShouldCompileOnly())
+            (void)JS_ExecuteScript(cx, obj, script, &result);
 
         return;
     }
 
     /* It's an interactive filehandle; drop into read-eval-print loop. */
     lineno = 1;
     hitEOF = JS_FALSE;
     do {
@@ -659,24 +659,24 @@ ProcessFile(JSContext *cx,
                 break;
             }
             bufp += strlen(bufp);
             lineno++;
         } while (!JS_BufferIsCompilableUnit(cx, JS_FALSE, obj, buffer, strlen(buffer)));
 
         /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
-        scriptObj =
+        script =
             JS_CompileScriptForPrincipals(cx, obj, env->GetPrincipal(), buffer,
                                           strlen(buffer), "typein", startline);
-        if (scriptObj) {
+        if (script) {
             JSErrorReporter older;
 
             if (!env->ShouldCompileOnly()) {
-                ok = JS_ExecuteScript(cx, obj, scriptObj, &result);
+                ok = JS_ExecuteScript(cx, obj, script, &result);
                 if (ok && result != JSVAL_VOID) {
                     /* Suppress error reports from JS_ValueToString(). */
                     older = JS_SetErrorReporter(cx, NULL);
                     str = JS_ValueToString(cx, result);
                     JSAutoByteString bytes;
                     if (str)
                         bytes.encode(cx, str);
                     JS_SetErrorReporter(cx, older);
@@ -1232,31 +1232,31 @@ XPCShellEnvironment::EvaluateString(cons
   JSObject* global = GetGlobalObject();
 
   JSAutoEnterCompartment ac;
   if (!ac.enter(mCx, global)) {
       NS_ERROR("Failed to enter compartment!");
       return false;
   }
 
-  JSObject* scriptObj =
+  JSScript* script =
       JS_CompileUCScriptForPrincipals(mCx, global, GetPrincipal(),
                                       aString.get(), aString.Length(),
                                       "typein", 0);
-  if (!scriptObj) {
+  if (!script) {
      return false;
   }
 
   if (!ShouldCompileOnly()) {
       if (aResult) {
           aResult->Truncate();
       }
 
       jsval result;
-      JSBool ok = JS_ExecuteScript(mCx, global, scriptObj, &result);
+      JSBool ok = JS_ExecuteScript(mCx, global, script, &result);
       if (ok && result != JSVAL_VOID) {
           JSErrorReporter old = JS_SetErrorReporter(mCx, NULL);
           JSString* str = JS_ValueToString(mCx, result);
           nsDependentJSString depStr;
           if (str)
               depStr.init(mCx, str);
           JS_SetErrorReporter(mCx, old);
 
--- a/js/jsd/jsd_xpc.cpp
+++ b/js/jsd/jsd_xpc.cpp
@@ -1037,17 +1037,16 @@ PCMapEntry *
 jsdScript::CreatePPLineMap()
 {    
     JSContext  *cx  = JSD_GetDefaultJSContext (mCx);
     JSAutoRequest ar(cx);
     JSObject   *obj = JS_NewObject(cx, NULL, NULL, NULL);
     JSFunction *fun = JSD_GetJSFunction (mCx, mScript);
     JSScript   *script; /* In JSD compartment */
     PRUint32    baseLine;
-    JSObject   *scriptObj = NULL;
     JSString   *jsstr;
     size_t      length;
     const jschar *chars;
     
     if (fun) {
         uintN nargs;
 
         {
@@ -1088,27 +1087,22 @@ jsdScript::CreatePPLineMap()
             if (!jsstr)
                 return nsnull;
 
             if (!(chars = JS_GetStringCharsAndLength(cx, jsstr, &length)))
                 return nsnull;
         }
 
         JS::Anchor<JSString *> kungFuDeathGrip(jsstr);
-        scriptObj = JS_CompileUCScript (cx, obj, chars, length, "x-jsd:ppbuffer?type=script", 1);
-        if (!scriptObj)
+        script = JS_CompileUCScript (cx, obj, chars, length, "x-jsd:ppbuffer?type=script", 1);
+        if (!script)
             return nsnull;
-        script = JS_GetScriptFromObject(scriptObj);
         baseLine = 1;
     }
 
-    /* Make sure that a non-function script is rooted via scriptObj until the
-     * end of script usage. */
-    JS::Anchor<JSObject *> scriptAnchor(scriptObj);
-
     PRUint32 scriptExtent = JS_GetScriptLineExtent (cx, script);
     jsbytecode* firstPC = JS_LineNumberToPC (cx, script, 0);
     /* allocate worst case size of map (number of lines in script + 1
      * for our 0 record), we'll shrink it with a realloc later. */
     PCMapEntry *lineMap =
         static_cast<PCMapEntry *>
                    (PR_Malloc((scriptExtent + 1) * sizeof (PCMapEntry)));
     PRUint32 lineMapSize = 0;
--- a/js/src/jsapi-tests/testScriptInfo.cpp
+++ b/js/src/jsapi-tests/testScriptInfo.cpp
@@ -29,22 +29,20 @@ CharsMatch(const jschar *p, const char *
     return true;
 }
 
 // Bug 670958 - fix JS_GetScriptLineExtent, among others
 BEGIN_TEST(testScriptInfo)
 {
     uintN startLine = 1000;
 
-    JSObject *scriptObj = JS_CompileScript(cx, global, code, strlen(code),
-                                           __FILE__, startLine);
+    JSScript *script = JS_CompileScript(cx, global, code, strlen(code), __FILE__, startLine);
 
-    CHECK(scriptObj);
+    CHECK(script);
 
-    JSScript *script = JS_GetScriptFromObject(scriptObj);
     jsbytecode *start = JS_LineNumberToPC(cx, script, startLine);
     CHECK_EQUAL(JS_GetScriptBaseLineNumber(cx, script), startLine);
     CHECK_EQUAL(JS_PCToLineNumber(cx, script, start), startLine);
     CHECK_EQUAL(JS_GetScriptLineExtent(cx, script), 10);
     CHECK(strcmp(JS_GetScriptFilename(cx, script), __FILE__) == 0);
     CHECK(CharsMatch(JS_GetScriptSourceMap(cx, script), "http://example.com/path/to/source-map.json"));
 
     return true;
--- a/js/src/jsapi-tests/testScriptObject.cpp
+++ b/js/src/jsapi-tests/testScriptObject.cpp
@@ -10,25 +10,25 @@ struct ScriptObjectFixture : public JSAP
     static jschar uc_code[];
 
     ScriptObjectFixture()
     {
         for (int i = 0; i < code_size; i++)
             uc_code[i] = code[i];
     }
 
-    bool tryScript(JSObject *scriptObj)
+    bool tryScript(JSScript *script)
     {
-        CHECK(scriptObj);
+        CHECK(script);
 
         JS_GC(cx);
 
         /* After a garbage collection, the script should still work. */
         jsval result;
-        CHECK(JS_ExecuteScript(cx, global, scriptObj, &result));
+        CHECK(JS_ExecuteScript(cx, global, script, &result));
 
         return true;
     }
 };
 
 const char ScriptObjectFixture::code[] =
     "(function(a, b){return a+' '+b;}('hello', 'world'))";
 const int ScriptObjectFixture::code_size = sizeof(ScriptObjectFixture::code) - 1;
@@ -82,31 +82,31 @@ END_FIXTURE_TEST(ScriptObjectFixture, bu
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile)
 {
     TempFile tempScript;
     static const char script_filename[] = "temp-bug438633_JS_CompileFile";
     FILE *script_stream = tempScript.open(script_filename);
     CHECK(fputs(code, script_stream) != EOF);
     tempScript.close();
-    JSObject *scriptObj = JS_CompileFile(cx, global, script_filename);
+    JSScript *script = JS_CompileFile(cx, global, script_filename);
     tempScript.remove();
-    return tryScript(scriptObj);
+    return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile_empty)
 {
     TempFile tempScript;
     static const char script_filename[] = "temp-bug438633_JS_CompileFile_empty";
     tempScript.open(script_filename);
     tempScript.close();
-    JSObject *scriptObj = JS_CompileFile(cx, global, script_filename);
+    JSScript *script = JS_CompileFile(cx, global, script_filename);
     tempScript.remove();
-    return tryScript(scriptObj);
+    return tryScript(script);
 }
 END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile_empty)
 
 BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle)
 {
     TempFile tempScript;
     FILE *script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandle");
     CHECK(fputs(code, script_stream) != EOF);
--- a/js/src/jsapi-tests/testTrap.cpp
+++ b/js/src/jsapi-tests/testTrap.cpp
@@ -25,38 +25,37 @@ BEGIN_TEST(testTrap_gc)
 "while (i < 10) {\n"
 "    sum += i;\n"
 "    ++i;\n"
 "}\n"
 "({ result: sum });\n"
         ;
 
     // compile
-    JSObject *scriptObj = JS_CompileScript(cx, global, source, strlen(source), __FILE__, 1);
-    CHECK(scriptObj);
+    JSScript *script = JS_CompileScript(cx, global, source, strlen(source), __FILE__, 1);
+    CHECK(script);
 
     // execute
     jsvalRoot v2(cx);
-    CHECK(JS_ExecuteScript(cx, global, scriptObj, v2.addr()));
+    CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
     CHECK(JSVAL_IS_OBJECT(v2));
     CHECK_EQUAL(emptyTrapCallCount, 0);
 
     // Disable JIT for debugging
     JS_SetOptions(cx, JS_GetOptions(cx) & ~JSOPTION_JIT);
 
     // Enable debug mode
     CHECK(JS_SetDebugMode(cx, JS_TRUE));
 
     static const char trapClosureText[] = "some trap closure";
 
     // scope JSScript  usage to make sure that it is not used after
     // JS_ExecuteScript. This way we avoid using Anchor.
     JSString *trapClosure;
     {
-        JSScript *script = JS_GetScriptFromObject(scriptObj);
         jsbytecode *line2 = JS_LineNumberToPC(cx, script, 1);
         CHECK(line2);
 
         jsbytecode *line6 = JS_LineNumberToPC(cx, script, 5);
         CHECK(line2);
 
         trapClosure = JS_NewStringCopyZ(cx, trapClosureText);
         CHECK(trapClosure);
@@ -64,17 +63,17 @@ BEGIN_TEST(testTrap_gc)
         JS_SetTrap(cx, script, line6, EmptyTrapHandler, STRING_TO_JSVAL(trapClosure));
 
         JS_GC(cx);
 
         CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(trapClosure), trapClosureText));
     }
 
     // execute
-    CHECK(JS_ExecuteScript(cx, global, scriptObj, v2.addr()));
+    CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
     CHECK_EQUAL(emptyTrapCallCount, 11);
 
     JS_GC(cx);
 
     CHECK(JS_FlatStringEqualsAscii(JS_ASSERT_STRING_IS_FLAT(trapClosure), trapClosureText));
 
     return true;
 }
--- a/js/src/jsapi-tests/testVersion.cpp
+++ b/js/src/jsapi-tests/testVersion.cpp
@@ -37,17 +37,17 @@ struct VersionFixture : public JSAPITest
                JS_DefineFunction(cx, global, "checkNewScriptNoXML", CheckNewScriptNoXML, 0, 0) &&
                JS_DefineFunction(cx, global, "overrideVersion15", OverrideVersion15, 0, 0) &&
                JS_DefineFunction(cx, global, "captureVersion", CaptureVersion, 0, 0) &&
                JS_DefineFunction(cx, global, "checkOverride", CheckOverride, 1, 0) &&
                JS_DefineFunction(cx, global, "evalScriptVersion16",
                                  EvalScriptVersion16, 0, 0);
     }
 
-    JSObject *fakeScript(const char *contents, size_t length) {
+    JSScript *fakeScript(const char *contents, size_t length) {
         return JS_CompileScript(cx, global, contents, length, "<test>", 1);
     }
 
     bool hasXML(uintN version) {
         return VersionHasXML(JSVersion(version));
     }
 
     bool hasXML(JSScript *script) {
@@ -70,19 +70,19 @@ struct VersionFixture : public JSAPITest
 
     bool checkVersionIsOverridden() {
         CHECK(cx->isVersionOverridden());
         return true;
     }
 
     /* Check that script compilation results in a version without XML. */
     bool checkNewScriptNoXML() {
-        JSObject *scriptObj = fakeScript("", 0);
-        CHECK(scriptObj);
-        CHECK(!hasXML(JS_GetScriptFromObject(scriptObj)->getVersion()));
+        JSScript *script = fakeScript("", 0);
+        CHECK(script);
+        CHECK(!hasXML(script->getVersion()));
         return true;
     }
 
     bool checkVersionHasXML() {
         CHECK(VersionHasXML(cx->findVersion()));
         return true;
     }
 
@@ -191,19 +191,19 @@ BEGIN_FIXTURE_TEST(VersionFixture, testO
 
     /* Enable XML and compile a script to activate. */
     enableXML();
     const char toActivateChars[] =
         "checkVersionHasXML();"
         "disableXMLOption();"
         "callSetVersion17();"
         "checkNewScriptNoXML();";
-    JSObject *toActivate = fakeScript(toActivateChars, sizeof(toActivateChars) - 1);
+    JSScript *toActivate = fakeScript(toActivateChars, sizeof(toActivateChars) - 1);
     CHECK(toActivate);
-    CHECK(hasXML(JS_GetScriptFromObject(toActivate)));
+    CHECK(hasXML(toActivate));
 
     disableXML();
 
     /* Activate the script. */
     jsval dummy;
     CHECK(JS_ExecuteScript(cx, global, toActivate, &dummy));
     return true;
 }
--- a/js/src/jsapi-tests/testXDR.cpp
+++ b/js/src/jsapi-tests/testXDR.cpp
@@ -11,75 +11,75 @@ BEGIN_TEST(testXDR_bug506491)
     const char *s =
         "function makeClosure(s, name, value) {\n"
         "    eval(s);\n"
         "    return let (n = name, v = value) function () { return String(v); };\n"
         "}\n"
         "var f = makeClosure('0;', 'status', 'ok');\n";
 
     // compile
-    JSObject *scriptObj = JS_CompileScript(cx, global, s, strlen(s), __FILE__, __LINE__);
-    CHECK(scriptObj);
+    JSScript *script = JS_CompileScript(cx, global, s, strlen(s), __FILE__, __LINE__);
+    CHECK(script);
 
     // freeze
     JSXDRState *w = JS_XDRNewMem(cx, JSXDR_ENCODE);
     CHECK(w);
-    CHECK(JS_XDRScriptObject(w, &scriptObj));
+    CHECK(JS_XDRScript(w, &script));
     uint32 nbytes;
     void *p = JS_XDRMemGetData(w, &nbytes);
     CHECK(p);
     void *frozen = JS_malloc(cx, nbytes);
     CHECK(frozen);
     memcpy(frozen, p, nbytes);
     JS_XDRDestroy(w);
 
     // thaw
-    scriptObj = NULL;
+    script = NULL;
     JSXDRState *r = JS_XDRNewMem(cx, JSXDR_DECODE);
     JS_XDRMemSetData(r, frozen, nbytes);
-    CHECK(JS_XDRScriptObject(r, &scriptObj));
+    CHECK(JS_XDRScript(r, &script));
     JS_XDRDestroy(r);  // this frees `frozen`
 
     // execute
     jsvalRoot v2(cx);
-    CHECK(JS_ExecuteScript(cx, global, scriptObj, v2.addr()));
+    CHECK(JS_ExecuteScript(cx, global, script, v2.addr()));
 
     // try to break the Block object that is the parent of f
     JS_GC(cx);
 
     // confirm
     EVAL("f() === 'ok';\n", v2.addr());
     jsvalRoot trueval(cx, JSVAL_TRUE);
     CHECK_SAME(v2, trueval);
     return true;
 }
 END_TEST(testXDR_bug506491)
 
 BEGIN_TEST(testXDR_bug516827)
 {
     // compile an empty script
-    JSObject *scriptObj = JS_CompileScript(cx, global, "", 0, __FILE__, __LINE__);
-    CHECK(scriptObj);
+    JSScript *script = JS_CompileScript(cx, global, "", 0, __FILE__, __LINE__);
+    CHECK(script);
 
     // freeze
     JSXDRState *w = JS_XDRNewMem(cx, JSXDR_ENCODE);
     CHECK(w);
-    CHECK(JS_XDRScriptObject(w, &scriptObj));
+    CHECK(JS_XDRScript(w, &script));
     uint32 nbytes;
     void *p = JS_XDRMemGetData(w, &nbytes);
     CHECK(p);
     void *frozen = JS_malloc(cx, nbytes);
     CHECK(frozen);
     memcpy(frozen, p, nbytes);
     JS_XDRDestroy(w);
 
     // thaw
-    scriptObj = NULL;
+    script = NULL;
     JSXDRState *r = JS_XDRNewMem(cx, JSXDR_DECODE);
     JS_XDRMemSetData(r, frozen, nbytes);
-    CHECK(JS_XDRScriptObject(r, &scriptObj));
+    CHECK(JS_XDRScript(r, &script));
     JS_XDRDestroy(r);  // this frees `frozen`
 
     // execute with null result meaning no result wanted
-    CHECK(JS_ExecuteScript(cx, global, scriptObj, NULL));
+    CHECK(JS_ExecuteScript(cx, global, script, NULL));
     return true;
 }
 END_TEST(testXDR_bug516827)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2081,16 +2081,23 @@ JS_AddNamedStringRoot(JSContext *cx, JSS
 JS_PUBLIC_API(JSBool)
 JS_AddNamedObjectRoot(JSContext *cx, JSObject **rp, const char *name)
 {
     CHECK_REQUEST(cx);
     return js_AddGCThingRoot(cx, (void **)rp, name);
 }
 
 JS_PUBLIC_API(JSBool)
+JS_AddNamedScriptRoot(JSContext *cx, JSScript **rp, const char *name)
+{
+    CHECK_REQUEST(cx);
+    return js_AddGCThingRoot(cx, (void **)rp, name);
+}
+
+JS_PUBLIC_API(JSBool)
 JS_AddNamedGCThingRoot(JSContext *cx, void **rp, const char *name)
 {
     CHECK_REQUEST(cx);
     return js_AddGCThingRoot(cx, (void **)rp, name);
 }
 
 JS_PUBLIC_API(JSBool)
 JS_RemoveValueRoot(JSContext *cx, jsval *vp)
@@ -2109,16 +2116,23 @@ JS_RemoveStringRoot(JSContext *cx, JSStr
 JS_PUBLIC_API(JSBool)
 JS_RemoveObjectRoot(JSContext *cx, JSObject **rp)
 {
     CHECK_REQUEST(cx);
     return js_RemoveRoot(cx->runtime, (void *)rp);
 }
 
 JS_PUBLIC_API(JSBool)
+JS_RemoveScriptRoot(JSContext *cx, JSScript **rp)
+{
+    CHECK_REQUEST(cx);
+    return js_RemoveRoot(cx->runtime, (void *)rp);
+}
+
+JS_PUBLIC_API(JSBool)
 JS_RemoveGCThingRoot(JSContext *cx, void **rp)
 {
     CHECK_REQUEST(cx);
     return js_RemoveRoot(cx->runtime, (void *)rp);
 }
 
 JS_NEVER_INLINE JS_PUBLIC_API(void)
 JS_AnchorPtr(void *p)
@@ -4457,94 +4471,90 @@ struct AutoLastFrameCheck {
 
 inline static uint32
 JS_OPTIONS_TO_TCFLAGS(JSContext *cx)
 {
     return (cx->hasRunOption(JSOPTION_COMPILE_N_GO) ? TCF_COMPILE_N_GO : 0) |
            (cx->hasRunOption(JSOPTION_NO_SCRIPT_RVAL) ? TCF_NO_SCRIPT_RVAL : 0);
 }
 
-static JSObject *
+static JSScript *
 CompileUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj, JSPrincipals *principals,
                                       const jschar *chars, size_t length,
                                       const char *filename, uintN lineno, JSVersion version)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, principals);
     AutoLastFrameCheck lfc(cx);
 
     uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_OBJECT;
-    JSScript *script = Compiler::compileScript(cx, obj, NULL, principals, tcflags,
-                                               chars, length, filename, lineno, version);
-    if (!script)
-        return NULL;
-    JS_ASSERT(script->u.object);
-    return script->u.object;
-}
-
-extern JS_PUBLIC_API(JSObject *)
+    return Compiler::compileScript(cx, obj, NULL, principals, tcflags,
+                                   chars, length, filename, lineno, version);
+}
+
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
                                        JSPrincipals *principals,
                                        const jschar *chars, size_t length,
                                        const char *filename, uintN lineno,
                                        JSVersion version)
 {
     AutoVersionAPI avi(cx, version);
     return CompileUCScriptForPrincipalsCommon(cx, obj, principals, chars, length, filename, lineno,
                                               avi.version());
 }
 
-JS_PUBLIC_API(JSObject *)
+JS_PUBLIC_API(JSScript *)
 JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *principals,
                                 const jschar *chars, size_t length,
                                 const char *filename, uintN lineno)
 {
     return CompileUCScriptForPrincipalsCommon(cx, obj, principals, chars, length, filename, lineno,
                                               cx->findVersion());
 }
 
-JS_PUBLIC_API(JSObject *)
+JS_PUBLIC_API(JSScript *)
 JS_CompileUCScript(JSContext *cx, JSObject *obj, const jschar *chars, size_t length,
                    const char *filename, uintN lineno)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     return JS_CompileUCScriptForPrincipals(cx, obj, NULL, chars, length, filename, lineno);
 }
 
-JS_PUBLIC_API(JSObject *)
+JS_PUBLIC_API(JSScript *)
 JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
                                      JSPrincipals *principals,
                                      const char *bytes, size_t length,
                                      const char *filename, uintN lineno,
                                      JSVersion version)
 {
     AutoVersionAPI ava(cx, version);
     return JS_CompileScriptForPrincipals(cx, obj, principals, bytes, length, filename, lineno);
 }
 
-JS_PUBLIC_API(JSObject *)
+JS_PUBLIC_API(JSScript *)
 JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
                               JSPrincipals *principals,
                               const char *bytes, size_t length,
                               const char *filename, uintN lineno)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
 
     jschar *chars = InflateString(cx, bytes, &length);
     if (!chars)
         return NULL;
-    JSObject *scriptObj =
+    JSScript *script =
         JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length, filename, lineno);
     cx->free_(chars);
-    return scriptObj;
-}
-
-JS_PUBLIC_API(JSObject *)
+    return script;
+}
+
+JS_PUBLIC_API(JSScript *)
 JS_CompileScript(JSContext *cx, JSObject *obj, const char *bytes, size_t length,
                  const char *filename, uintN lineno)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     return JS_CompileScriptForPrincipals(cx, obj, NULL, bytes, length, filename, lineno);
 }
 
 JS_PUBLIC_API(JSBool)
@@ -4595,17 +4605,17 @@ JS_BufferIsCompilableUnit(JSContext *cx,
 #if defined(HAVE_GETC_UNLOCKED)
 # define fast_getc getc_unlocked
 #elif defined(HAVE__GETC_NOLOCK)
 # define fast_getc _getc_nolock
 #else
 # define fast_getc getc
 #endif
 
-static JSObject *
+static JSScript *
 CompileFileHelper(JSContext *cx, JSObject *obj, JSPrincipals *principals,
                   const char* filename, FILE *fp)
 {
     struct stat st;
     int ok = fstat(fileno(fp), &st);
     if (ok != 0)
         return NULL;
 
@@ -4652,23 +4662,20 @@ CompileFileHelper(JSContext *cx, JSObjec
     }
 
     JS_ASSERT(i <= len);
     len = i;
     uint32 tcflags = JS_OPTIONS_TO_TCFLAGS(cx) | TCF_NEED_MUTABLE_SCRIPT | TCF_NEED_SCRIPT_OBJECT;
     script = Compiler::compileScript(cx, obj, NULL, principals, tcflags, buf, len, filename, 1,
                                      cx->findVersion());
     cx->free_(buf);
-    if (!script)
-        return NULL;
-    JS_ASSERT(script->u.object);
-    return script->u.object;
-}
-
-JS_PUBLIC_API(JSObject *)
+    return script;
+}
+
+JS_PUBLIC_API(JSScript *)
 JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj);
     AutoLastFrameCheck lfc(cx);
 
     FILE *fp;
@@ -4678,55 +4685,55 @@ JS_CompileFile(JSContext *cx, JSObject *
         fp = fopen(filename, "r");
         if (!fp) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_OPEN,
                                  filename, "No such file or directory");
             return NULL;
         }
     }
 
-    JSObject *scriptObj = CompileFileHelper(cx, obj, NULL, filename, fp);
+    JSScript *script = CompileFileHelper(cx, obj, NULL, filename, fp);
     if (fp != stdin)
         fclose(fp);
-    return scriptObj;
-}
-
-JS_PUBLIC_API(JSObject *)
+    return script;
+}
+
+JS_PUBLIC_API(JSScript *)
 JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj, const char *filename,
                                   FILE *file, JSPrincipals *principals)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, obj, principals);
     AutoLastFrameCheck lfc(cx);
 
     return CompileFileHelper(cx, obj, principals, filename, file);
 }
 
-JS_PUBLIC_API(JSObject *)
+JS_PUBLIC_API(JSScript *)
 JS_CompileFileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj, const char *filename,
                                          FILE *file, JSPrincipals *principals, JSVersion version)
 {
     AutoVersionAPI ava(cx, version);
     return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, principals);
 }
 
-JS_PUBLIC_API(JSObject *)
+JS_PUBLIC_API(JSScript *)
 JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename, FILE *file)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     return JS_CompileFileHandleForPrincipals(cx, obj, filename, file, NULL);
 }
 
-JS_PUBLIC_API(JSScript *)
-JS_GetScriptFromObject(JSObject *scriptObj)
-{
-    JS_ASSERT(scriptObj->isScript());
-
-    return (JSScript *) scriptObj->getPrivate();
+JS_PUBLIC_API(JSObject *)
+JS_GetObjectFromScript(JSScript *script)
+{
+    JS_ASSERT(script->u.object);
+
+    return script->u.object;
 }
 
 static JSFunction *
 CompileUCFunctionForPrincipalsCommon(JSContext *cx, JSObject *obj,
                                      JSPrincipals *principals, const char *name,
                                      uintN nargs, const char **argnames,
                                      const jschar *chars, size_t length,
                                      const char *filename, uintN lineno, JSVersion version)
@@ -4857,22 +4864,16 @@ JS_DecompileScript(JSContext *cx, JSScri
         str = js_GetPrinterOutput(jp);
     else
         str = NULL;
     js_DestroyPrinter(jp);
     return str;
 }
 
 JS_PUBLIC_API(JSString *)
-JS_DecompileScriptObject(JSContext *cx, JSObject *scriptObj, const char *name, uintN indent)
-{
-    return JS_DecompileScript(cx, scriptObj->getScript(), name, indent);
-}
-
-JS_PUBLIC_API(JSString *)
 JS_DecompileFunction(JSContext *cx, JSFunction *fun, uintN indent)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
     assertSameCompartment(cx, fun);
     return js_DecompileToString(cx, "JS_DecompileFunction", fun,
                                 indent & ~JS_DONT_PRETTY_PRINT,
                                 !(indent & JS_DONT_PRETTY_PRINT),
@@ -4887,32 +4888,32 @@ JS_DecompileFunctionBody(JSContext *cx, 
     assertSameCompartment(cx, fun);
     return js_DecompileToString(cx, "JS_DecompileFunctionBody", fun,
                                 indent & ~JS_DONT_PRETTY_PRINT,
                                 !(indent & JS_DONT_PRETTY_PRINT),
                                 false, false, js_DecompileFunctionBody);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_ExecuteScript(JSContext *cx, JSObject *obj, JSObject *scriptObj, jsval *rval)
+JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
 {
     JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
     CHECK_REQUEST(cx);
-    assertSameCompartment(cx, obj, scriptObj);
+    assertSameCompartment(cx, obj, script);
     AutoLastFrameCheck lfc(cx);
 
-    return Execute(cx, scriptObj->getScript(), *obj, Valueify(rval));
-}
-
-JS_PUBLIC_API(JSBool)
-JS_ExecuteScriptVersion(JSContext *cx, JSObject *obj, JSObject *scriptObj, jsval *rval,
+    return Execute(cx, script, *obj, Valueify(rval));
+}
+
+JS_PUBLIC_API(JSBool)
+JS_ExecuteScriptVersion(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval,
                         JSVersion version)
 {
     AutoVersionAPI ava(cx, version);
-    return JS_ExecuteScript(cx, obj, scriptObj, rval);
+    return JS_ExecuteScript(cx, obj, script, rval);
 }
 
 bool
 EvaluateUCScriptForPrincipalsCommon(JSContext *cx, JSObject *obj,
                                     JSPrincipals *principals,
                                     const jschar *chars, uintN length,
                                     const char *filename, uintN lineno,
                                     jsval *rval, JSVersion compileVersion)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1318,28 +1318,34 @@ JS_AddNamedValueRoot(JSContext *cx, jsva
 
 extern JS_PUBLIC_API(JSBool)
 JS_AddNamedStringRoot(JSContext *cx, JSString **rp, const char *name);
 
 extern JS_PUBLIC_API(JSBool)
 JS_AddNamedObjectRoot(JSContext *cx, JSObject **rp, const char *name);
 
 extern JS_PUBLIC_API(JSBool)
+JS_AddNamedScriptRoot(JSContext *cx, JSScript **rp, const char *name);
+
+extern JS_PUBLIC_API(JSBool)
 JS_AddNamedGCThingRoot(JSContext *cx, void **rp, const char *name);
 
 extern JS_PUBLIC_API(JSBool)
 JS_RemoveValueRoot(JSContext *cx, jsval *vp);
 
 extern JS_PUBLIC_API(JSBool)
 JS_RemoveStringRoot(JSContext *cx, JSString **rp);
 
 extern JS_PUBLIC_API(JSBool)
 JS_RemoveObjectRoot(JSContext *cx, JSObject **rp);
 
 extern JS_PUBLIC_API(JSBool)
+JS_RemoveScriptRoot(JSContext *cx, JSScript **rp);
+
+extern JS_PUBLIC_API(JSBool)
 JS_RemoveGCThingRoot(JSContext *cx, void **rp);
 
 /* TODO: remove these APIs */
 
 extern JS_FRIEND_API(JSBool)
 js_AddRootRT(JSRuntime *rt, jsval *vp, const char *name);
 
 extern JS_FRIEND_API(JSBool)
@@ -2717,70 +2723,73 @@ JS_CloneFunctionObject(JSContext *cx, JS
  * JS_TRUE.  The intent is to support interactive compilation - accumulate
  * lines in a buffer until JS_BufferIsCompilableUnit is true, then pass it to
  * the compiler.
  */
 extern JS_PUBLIC_API(JSBool)
 JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8,
                           JSObject *obj, const char *bytes, size_t length);
 
-extern JS_PUBLIC_API(JSObject *)
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileScript(JSContext *cx, JSObject *obj,
                  const char *bytes, size_t length,
                  const char *filename, uintN lineno);
 
-extern JS_PUBLIC_API(JSObject *)
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
                               JSPrincipals *principals,
                               const char *bytes, size_t length,
                               const char *filename, uintN lineno);
 
-extern JS_PUBLIC_API(JSObject *)
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
                                      JSPrincipals *principals,
                                      const char *bytes, size_t length,
                                      const char *filename, uintN lineno,
                                      JSVersion version);
 
-extern JS_PUBLIC_API(JSObject *)
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileUCScript(JSContext *cx, JSObject *obj,
                    const jschar *chars, size_t length,
                    const char *filename, uintN lineno);
 
-extern JS_PUBLIC_API(JSObject *)
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
                                 JSPrincipals *principals,
                                 const jschar *chars, size_t length,
                                 const char *filename, uintN lineno);
 
-extern JS_PUBLIC_API(JSObject *)
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
                                        JSPrincipals *principals,
                                        const jschar *chars, size_t length,
                                        const char *filename, uintN lineno,
                                        JSVersion version);
 
-extern JS_PUBLIC_API(JSObject *)
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename);
 
-extern JS_PUBLIC_API(JSObject *)
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileFileHandle(JSContext *cx, JSObject *obj, const char *filename,
                      FILE *fh);
 
-extern JS_PUBLIC_API(JSObject *)
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileFileHandleForPrincipals(JSContext *cx, JSObject *obj,
                                   const char *filename, FILE *fh,
                                   JSPrincipals *principals);
 
-extern JS_PUBLIC_API(JSObject *)
+extern JS_PUBLIC_API(JSScript *)
 JS_CompileFileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj,
                                          const char *filename, FILE *fh,
                                          JSPrincipals *principals,
                                          JSVersion version);
 
+extern JS_PUBLIC_API(JSObject *)
+JS_GetObjectFromScript(JSScript *script);
+
 extern JS_PUBLIC_API(JSFunction *)
 JS_CompileFunction(JSContext *cx, JSObject *obj, const char *name,
                    uintN nargs, const char **argnames,
                    const char *bytes, size_t length,
                    const char *filename, uintN lineno);
 
 extern JS_PUBLIC_API(JSFunction *)
 JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *obj,
@@ -2806,17 +2815,17 @@ extern JS_PUBLIC_API(JSFunction *)
 JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj,
                                          JSPrincipals *principals, const char *name,
                                          uintN nargs, const char **argnames,
                                          const jschar *chars, size_t length,
                                          const char *filename, uintN lineno,
                                          JSVersion version);
 
 extern JS_PUBLIC_API(JSString *)
-JS_DecompileScriptObject(JSContext *cx, JSObject *scriptObj, const char *name, uintN indent);
+JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, uintN indent);
 
 /*
  * API extension: OR this into indent to avoid pretty-printing the decompiled
  * source resulting from JS_DecompileFunction{,Body}.
  */
 #define JS_DONT_PRETTY_PRINT    ((uintN)0x8000)
 
 extern JS_PUBLIC_API(JSString *)
@@ -2856,20 +2865,20 @@ JS_DecompileFunctionBody(JSContext *cx, 
  * points with signatures matching the following six, and that doesn't seem
  * worth the code bloat cost.  Such new entry points would probably have less
  * obvious names, too, so would not tend to be used.  The JS_SetOption call,
  * OTOH, can be more easily hacked into existing code that does not depend on
  * the bug; such code can continue to use the familiar JS_EvaluateScript,
  * etc., entry points.
  */
 extern JS_PUBLIC_API(JSBool)
-JS_ExecuteScript(JSContext *cx, JSObject *obj, JSObject *scriptObj, jsval *rval);
+JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval);
 
 extern JS_PUBLIC_API(JSBool)
-JS_ExecuteScriptVersion(JSContext *cx, JSObject *obj, JSObject *scriptObj, jsval *rval,
+JS_ExecuteScriptVersion(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval,
                         JSVersion version);
 
 /*
  * Execute either the function-defining prolog of a script, or the script's
  * main body, but not both.
  */
 typedef enum JSExecPart { JSEXEC_PROLOG, JSEXEC_MAIN } JSExecPart;
 
--- a/js/src/jsdbgapi.h
+++ b/js/src/jsdbgapi.h
@@ -85,19 +85,16 @@ class JS_PUBLIC_API(AutoEnterFrameCompar
     bool enter(JSContext *cx, JSStackFrame *target);
 };
 
 } /* namespace JS */
 
 JS_BEGIN_EXTERN_C
 #endif
 
-extern JS_PUBLIC_API(JSScript *)
-JS_GetScriptFromObject(JSObject *scriptObject);
-
 extern JS_PUBLIC_API(JSString *)
 JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, uintN indent);
 
 /*
  * Currently, we only support runtime-wide debugging. In the future, we should
  * be able to support compartment-wide debugging.
  */
 extern JS_PUBLIC_API(void)
--- a/js/src/jsprvtd.h
+++ b/js/src/jsprvtd.h
@@ -80,17 +80,16 @@ typedef struct JSArgumentFormatMap  JSAr
 typedef struct JSCodeGenerator      JSCodeGenerator;
 typedef struct JSGCThing            JSGCThing;
 typedef struct JSGenerator          JSGenerator;
 typedef struct JSNativeEnumerator   JSNativeEnumerator;
 typedef struct JSFunctionBox        JSFunctionBox;
 typedef struct JSObjectBox          JSObjectBox;
 typedef struct JSParseNode          JSParseNode;
 typedef struct JSProperty           JSProperty;
-typedef struct JSScript             JSScript;
 typedef struct JSSharpObjectMap     JSSharpObjectMap;
 typedef struct JSThread             JSThread;
 typedef struct JSTreeContext        JSTreeContext;
 typedef struct JSTryNote            JSTryNote;
 
 /* Friend "Advanced API" typedefs. */
 typedef struct JSAtomState          JSAtomState;
 typedef struct JSCodeSpec           JSCodeSpec;
--- a/js/src/jspubtd.h
+++ b/js/src/jspubtd.h
@@ -158,16 +158,17 @@ typedef struct JSObjectMap       JSObjec
 typedef struct JSRuntime         JSRuntime;
 typedef struct JSStackFrame      JSStackFrame;
 typedef struct JSXDRState        JSXDRState;
 typedef struct JSExceptionState  JSExceptionState;
 typedef struct JSLocaleCallbacks JSLocaleCallbacks;
 typedef struct JSSecurityCallbacks JSSecurityCallbacks;
 typedef struct JSCompartment     JSCompartment;
 typedef struct JSCrossCompartmentCall JSCrossCompartmentCall;
+typedef struct JSScript          JSScript;
 typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;
 typedef struct JSStructuredCloneReader JSStructuredCloneReader;
 typedef struct JSStructuredCloneCallbacks JSStructuredCloneCallbacks;
 typedef struct JSPropertyName    JSPropertyName;
 
 #ifdef __cplusplus
 typedef class JSWrapper          JSWrapper;
 typedef class JSCrossCompartmentWrapper JSCrossCompartmentWrapper;
--- a/js/src/jsxdrapi.cpp
+++ b/js/src/jsxdrapi.cpp
@@ -677,27 +677,27 @@ XDRScriptState::XDRScriptState(JSXDRStat
 XDRScriptState::~XDRScriptState()
 {
     xdr->state = NULL;
     if (xdr->mode == JSXDR_DECODE && filename && !filenameSaved)
         xdr->cx->free_((void *)filename);
 }
 
 JS_PUBLIC_API(JSBool)
-JS_XDRScriptObject(JSXDRState *xdr, JSObject **scriptObjp)
+JS_XDRScript(JSXDRState *xdr, JSScript **scriptp)
 {
     JS_ASSERT(!xdr->state);
 
     JSScript *script;
     uint32 magic;
     if (xdr->mode == JSXDR_DECODE) {
         script = NULL;
-        *scriptObjp = NULL;
+        *scriptp = NULL;
     } else {
-        script = (*scriptObjp)->getScript();
+        script = *scriptp;
         magic = JSXDR_MAGIC_SCRIPT_CURRENT;
     }
 
     if (!JS_XDRUint32(xdr, &magic))
         return false;
 
     if (magic != JSXDR_MAGIC_SCRIPT_CURRENT) {
         /* We do not provide binary compatibility with older scripts. */
@@ -713,21 +713,21 @@ JS_XDRScriptObject(JSXDRState *xdr, JSOb
         state.filename = script->filename;
     if (!JS_XDRCStringOrNull(xdr, (char **) &state.filename))
         return false;
 
     if (!js_XDRScript(xdr, &script))
         return false;
 
     if (xdr->mode == JSXDR_DECODE) {
-        *scriptObjp = js_NewScriptObject(xdr->cx, script);
-        if (!*scriptObjp)
+        if (!js_NewScriptObject(xdr->cx, script))
             return false;
         js_CallNewScriptHook(xdr->cx, script, NULL);
-        Debugger::onNewScript(xdr->cx, script, *scriptObjp, Debugger::NewHeldScript);
+        Debugger::onNewScript(xdr->cx, script, script->u.object, Debugger::NewHeldScript);
+        *scriptp = script;
     }
 
     return true;
 }
 
 #define CLASS_REGISTRY_MIN      8
 #define CLASS_INDEX_TO_ID(i)    ((i)+1)
 #define CLASS_ID_TO_INDEX(id)   ((id)-1)
--- a/js/src/jsxdrapi.h
+++ b/js/src/jsxdrapi.h
@@ -181,17 +181,17 @@ JS_XDRStringOrNull(JSXDRState *xdr, JSSt
 
 extern JS_PUBLIC_API(JSBool)
 JS_XDRDouble(JSXDRState *xdr, jsdouble *dp);
 
 extern JS_PUBLIC_API(JSBool)
 JS_XDRValue(JSXDRState *xdr, jsval *vp);
 
 extern JS_PUBLIC_API(JSBool)
-JS_XDRScriptObject(JSXDRState *xdr, JSObject **scriptObjp);
+JS_XDRScript(JSXDRState *xdr, JSScript **scriptp);
 
 extern JS_PUBLIC_API(JSBool)
 JS_XDRRegisterClass(JSXDRState *xdr, JSClass *clasp, uint32 *lp);
 
 extern JS_PUBLIC_API(uint32)
 JS_XDRFindClassIdByName(JSXDRState *xdr, const char *name);
 
 extern JS_PUBLIC_API(JSClass *)
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -422,17 +422,17 @@ SkipUTF8BOM(FILE* file)
     if (ch1 != EOF)
         ungetc(ch1, file);
 }
 
 static void
 Process(JSContext *cx, JSObject *obj, const char *filename, bool forceTTY)
 {
     JSBool ok, hitEOF;
-    JSObject *scriptObj;
+    JSScript *script;
     jsval result;
     JSString *str;
     char *buffer;
     size_t size;
     jschar *uc_buffer;
     size_t uc_len;
     int lineno;
     int startline;
@@ -472,20 +472,20 @@ Process(JSContext *cx, JSObject *obj, co
                     break;
             }
         }
         ungetc(ch, file);
 
         int64 t1 = PRMJ_Now();
         oldopts = JS_GetOptions(cx);
         JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-        scriptObj = JS_CompileFileHandle(cx, obj, filename, file);
+        script = JS_CompileFileHandle(cx, obj, filename, file);
         JS_SetOptions(cx, oldopts);
-        if (scriptObj && !compileOnly) {
-            (void) JS_ExecuteScript(cx, obj, scriptObj, NULL);
+        if (script && !compileOnly) {
+            (void) JS_ExecuteScript(cx, obj, script, NULL);
             int64 t2 = PRMJ_Now() - t1;
             if (printTiming)
                 printf("runtime = %.3f ms\n", double(t2) / PRMJ_USEC_PER_MSEC);
         }
 
         goto cleanup;
     }
 
@@ -570,23 +570,22 @@ Process(JSContext *cx, JSObject *obj, co
 
         /* Clear any pending exception from previous failed compiles. */
         JS_ClearPendingException(cx);
 
         /* Even though we're interactive, we have a compile-n-go opportunity. */
         oldopts = JS_GetOptions(cx);
         if (!compileOnly)
             JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO);
-        scriptObj = JS_CompileUCScript(cx, obj, uc_buffer, uc_len, "typein",
-                                       startline);
+        script = JS_CompileUCScript(cx, obj, uc_buffer, uc_len, "typein", startline);
         if (!compileOnly)
             JS_SetOptions(cx, oldopts);
 
-        if (scriptObj && !compileOnly) {
-            ok = JS_ExecuteScript(cx, obj, scriptObj, &result);
+        if (script && !compileOnly) {
+            ok = JS_ExecuteScript(cx, obj, script, &result);
             if (ok && !JSVAL_IS_VOID(result)) {
                 str = JS_ValueToSource(cx, result);
                 ok = !!str;
                 if (ok) {
                     JSAutoByteString bytes(cx, str);
                     ok = !!bytes;
                     if (ok)
                         fprintf(gOutFile, "%s\n", bytes.ptr());
@@ -781,22 +780,22 @@ Load(JSContext *cx, uintN argc, jsval *v
             return false;
         argv[i] = STRING_TO_JSVAL(str);
         JSAutoByteString filename(cx, str);
         if (!filename)
             return JS_FALSE;
         errno = 0;
         uint32 oldopts = JS_GetOptions(cx);
         JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-        JSObject *scriptObj = JS_CompileFile(cx, thisobj, filename.ptr());
+        JSScript *script = JS_CompileFile(cx, thisobj, filename.ptr());
         JS_SetOptions(cx, oldopts);
-        if (!scriptObj)
+        if (!script)
             return false;
 
-        if (!compileOnly && !JS_ExecuteScript(cx, thisobj, scriptObj, NULL))
+        if (!compileOnly && !JS_ExecuteScript(cx, thisobj, script, NULL))
             return false;
     }
 
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return true;
 }
 
 static JSBool
@@ -950,19 +949,19 @@ Run(JSContext *cx, uintN argc, jsval *vp
     if (!ucbuf)
         return false;
 
     JS::Anchor<JSString *> a_str(str);
     uint32 oldopts = JS_GetOptions(cx);
     JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
 
     int64 startClock = PRMJ_Now();
-    JSObject *scriptObj = JS_CompileUCScript(cx, thisobj, ucbuf, buflen, filename.ptr(), 1);
+    JSScript *script = JS_CompileUCScript(cx, thisobj, ucbuf, buflen, filename.ptr(), 1);
     JS_SetOptions(cx, oldopts);
-    if (!scriptObj || !JS_ExecuteScript(cx, thisobj, scriptObj, NULL))
+    if (!script || !JS_ExecuteScript(cx, thisobj, script, NULL))
         return false;
 
     int64 endClock = PRMJ_Now();
     JS_SET_RVAL(cx, vp, DOUBLE_TO_JSVAL((endClock - startClock) / double(PRMJ_USEC_PER_MSEC)));
     return true;
 }
 
 /*
@@ -1546,20 +1545,20 @@ MakeFinalizeObserver(JSContext *cx, uint
 static JSBool
 FinalizeCount(JSContext *cx, uintN argc, jsval *vp)
 {
     *vp = INT_TO_JSVAL(finalizeCount);
     return true;
 }
 
 static JSScript *
-ValueToScript(JSContext *cx, jsval v)
+ValueToScript(JSContext *cx, jsval v, JSFunction **funp = NULL)
 {
     JSScript *script = NULL;
-    JSFunction *fun;
+    JSFunction *fun = NULL;
 
     if (!JSVAL_IS_PRIMITIVE(v)) {
         JSObject *obj = JSVAL_TO_OBJECT(v);
         JSClass *clasp = JS_GET_CLASS(cx, obj);
 
         if (clasp == Jsvalify(&ScriptClass)) {
             script = (JSScript *) JS_GetPrivate(cx, obj);
         } else if (clasp == Jsvalify(&GeneratorClass)) {
@@ -1574,16 +1573,18 @@ ValueToScript(JSContext *cx, jsval v)
         if (!fun)
             return NULL;
         script = fun->maybeScript();
         if (!script) {
             JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL,
                                  JSSMSG_SCRIPTS_ONLY);
         }
     }
+    if (fun && funp)
+        *funp = fun;
 
     return script;
 }
 
 static JSBool
 SetDebug(JSContext *cx, uintN argc, jsval *vp)
 {
     jsval *argv = JS_ARGV(cx, vp);
@@ -1997,223 +1998,238 @@ TryNotes(JSContext *cx, JSScript *script
         Sprint(sp, " %-7s %6u %8u %8u\n",
                TryNoteNames[tn->kind], tn->stackDepth,
                tn->start, tn->start + tn->length);
     } while (++tn != tnlimit);
     return JS_TRUE;
 }
 
 static bool
-DisassembleValue(JSContext *cx, jsval v, bool lines, bool recursive, Sprinter *sp)
+DisassembleScript(JSContext *cx, JSScript *script, JSFunction *fun, bool lines, bool recursive,
+                  Sprinter *sp)
 {
-    JSScript *script = ValueToScript(cx, v);
-    if (!script)
-        return false;
-    if (!JSVAL_IS_PRIMITIVE(v) && JSVAL_TO_OBJECT(v)->isFunction()) {
-        JSFunction *fun = JS_ValueToFunction(cx, v);
-        if (fun && (fun->flags & ~7U)) {
-            uint16 flags = fun->flags;
-            Sprint(sp, "flags:");
-
+    if (fun && (fun->flags & ~7U)) {
+        uint16 flags = fun->flags;
+        Sprint(sp, "flags:");
+        
 #define SHOW_FLAG(flag) if (flags & JSFUN_##flag) Sprint(sp, " " #flag);
-
-            SHOW_FLAG(LAMBDA);
-            SHOW_FLAG(HEAVYWEIGHT);
-            SHOW_FLAG(EXPR_CLOSURE);
-            SHOW_FLAG(TRCINFO);
-
+        
+        SHOW_FLAG(LAMBDA);
+        SHOW_FLAG(HEAVYWEIGHT);
+        SHOW_FLAG(EXPR_CLOSURE);
+        SHOW_FLAG(TRCINFO);
+        
 #undef SHOW_FLAG
-
-            if (fun->isInterpreted()) {
-                if (fun->isNullClosure())
-                    Sprint(sp, " NULL_CLOSURE");
-                else if (fun->isFlatClosure())
-                    Sprint(sp, " FLAT_CLOSURE");
-
-                JSScript *script = fun->script();
-                if (script->bindings.hasUpvars()) {
-                    Sprint(sp, "\nupvars: {\n");
-
-                    Vector<JSAtom *> localNames(cx);
-                    if (!script->bindings.getLocalNameArray(cx, &localNames))
-                        return false;
-
-                    JSUpvarArray *uva = script->upvars();
-                    uintN upvar_base = script->bindings.countArgsAndVars();
-
-                    for (uint32 i = 0, n = uva->length; i < n; i++) {
-                        JSAtom *atom = localNames[upvar_base + i];
-                        UpvarCookie cookie = uva->vector[i];
-                        JSAutoByteString printable;
-                        if (js_AtomToPrintableString(cx, atom, &printable)) {
-                            Sprint(sp, "  %s: {skip:%u, slot:%u},\n",
-                                   printable.ptr(), cookie.level(), cookie.slot());
-                        }
-                    }
-
-                    Sprint(sp, "}");
+        
+        if (fun->isNullClosure())
+            Sprint(sp, " NULL_CLOSURE");
+        else if (fun->isFlatClosure())
+            Sprint(sp, " FLAT_CLOSURE");
+        
+        JSScript *script = fun->script();
+        if (script->bindings.hasUpvars()) {
+            Sprint(sp, "\nupvars: {\n");
+            
+            Vector<JSAtom *> localNames(cx);
+            if (!script->bindings.getLocalNameArray(cx, &localNames))
+                return false;
+            
+            JSUpvarArray *uva = script->upvars();
+            uintN upvar_base = script->bindings.countArgsAndVars();
+            
+            for (uint32 i = 0, n = uva->length; i < n; i++) {
+                JSAtom *atom = localNames[upvar_base + i];
+                UpvarCookie cookie = uva->vector[i];
+                JSAutoByteString printable;
+                if (js_AtomToPrintableString(cx, atom, &printable)) {
+                    Sprint(sp, "  %s: {skip:%u, slot:%u},\n",
+                           printable.ptr(), cookie.level(), cookie.slot());
                 }
             }
-            Sprint(sp, "\n");
+            
+            Sprint(sp, "}");
         }
+        Sprint(sp, "\n");
     }
 
     if (!js_Disassemble(cx, script, lines, sp))
         return false;
     SrcNotes(cx, script, sp);
     TryNotes(cx, script, sp);
 
     if (recursive && JSScript::isValidOffset(script->objectsOffset)) {
         JSObjectArray *objects = script->objects();
         for (uintN i = 0; i != objects->length; ++i) {
             JSObject *obj = objects->vector[i];
             if (obj->isFunction()) {
                 Sprint(sp, "\n");
-                if (!DisassembleValue(cx, OBJECT_TO_JSVAL(obj), lines, recursive, sp))
+                JSFunction *fun = obj->getFunctionPrivate();
+                JSScript *nested = fun->maybeScript();
+                if (!DisassembleScript(cx, nested, fun, lines, recursive, sp))
                     return false;
             }
         }
     }
     return true;
 }
 
+namespace {
+
+struct DisassembleOptionParser {
+    uintN   argc;
+    jsval   *argv;
+    bool    lines;
+    bool    recursive;
+
+    DisassembleOptionParser(uintN argc, jsval *argv)
+      : argc(argc), argv(argv), lines(false), recursive(false) {}
+
+    bool parse(JSContext *cx) {
+        /* Read options off early arguments */
+        while (argc > 0 && JSVAL_IS_STRING(argv[0])) {
+            JSString *str = JSVAL_TO_STRING(argv[0]);
+            JSFlatString *flatStr = JS_FlattenString(cx, str);
+            if (!flatStr)
+                return false;
+            if (JS_FlatStringEqualsAscii(flatStr, "-l"))
+                lines = true;
+            else if (JS_FlatStringEqualsAscii(flatStr, "-r"))
+                recursive = true;
+            else
+                break;
+            argv++, argc--;
+        }
+        return true;
+    }
+};
+
+} /* anonymous namespace */
+
 static JSBool
 DisassembleToString(JSContext *cx, uintN argc, jsval *vp)
 {
-    jsval *argv = JS_ARGV(cx, vp);
-
-    /* Read options off early arguments */
-    bool lines = false, recursive = false;
-    while (argc > 0 && JSVAL_IS_STRING(argv[0])) {
-        JSString *str = JSVAL_TO_STRING(argv[0]);
-        JSFlatString *flatStr = JS_FlattenString(cx, str);
-        if (!flatStr)
-            return JS_FALSE;
-        lines |= !!JS_FlatStringEqualsAscii(flatStr, "-l");
-        recursive |= !!JS_FlatStringEqualsAscii(flatStr, "-r");
-        if (!lines && !recursive)
-            break;
-        argv++, argc--;
-    }
+    DisassembleOptionParser p(argc, JS_ARGV(cx, vp));
+    if (!p.parse(cx))
+        return false;
 
     void *mark = JS_ARENA_MARK(&cx->tempPool);
     Sprinter sprinter;
     INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
     Sprinter *sp = &sprinter;
 
     bool ok = true;
-    if (argc == 0) {
+    if (p.argc == 0) {
         /* Without arguments, disassemble the current script. */
         if (JSStackFrame *frame = JS_GetScriptedCaller(cx, NULL)) {
             JSScript *script = JS_GetFrameScript(cx, frame);
-            if (js_Disassemble(cx, script, lines, sp)) {
+            if (js_Disassemble(cx, script, p.lines, sp)) {
                 SrcNotes(cx, script, sp);
                 TryNotes(cx, script, sp);
             } else {
                 ok = false;
             }
         }
     } else {
-        for (uintN i = 0; i < argc; i++)
-            ok = ok && DisassembleValue(cx, argv[i], lines, recursive, sp);
+        for (uintN i = 0; i < p.argc; i++) {
+            JSFunction *fun;
+            JSScript *script = ValueToScript(cx, p.argv[i], &fun);
+            ok = ok && script && DisassembleScript(cx, script, fun, p.lines, p.recursive, sp);
+        }
     }
 
     JSString *str = ok ? JS_NewStringCopyZ(cx, sprinter.base) : NULL;
     JS_ARENA_RELEASE(&cx->tempPool, mark);
     if (!str)
         return false;
     JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(str));
     return true;
 }
 
 static JSBool
 Disassemble(JSContext *cx, uintN argc, jsval *vp)
 {
-    jsval *argv = JS_ARGV(cx, vp);
-
-    /* Read options off early arguments */
-    bool lines = false, recursive = false;
-    while (argc > 0 && JSVAL_IS_STRING(argv[0])) {
-        JSString *str = JSVAL_TO_STRING(argv[0]);
-        JSFlatString *flatStr = JS_FlattenString(cx, str);
-        if (!flatStr)
-            return JS_FALSE;
-        lines |= !!JS_FlatStringEqualsAscii(flatStr, "-l");
-        recursive |= !!JS_FlatStringEqualsAscii(flatStr, "-r");
-        if (!lines && !recursive)
-            break;
-        argv++, argc--;
-    }
+    DisassembleOptionParser p(argc, JS_ARGV(cx, vp));
+    if (!p.parse(cx))
+        return false;
 
     void *mark = JS_ARENA_MARK(&cx->tempPool);
     Sprinter sprinter;
     INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
     Sprinter *sp = &sprinter;
 
     bool ok = true;
-    if (argc == 0) {
+    if (p.argc == 0) {
         /* Without arguments, disassemble the current script. */
         if (JSStackFrame *frame = JS_GetScriptedCaller(cx, NULL)) {
             JSScript *script = JS_GetFrameScript(cx, frame);
-            if (js_Disassemble(cx, script, lines, sp)) {
+            if (js_Disassemble(cx, script, p.lines, sp)) {
                 SrcNotes(cx, script, sp);
                 TryNotes(cx, script, sp);
             } else {
                 ok = false;
             }
         }
     } else {
-        for (uintN i = 0; i < argc; i++)
-            ok = ok && DisassembleValue(cx, argv[i], lines, recursive, sp);
+        for (uintN i = 0; i < p.argc; i++) {
+            JSFunction *fun;
+            JSScript *script = ValueToScript(cx, p.argv[i], &fun);
+            ok = ok && script && DisassembleScript(cx, script, fun, p.lines, p.recursive, sp);
+        }
     }
 
     if (ok)
         fprintf(stdout, "%s\n", sprinter.base);
     JS_ARENA_RELEASE(&cx->tempPool, mark);
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return ok;
 }
 
 static JSBool
 DisassFile(JSContext *cx, uintN argc, jsval *vp)
 {
-    jsval *argv = JS_ARGV(cx, vp);
-
-    if (!argc) {
+    /* Support extra options at the start, just like Dissassemble. */
+    DisassembleOptionParser p(argc, JS_ARGV(cx, vp));
+    if (!p.parse(cx))
+        return false;
+    
+    if (!p.argc) {
         JS_SET_RVAL(cx, vp, JSVAL_VOID);
         return JS_TRUE;
     }
 
-    /* Support extra options at the start, just like Dissassemble. */
-    uintN _argc = argc;
-    argv += argc-1;
-    argc = 1;
-
     JSObject *thisobj = JS_THIS_OBJECT(cx, vp);
     if (!thisobj)
         return JS_FALSE;
 
-    JSString *str = JS_ValueToString(cx, argv[0]);
+    JSString *str = JS_ValueToString(cx, p.argv[0]);
     if (!str)
         return JS_FALSE;
     JSAutoByteString filename(cx, str);
     if (!filename)
         return JS_FALSE;
 
     uint32 oldopts = JS_GetOptions(cx);
     JS_SetOptions(cx, oldopts | JSOPTION_COMPILE_N_GO | JSOPTION_NO_SCRIPT_RVAL);
-    JSObject *scriptObj = JS_CompileFile(cx, thisobj, filename.ptr());
+    JSScript *script = JS_CompileFile(cx, thisobj, filename.ptr());
     JS_SetOptions(cx, oldopts);
-    if (!scriptObj)
+    if (!script)
         return false;
 
-    argv[0] = OBJECT_TO_JSVAL(scriptObj);
-    JSBool ok = Disassemble(cx, _argc, vp); /* gross, but works! */
+    void *mark = JS_ARENA_MARK(&cx->tempPool);
+    Sprinter sprinter;
+    INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0);
+    bool ok = DisassembleScript(cx, script, NULL, p.lines, p.recursive, &sprinter);
+    if (ok)
+        fprintf(stdout, "%s\n", sprinter.base);
+    JS_ARENA_RELEASE(&cx->tempPool, mark);
+    if (!ok)
+        return false;
+    
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
-    return ok;
+    return true;
 }
 
 static JSBool
 DisassWithSrc(JSContext *cx, uintN argc, jsval *vp)
 {
 #define LINE_BUF_LEN 512
     uintN i, len, line1, line2, bupline;
     JSScript *script;
--- a/js/src/shell/jsworkers.cpp
+++ b/js/src/shell/jsworkers.cpp
@@ -889,22 +889,22 @@ class InitEvent : public Event
         jsval s;
         if (!deserializeData(cx, &s))
             return fail;
         JS_ASSERT(JSVAL_IS_STRING(s));
         JSAutoByteString filename(cx, JSVAL_TO_STRING(s));
         if (!filename)
             return fail;
 
-        JSObject *scriptObj = JS_CompileFile(cx, child->getGlobal(), filename.ptr());
-        if (!scriptObj)
+        JSScript *script = JS_CompileFile(cx, child->getGlobal(), filename.ptr());
+        if (!script)
             return fail;
 
         AutoValueRooter rval(cx);
-        JSBool ok = JS_ExecuteScript(cx, child->getGlobal(), scriptObj, Jsvalify(rval.addr()));
+        JSBool ok = JS_ExecuteScript(cx, child->getGlobal(), script, Jsvalify(rval.addr()));
         return Result(ok);
     }
 };
 
 class DownMessageEvent : public Event
 {
   public:
     static DownMessageEvent *create(JSContext *cx, Worker *child, jsval data) {
--- a/js/src/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/src/xpconnect/loader/mozJSComponentLoader.cpp
@@ -830,42 +830,42 @@ mozJSComponentLoader::GlobalForLocation(
     // Expose the URI from which the script was imported through a special
     // variable that we insert into the JSM.
     JSString *exposedUri = JS_NewStringCopyN(cx, nativePath.get(), nativePath.Length());
     if (!JS_DefineProperty(cx, global, "__URI__",
                            STRING_TO_JSVAL(exposedUri), nsnull, nsnull, 0))
         return NS_ERROR_FAILURE;
 
 
-    JSObject *scriptObj = nsnull;
+    JSScript *script = nsnull;
 
     // Before compiling the script, first check to see if we have it in
     // the startupcache.  Note: as a rule, startupcache errors are not fatal
     // to loading the script, since we can always slow-load.
     
     PRBool writeToCache = PR_FALSE;
     StartupCache* cache = StartupCache::GetSingleton();
 
     nsCAutoString cachePath(kJSCachePrefix);
     rv = PathifyURI(aURI, cachePath);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (cache) {
-        rv = ReadCachedScript(cache, cachePath, cx, &scriptObj);
+        rv = ReadCachedScript(cache, cachePath, cx, &script);
         if (NS_SUCCEEDED(rv)) {
             LOG(("Successfully loaded %s from startupcache\n", nativePath.get()));
         } else {
             // This is ok, it just means the script is not yet in the
             // cache. Could mean that the cache was corrupted and got removed,
             // but either way we're going to write this out.
             writeToCache = PR_TRUE;
         }
     }
 
-    if (!scriptObj) {
+    if (!script) {
         // The script wasn't in the cache , so compile it now.
         LOG(("Slow loading %s\n", nativePath.get()));
 
         // If |exception| is non-null, then our caller wants us to propagate
         // any exceptions out to our caller. Ensure that the engine doesn't
         // eagerly report the exception.
         uint32 oldopts = JS_GetOptions(cx);
         JS_SetOptions(cx, oldopts | JSOPTION_NO_SCRIPT_RVAL |
@@ -914,17 +914,17 @@ mozJSComponentLoader::GlobalForLocation(
 
             char *buf = static_cast<char*>(PR_MemMap(map, 0, fileSize32));
             if (!buf) {
                 NS_WARNING("Failed to map file");
                 JS_SetOptions(cx, oldopts);
                 return NS_ERROR_FAILURE;
             }
 
-            scriptObj = JS_CompileScriptForPrincipalsVersion(
+            script = JS_CompileScriptForPrincipalsVersion(
               cx, global, jsPrincipals, buf, fileSize32, nativePath.get(), 1,
               JSVERSION_LATEST);
 
             PR_MemUnmap(buf, fileSize32);
 
 #else  /* HAVE_PR_MEMMAP */
 
             /**
@@ -934,17 +934,17 @@ mozJSComponentLoader::GlobalForLocation(
 
             FILE *fileHandle;
             rv = aComponentFile->OpenANSIFileDesc("r", &fileHandle);
             if (NS_FAILED(rv)) {
                 JS_SetOptions(cx, oldopts);
                 return NS_ERROR_FILE_NOT_FOUND;
             }
 
-            scriptObj = JS_CompileFileHandleForPrincipalsVersion(
+            script = JS_CompileFileHandleForPrincipalsVersion(
               cx, global, nativePath.get(), fileHandle, jsPrincipals, JSVERSION_LATEST);
 
             /* JS will close the filehandle after compilation is complete. */
 #endif /* HAVE_PR_MEMMAP */
         } else {
             nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
             NS_ENSURE_SUCCESS(rv, rv);
 
@@ -970,60 +970,60 @@ mozJSComponentLoader::GlobalForLocation(
 
             /* read the file in one swoop */
             rv = scriptStream->Read(buf, len, &bytesRead);
             if (bytesRead != len)
                 return NS_BASE_STREAM_OSERROR;
 
             buf[len] = '\0';
 
-            scriptObj = JS_CompileScriptForPrincipalsVersion(
+            script = JS_CompileScriptForPrincipalsVersion(
               cx, global, jsPrincipals, buf, bytesRead, nativePath.get(), 1,
               JSVERSION_LATEST);
         }
         // Propagate the exception, if one exists. Also, don't leave the stale
         // exception on this context.
         JS_SetOptions(cx, oldopts);
-        if (!scriptObj && exception) {
+        if (!script && exception) {
             JS_GetPendingException(cx, exception);
             JS_ClearPendingException(cx);
         }
     }
 
-    if (!scriptObj) {
+    if (!script) {
 #ifdef DEBUG_shaver_off
         fprintf(stderr, "mJCL: script compilation of %s FAILED\n",
                 nativePath.get());
 #endif
         return NS_ERROR_FAILURE;
     }
 
 #ifdef DEBUG_shaver_off
     fprintf(stderr, "mJCL: compiled JS component %s\n",
             nativePath.get());
 #endif
 
     if (writeToCache) {
         // We successfully compiled the script, so cache it. 
-        rv = WriteCachedScript(cache, cachePath, cx, scriptObj);
+        rv = WriteCachedScript(cache, cachePath, cx, script);
 
         // Don't treat failure to write as fatal, since we might be working
         // with a read-only cache.
         if (NS_SUCCEEDED(rv)) {
             LOG(("Successfully wrote to cache\n"));
         } else {
             LOG(("Failed to write to cache\n"));
         }
     }
 
     // Assign aGlobal here so that it's available to recursive imports.
     // See bug 384168.
     *aGlobal = global;
 
-    if (!JS_ExecuteScriptVersion(cx, global, scriptObj, NULL, JSVERSION_LATEST)) {
+    if (!JS_ExecuteScriptVersion(cx, global, script, NULL, JSVERSION_LATEST)) {
 #ifdef DEBUG_shaver_off
         fprintf(stderr, "mJCL: failed to execute %s\n", nativePath.get());
 #endif
         *aGlobal = nsnull;
         return NS_ERROR_FAILURE;
     }
 
     /* Freed when we remove from the table. */
--- a/js/src/xpconnect/loader/mozJSLoaderUtils.cpp
+++ b/js/src/xpconnect/loader/mozJSLoaderUtils.cpp
@@ -43,35 +43,35 @@
 
 #include "mozilla/scache/StartupCache.h"
 #include "mozilla/scache/StartupCacheUtils.h"
 
 using namespace mozilla::scache;
 
 static nsresult
 ReadScriptFromStream(JSContext *cx, nsIObjectInputStream *stream,
-                     JSObject **scriptObj)
+                     JSScript **script)
 {
-    *scriptObj = nsnull;
+    *script = nsnull;
 
     PRUint32 size;
     nsresult rv = stream->Read32(&size);
     NS_ENSURE_SUCCESS(rv, rv);
 
     char *data;
     rv = stream->ReadBytes(size, &data);
     NS_ENSURE_SUCCESS(rv, rv);
 
     JSXDRState *xdr = JS_XDRNewMem(cx, JSXDR_DECODE);
     NS_ENSURE_TRUE(xdr, NS_ERROR_OUT_OF_MEMORY);
 
     xdr->userdata = stream;
     JS_XDRMemSetData(xdr, data, size);
 
-    if (!JS_XDRScriptObject(xdr, scriptObj)) {
+    if (!JS_XDRScript(xdr, script)) {
         rv = NS_ERROR_FAILURE;
     }
 
     // Update data in case ::JS_XDRScript called back into C++ code to
     // read an XPCOM object.
     //
     // In that case, the serialization process must have flushed a run
     // of counted bytes containing JS data at the point where the XPCOM
@@ -98,26 +98,26 @@ ReadScriptFromStream(JSContext *cx, nsIO
     // If data is null now, it must have been freed while deserializing an
     // XPCOM object (e.g., a principal) beneath ::JS_XDRScript.
     nsMemory::Free(data);
 
     return rv;
 }
 
 static nsresult
-WriteScriptToStream(JSContext *cx, JSObject *scriptObj,
+WriteScriptToStream(JSContext *cx, JSScript *script,
                     nsIObjectOutputStream *stream)
 {
     JSXDRState *xdr = JS_XDRNewMem(cx, JSXDR_ENCODE);
     NS_ENSURE_TRUE(xdr, NS_ERROR_OUT_OF_MEMORY);
 
     xdr->userdata = stream;
     nsresult rv = NS_OK;
 
-    if (JS_XDRScriptObject(xdr, &scriptObj)) {
+    if (JS_XDRScript(xdr, &script)) {
         // Get the encoded JSXDRState data and write it.  The JSXDRState owns
         // this buffer memory and will free it beneath ::JS_XDRDestroy.
         //
         // If an XPCOM object needs to be written in the midst of the JS XDR
         // encoding process, the C++ code called back from the JS engine (e.g.,
         // nsEncodeJSPrincipals in caps/src/nsJSPrincipals.cpp) will flush data
         // from the JSXDRState to aStream, then write the object, then return
         // to JS XDR code with xdr reset so new JS data is encoded at the front
@@ -140,49 +140,49 @@ WriteScriptToStream(JSContext *cx, JSObj
         rv = NS_ERROR_FAILURE; // likely to be a principals serialization error
     }
 
     JS_XDRDestroy(xdr);
     return rv;
 }
 
 nsresult
-ReadCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx, JSObject **scriptObj)
+ReadCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx, JSScript **script)
 {
     nsresult rv;
 
     nsAutoArrayPtr<char> buf;
     PRUint32 len;
     rv = cache->GetBuffer(PromiseFlatCString(uri).get(), getter_Transfers(buf),
                           &len);
     if (NS_FAILED(rv)) {
         return rv; // don't warn since NOT_AVAILABLE is an ok error
     }
 
     nsCOMPtr<nsIObjectInputStream> ois;
     rv = NewObjectInputStreamFromBuffer(buf, len, getter_AddRefs(ois));
     NS_ENSURE_SUCCESS(rv, rv);
     buf.forget();
 
-    return ReadScriptFromStream(cx, ois, scriptObj);
+    return ReadScriptFromStream(cx, ois, script);
 }
 
 nsresult
-WriteCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx, JSObject *scriptObj)
+WriteCachedScript(StartupCache* cache, nsACString &uri, JSContext *cx, JSScript *script)
 {
     nsresult rv;
 
     nsCOMPtr<nsIObjectOutputStream> oos;
     nsCOMPtr<nsIStorageStream> storageStream;
     rv = NewObjectOutputWrappedStorageStream(getter_AddRefs(oos),
                                              getter_AddRefs(storageStream),
                                              true);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = WriteScriptToStream(cx, scriptObj, oos);
+    rv = WriteScriptToStream(cx, script, oos);
     oos->Close();
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoArrayPtr<char> buf;
     PRUint32 len;
     rv = NewBufferFromStorageStream(storageStream, getter_Transfers(buf), &len);
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/js/src/xpconnect/loader/mozJSLoaderUtils.h
+++ b/js/src/xpconnect/loader/mozJSLoaderUtils.h
@@ -47,14 +47,14 @@ class nsIURI;
 namespace mozilla {
 namespace scache {
 class StartupCache;
 }
 }
 
 nsresult
 ReadCachedScript(mozilla::scache::StartupCache* cache, nsACString &uri,
-                 JSContext *cx, JSObject **scriptObj);
+                 JSContext *cx, JSScript **script);
 
 nsresult
 WriteCachedScript(mozilla::scache::StartupCache* cache, nsACString &uri,
-                  JSContext *cx, JSObject *scriptObj);
+                  JSContext *cx, JSScript *script);
 #endif /* mozJSLoaderUtils_h */
--- a/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
+++ b/js/src/xpconnect/loader/mozJSSubScriptLoader.cpp
@@ -103,17 +103,17 @@ ReportError(JSContext *cx, const char *m
     JS_SetPendingException(cx, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, msg)));
     return NS_OK;
 }
 
 nsresult
 mozJSSubScriptLoader::ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_obj,
                                  jschar *charset, const char *uriStr,
                                  nsIIOService *serv, nsIPrincipal *principal,
-                                 JSObject **scriptObjp)
+                                 JSScript **scriptp)
 {
     nsCOMPtr<nsIChannel>     chan;
     nsCOMPtr<nsIInputStream> instream;
     JSPrincipals    *jsPrincipals;
     JSErrorReporter  er;
 
     nsresult rv;
     // Instead of calling NS_OpenURI, we create the channel ourselves and call
@@ -159,23 +159,23 @@ mozJSSubScriptLoader::ReadScript(nsIURI 
                 nsnull, reinterpret_cast<const PRUint8*>(buf.get()), len,
                 nsDependentString(reinterpret_cast<PRUnichar*>(charset)), nsnull, script);
 
         if (NS_FAILED(rv)) {
             JSPRINCIPALS_DROP(cx, jsPrincipals);
             return ReportError(cx, LOAD_ERROR_BADCHARSET);
         }
 
-        *scriptObjp =
+        *scriptp =
             JS_CompileUCScriptForPrincipals(cx, target_obj, jsPrincipals,
                                             reinterpret_cast<const jschar*>(script.get()),
                                             script.Length(), uriStr, 1);
     } else {
-        *scriptObjp = JS_CompileScriptForPrincipals(cx, target_obj, jsPrincipals, buf.get(),
-                                                         len, uriStr, 1);
+        *scriptp = JS_CompileScriptForPrincipals(cx, target_obj, jsPrincipals, buf.get(),
+                                                 len, uriStr, 1);
     }
 
     JSPRINCIPALS_DROP(cx, jsPrincipals);
 
     /* repent for our evil deeds */
     JS_SetErrorReporter(cx, er);
 
     return NS_OK;
@@ -393,43 +393,41 @@ mozJSSubScriptLoader::LoadSubScript (con
         nsCAutoString tmp(JS_GetScriptFilename(cx, script));
         tmp.AppendLiteral(" -> ");
         tmp.Append(uriStr);
 
         uriStr = tmp;
     }
 
     bool writeScript = false;
-    JSObject *scriptObj = nsnull;
     JSVersion version = cx->findVersion();
     nsCAutoString cachePath;
     cachePath.AppendPrintf("jssubloader/%d", version);
     PathifyURI(uri, cachePath);
 
+    script = nsnull;
     if (cache)
-        rv = ReadCachedScript(cache, cachePath, cx, &scriptObj);
-    if (!scriptObj) {
+        rv = ReadCachedScript(cache, cachePath, cx, &script);
+    if (!script) {
         rv = ReadScript(uri, cx, target_obj, charset, (char *)uriStr.get(), serv,
-                        principal, &scriptObj);
+                        principal, &script);
         writeScript = true;
     }
 
-    if (NS_FAILED(rv) || !scriptObj)
+    if (NS_FAILED(rv) || !script)
         return rv;
 
-    ok = false;
-    if (scriptObj)
-        ok = JS_ExecuteScriptVersion(cx, target_obj, scriptObj, rval, version);
+    ok = JS_ExecuteScriptVersion(cx, target_obj, script, rval, version);
 
     if (ok) {
         JSAutoEnterCompartment rac;
         if (!rac.enter(cx, result_obj) || !JS_WrapValue(cx, rval))
             return NS_ERROR_UNEXPECTED; 
     }
 
     if (cache && ok && writeScript) {
-        WriteCachedScript(cache, cachePath, cx, scriptObj);
+        WriteCachedScript(cache, cachePath, cx, script);
     }
 
     cc->SetReturnValueWasSet (ok);
     return NS_OK;
 }
 
--- a/js/src/xpconnect/loader/mozJSSubScriptLoader.h
+++ b/js/src/xpconnect/loader/mozJSSubScriptLoader.h
@@ -62,12 +62,12 @@ public:
     // all the interface method declarations...
     NS_DECL_ISUPPORTS
     NS_DECL_MOZIJSSUBSCRIPTLOADER
 
 private:
     nsresult ReadScript(nsIURI *uri, JSContext *cx, JSObject *target_obj,
                         jschar *charset, const char *uriStr,
                         nsIIOService *serv, nsIPrincipal *principal,
-                        JSObject **scriptObjp);
+                        JSScript **scriptp);
 
     nsCOMPtr<nsIPrincipal> mSystemPrincipal;
 };
--- a/js/src/xpconnect/shell/xpcshell.cpp
+++ b/js/src/xpconnect/shell/xpcshell.cpp
@@ -472,24 +472,24 @@ Load(JSContext *cx, uintN argc, jsval *v
         if (!filename)
             return false;
         FILE *file = fopen(filename.ptr(), "r");
         if (!file) {
             JS_ReportError(cx, "cannot open file '%s' for reading",
                            filename.ptr());
             return false;
         }
-        JSObject *scriptObj = JS_CompileFileHandleForPrincipals(cx, obj, filename.ptr(),
-                                                                file, gJSPrincipals);
+        JSScript *script = JS_CompileFileHandleForPrincipals(cx, obj, filename.ptr(),
+                                                             file, gJSPrincipals);
         fclose(file);
-        if (!scriptObj)
+        if (!script)
             return false;
 
         jsval result;
-        if (!compileOnly && !JS_ExecuteScript(cx, obj, scriptObj, &result))
+        if (!compileOnly && !JS_ExecuteScript(cx, obj, script, &result))
             return false;
     }
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return true;
 }
 
 static JSBool
 Version(JSContext *cx, uintN argc, jsval *vp)
@@ -1006,17 +1006,17 @@ my_GetErrorMessage(void *userRef, const 
         else
             return NULL;
 }
 
 static void
 ProcessFile(JSContext *cx, JSObject *obj, const char *filename, FILE *file,
             JSBool forceTTY)
 {
-    JSObject *scriptObj;
+    JSScript *script;
     jsval result;
     int lineno, startline;
     JSBool ok, hitEOF;
     char *bufp, buffer[4096];
     JSString *str;
 
     if (forceTTY) {
         file = stdin;
@@ -1039,21 +1039,21 @@ ProcessFile(JSContext *cx, JSObject *obj
             while((ch = fgetc(file)) != EOF) {
                 if(ch == '\n' || ch == '\r')
                     break;
             }
         }
         ungetc(ch, file);
         DoBeginRequest(cx);
 
-        scriptObj = JS_CompileFileHandleForPrincipals(cx, obj, filename, file,
-                                                      gJSPrincipals);
+        script = JS_CompileFileHandleForPrincipals(cx, obj, filename, file,
+                                                   gJSPrincipals);
 
-        if (scriptObj && !compileOnly)
-            (void)JS_ExecuteScript(cx, obj, scriptObj, &result);
+        if (script && !compileOnly)
+            (void)JS_ExecuteScript(cx, obj, script, &result);
         DoEndRequest(cx);
 
         return;
     }
 
     /* It's an interactive filehandle; drop into read-eval-print loop. */
     lineno = 1;
     hitEOF = JS_FALSE;
@@ -1075,23 +1075,23 @@ ProcessFile(JSContext *cx, JSObject *obj
             }
             bufp += strlen(bufp);
             lineno++;
         } while (!JS_BufferIsCompilableUnit(cx, JS_FALSE, obj, buffer, strlen(buffer)));
 
         DoBeginRequest(cx);
         /* Clear any pending exception from previous failed compiles.  */
         JS_ClearPendingException(cx);
-        scriptObj = JS_CompileScriptForPrincipals(cx, obj, gJSPrincipals, buffer,
-                                                  strlen(buffer), "typein", startline);
-        if (scriptObj) {
+        script = JS_CompileScriptForPrincipals(cx, obj, gJSPrincipals, buffer,
+                                               strlen(buffer), "typein", startline);
+        if (script) {
             JSErrorReporter older;
 
             if (!compileOnly) {
-                ok = JS_ExecuteScript(cx, obj, scriptObj, &result);
+                ok = JS_ExecuteScript(cx, obj, script, &result);
                 if (ok && result != JSVAL_VOID) {
                     /* Suppress error reports from JS_ValueToString(). */
                     older = JS_SetErrorReporter(cx, NULL);
                     str = JS_ValueToString(cx, result);
                     JS_SetErrorReporter(cx, older);
                     JSAutoByteString bytes;
                     if (str && bytes.encode(cx, str))
                         fprintf(gOutFile, "%s\n", bytes.ptr());
--- a/js/src/xpconnect/src/nsXPConnect.cpp
+++ b/js/src/xpconnect/src/nsXPConnect.cpp
@@ -421,36 +421,36 @@ nsXPConnect::GarbageCollect()
 {
     Collect();
     return NS_OK;
 }
 
 // JSTRACE_XML can recursively hold on to more JSTRACE_XML objects, adding it to
 // the cycle collector avoids stack overflow.
 inline bool
-AddToCCKind(uint32 kind)
+AddToCCKind(JSGCTraceKind kind)
 {
-    return kind == JSTRACE_OBJECT || kind == JSTRACE_XML;
+    return kind == JSTRACE_OBJECT || kind == JSTRACE_XML || kind == JSTRACE_SCRIPT;
 }
 
 #ifdef DEBUG_CC
 struct NoteJSRootTracer : public JSTracer
 {
     NoteJSRootTracer(PLDHashTable *aObjects,
                      nsCycleCollectionTraversalCallback& cb)
       : mObjects(aObjects),
         mCb(cb)
     {
     }
     PLDHashTable* mObjects;
     nsCycleCollectionTraversalCallback& mCb;
 };
 
 static void
-NoteJSRoot(JSTracer *trc, void *thing, uint32 kind)
+NoteJSRoot(JSTracer *trc, void *thing, JSGCTraceKind kind)
 {
     if(AddToCCKind(kind))
     {
         NoteJSRootTracer *tracer = static_cast<NoteJSRootTracer*>(trc);
         PLDHashEntryHdr *entry = PL_DHashTableOperate(tracer->mObjects, thing,
                                                       PL_DHASH_ADD);
         if(entry && !reinterpret_cast<PLDHashEntryStub*>(entry)->key)
         {
--- a/js/src/xpconnect/tests/TestXPC.cpp
+++ b/js/src/xpconnect/tests/TestXPC.cpp
@@ -109,18 +109,18 @@ Load(JSContext *cx, uintN argc, jsval *v
     for (i = 0; i < argc; i++) {
         str = JS_ValueToString(cx, argv[i]);
         if (!str)
             return JS_FALSE;
         argv[i] = STRING_TO_JSVAL(str);
         JSAutoByteString filename(cx, str);
         if (!filename)
             return false;
-        JSObject *scriptObj = JS_CompileFile(cx, obj, filename.ptr());
-        if (!scriptObj || !JS_ExecuteScript(cx, obj, scriptObj, &result))
+        JSScript *script = JS_CompileFile(cx, obj, filename.ptr());
+        if (!script || !JS_ExecuteScript(cx, obj, script, &result))
             return false;
     }
     JS_SET_RVAL(cx, vp, JSVAL_VOID);
     return JS_TRUE;
 }
 
 static JSFunctionSpec glob_functions[] = {
     {"print",           Print,          0,0},