Improve logging in jssh, allow loading of remote scripts, fix leak. Bug
authorbzbarsky@mit.edu
Mon, 23 Jul 2007 21:07:57 -0700
changeset 3823 ee8927c596ade21a5bcedba25a55a9d42bcb8189
parent 3822 cc97475054b04a020c7d10115bc4f1606a5173f8
child 3824 e7016a309584aae3f021ee207f297b0ddc154d74
push id1
push userbsmedberg@mozilla.com
push dateThu, 20 Mar 2008 16:49:24 +0000
treeherdermozilla-central@61007906a1f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs369816
milestone1.9a7pre
Improve logging in jssh, allow loading of remote scripts, fix leak. Bug 369816, patch by Chris Shoemaker <chris.shoemaker@cox.net>, r=afri, sr=bzbarsky
extensions/jssh/nsJSSh.cpp
extensions/jssh/nsJSSh.h
extensions/jssh/nsJSShServer.cpp
--- a/extensions/jssh/nsJSSh.cpp
+++ b/extensions/jssh/nsJSSh.cpp
@@ -44,16 +44,21 @@
 #include "nsIScriptSecurityManager.h"
 #include "nsIIOService.h"
 #include "nsNetCID.h"
 #include "nsIChannel.h"
 #include "nsThreadUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsMemory.h"
+#include "nsAutoPtr.h"
+
+#ifdef PR_LOGGING
+PRLogModuleInfo *gJSShLog = PR_NewLogModule("jssh");
+#endif
 
 //**********************************************************************
 // Javascript Environment
 
 const char *gWelcome = "Welcome to the Mozilla JavaScript Shell!\n";
 const char *gGoodbye = "Goodbye!\n";
 
 // GetJSShGlobal: helper for native js functions to obtain the global
@@ -208,19 +213,17 @@ Suspend(JSContext *cx, JSObject *obj, ui
   nsJSSh* shell;
   if (!GetJSShGlobal(cx, obj, &shell)) return JS_FALSE;
 
   nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
 
   PR_AtomicIncrement(&shell->mSuspendCount);
   
   while (shell->mSuspendCount) {
-#ifdef DEBUG
-    printf("|");
-#endif
+    LOG(("|"));
     NS_ProcessNextEvent(thread);
   }
            
   return JS_TRUE;
 }
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 Resume(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
@@ -243,17 +246,17 @@ AddressOf(JSContext *cx, JSObject *obj, 
   // instead.
   
   JSObject *arg_obj;
   if (!JS_ValueToObject(cx, argv[0], &arg_obj)) {
     return JS_FALSE;
   }
   
   char buf[80];
-  sprintf(buf,"%p",arg_obj);
+  sprintf(buf, "%p", arg_obj);
   JSString *str = JS_NewStringCopyZ(cx, buf);
   *rval = STRING_TO_JSVAL(str);
   return JS_TRUE;
 }
 
 JS_STATIC_DLL_CALLBACK(JSBool)
 SetProtocol(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
 {
@@ -424,19 +427,17 @@ nsJSSh::nsJSSh(nsIInputStream* input,
     mInput(input), mOutput(output), mQuit(PR_FALSE), mStartupURI(startupURI),
     mSuspendCount(0), mPrompt("\n> "),
     mEmitHeader(PR_FALSE), mProtocol("interactive")
 {
 }
 
 nsJSSh::~nsJSSh()
 {
-#ifdef DEBUG
-  printf("JSSh: ~connection!\n");
-#endif  
+  LOG(("JSSh: ~connection!\n"));
 }
 
 already_AddRefed<nsIRunnable>
 CreateJSSh(nsIInputStream* input, nsIOutputStream*output,
            const nsACString &startupURI)
 {
   nsIRunnable* obj = new nsJSSh(input, output, startupURI);
   NS_IF_ADDREF(obj);
@@ -469,19 +470,17 @@ NS_IMETHODIMP nsJSSh::Run()
     NS_ASSERTION(pom, "uh-oh, no proxy object manager!");
     pom->GetProxyForObject(NS_PROXY_TO_MAIN_THREAD,
                            NS_GET_IID(nsIJSSh),
                            (nsIJSSh*)this,
                            NS_PROXY_SYNC,
                            getter_AddRefs(proxied_shell));
   }
   else {
-#ifdef DEBUG
-    printf("jssh shell will block main thread!\n");
-#endif
+    LOG(("jssh shell will block main thread!\n"));
     proxied_shell = this;
   }
   proxied_shell->Init();
 
   if (mInput) {
     // read-eval-print loop
     PRUint32 bytesWritten;
     if (mOutput && !mProtocol.Equals(NS_LITERAL_CSTRING("plain")))
@@ -668,18 +667,22 @@ NS_IMETHODIMP nsJSSh::ExecuteBuffer()
 
   if (script) {
     jsval result;
     if (JS_ExecuteScript(mJSContext, mContextObj, script, &result) && result!=JSVAL_VOID && mOutput) {
       // XXX for some wrapped native objects the following code will crash; probably because the
       // native object is getting released before we reach this:
        JSString *str = JS_ValueToString(mJSContext, result);
        if (str) {
+         nsDependentString chars(reinterpret_cast<const PRUnichar*>
+                                 (JS_GetStringChars(str)),
+                                 JS_GetStringLength(str));
+         NS_ConvertUTF16toUTF8 cstr(chars);
          PRUint32 bytesWritten;
-         mOutput->Write(JS_GetStringBytes(str), JS_GetStringLength(str), &bytesWritten);
+         mOutput->Write(cstr.get(), cstr.Length(), &bytesWritten);
        }
     }
     JS_DestroyScript(mJSContext, script);
   }
 
   JSContext *oldcx;
   mContextStack->Pop(&oldcx);
   NS_ASSERTION(oldcx == mJSContext, "JS thread context push/pop mismatch");
@@ -756,55 +759,55 @@ PRBool nsJSSh::LoadURL(const char *url, 
   
   nsCOMPtr<nsIInputStream> instream;
   channel->Open(getter_AddRefs(instream));
   if (!instream) {
     NS_ERROR("could not open stream");
     return PR_FALSE;
   }
 
-  PRInt32 content_length=-1;
-  if (NS_FAILED(channel->GetContentLength(&content_length))) {
-    NS_ERROR("could not get content length");
-    return PR_FALSE;
-  }
-  
-  char *buf = new char[content_length+1];
+  nsCString buffer;
+  nsAutoArrayPtr<char> buf(new char[1024]);
   if (!buf) {
     NS_ERROR("could not alloc buffer");
     return PR_FALSE;
   }
 
-  PRUint32 bytesRead=0;
-  instream->Read(buf, content_length, &bytesRead);
-  if (bytesRead!=content_length) {
-    NS_ERROR("stream read error");
-    return PR_FALSE;
-  }
+  PRUint32 bytesRead = 0;
+
+  do {
+    if (NS_FAILED(instream->Read(buf, 1024, &bytesRead))) {
+      NS_ERROR("stream read error");
+      return PR_FALSE;
+    }
+    buffer.Append(buf, bytesRead);
+    LOG(("appended %d bytes:\n%s", bytesRead, buffer.get()));
+  } while (bytesRead > 0);
+
+  LOG(("loaded %d bytes:\n%s", buffer.Length(), buffer.get()));
 
   JS_BeginRequest(mJSContext);
   JSPrincipals *jsprincipals;
   mPrincipal->GetJSPrincipals(mJSContext, &jsprincipals);
 
   if(NS_FAILED(mContextStack->Push(mJSContext))) {
     NS_ERROR("failed to push the current JSContext on the nsThreadJSContextStack");
     return NS_ERROR_FAILURE;
   }
 
   jsval result;
   JSBool ok = JS_EvaluateScriptForPrincipals(mJSContext, mContextObj,
-                                             jsprincipals, buf, content_length,
+                                             jsprincipals, buffer.get(),
+                                             buffer.Length(),
                                              url, 1, &result);
   JSPRINCIPALS_DROP(mJSContext, jsprincipals);
 
   JSContext *oldcx;
   mContextStack->Pop(&oldcx);
   NS_ASSERTION(oldcx == mJSContext, "JS thread context push/pop mismatch");
 
   if (ok && retval) *retval=result;
   
   JS_EndRequest(mJSContext);
 
-  delete[] buf;
-  
   return ok;
 }
   
--- a/extensions/jssh/nsJSSh.h
+++ b/extensions/jssh/nsJSSh.h
@@ -46,16 +46,29 @@
 #include "nsIOutputStream.h"
 #include "nsIJSSh.h"
 #include "nsIJSContextStack.h"
 #include "nsIPrincipal.h"
 #include "nsStringAPI.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIXPCScriptable.h"
 
+#ifdef MOZ_LOGGING
+#define FORCE_PR_LOG
+#endif
+#include "prlog.h"
+
+// NSPR_LOG_MODULES=jssh
+#ifdef PR_LOGGING
+extern PRLogModuleInfo *gJSShLog;
+#define LOG(args) PR_LOG(gJSShLog, PR_LOG_DEBUG, args)
+#else
+#define LOG(args)
+#endif
+
 class nsJSSh : public nsIRunnable, public nsIJSSh,
                public nsIScriptObjectPrincipal,
                public nsIXPCScriptable
 {
 public:
   nsJSSh(nsIInputStream* input, nsIOutputStream*output,
          const nsACString &startupURI);
   ~nsJSSh();
--- a/extensions/jssh/nsJSShServer.cpp
+++ b/extensions/jssh/nsJSShServer.cpp
@@ -98,51 +98,43 @@ NS_INTERFACE_MAP_END
 /* void onSocketAccepted (in nsIServerSocket aServ, in nsISocketTransport aTransport); */
 NS_IMETHODIMP ConnectionListener::OnSocketAccepted(nsIServerSocket *aServ, nsISocketTransport *aTransport)
 {
   nsCOMPtr<nsIInputStream> input;
   nsCOMPtr<nsIOutputStream> output;
   aTransport->OpenInputStream(nsITransport::OPEN_BLOCKING, 0, 0, getter_AddRefs(input));
   aTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING, 0, 0, getter_AddRefs(output));
   
-#ifdef DEBUG
-  printf("JSSh server: new connection!\n");
-#endif
+  LOG(("JSSh server: new connection!\n"));
 
   nsCOMPtr<nsIRunnable> shell = CreateJSSh(input, output, mStartupURI);
 
   nsCOMPtr<nsIThread> thread;
   NS_NewThread(getter_AddRefs(thread), shell);
   return NS_OK;
 }
 
 /* void onStopListening (in nsIServerSocket aServ, in nsresult aStatus); */
 NS_IMETHODIMP ConnectionListener::OnStopListening(nsIServerSocket *aServ, nsresult aStatus)
 {
-#ifdef DEBUG
-  printf("JSSh server: stopped listening!\n");
-#endif
+  LOG(("JSSh server: stopped listening!\n"));
   return NS_OK;
 }
 
 //**********************************************************************
 // nsJSShServer implementation
 
 nsJSShServer::nsJSShServer()
 {
-#ifdef DEBUG
-  printf("nsJSShServer ctor\n");
-#endif
+  LOG(("nsJSShServer ctor\n"));
 }
 
 nsJSShServer::~nsJSShServer()
 {
-#ifdef DEBUG
-  printf("nsJSShServer dtor\n");
-#endif
+  LOG(("nsJSShServer dtor\n"));
   // XXX should we stop listening or not??
   StopServerSocket();
 }
 
 //----------------------------------------------------------------------
 // nsISupports methods:
 
 NS_IMPL_ADDREF(nsJSShServer)