Index: source/ps/GameSetup/Config.cpp
===================================================================
--- source/ps/GameSetup/Config.cpp	(revision 16085)
+++ source/ps/GameSetup/Config.cpp	(working copy)
@@ -130,8 +130,8 @@
 	CFG_GET_VAL("jsdebugger.enable", g_JSDebuggerEnabled);
 	CFG_GET_VAL("profiler2.script.enable", g_ScriptProfilingEnabled);
 
-	if (g_JSDebuggerEnabled)
-		LOGERROR(L"JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)");
+	//if (g_JSDebuggerEnabled)
+	//	LOGERROR(L"JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)");
 	// Script Debugging and profiling does not make sense together because of the hooks
 	// that reduce performance a lot - and it wasn't tested if it even works together.
 	if (g_JSDebuggerEnabled && g_ScriptProfilingEnabled)
Index: source/ps/GameSetup/GameSetup.cpp
===================================================================
--- source/ps/GameSetup/GameSetup.cpp	(revision 16085)
+++ source/ps/GameSetup/GameSetup.cpp	(working copy)
@@ -727,9 +727,9 @@
 
 
 	// JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
-	//TIMER_BEGIN(L"shutdown DebuggingServer (if active)");
-	//delete g_DebuggingServer;
-	//TIMER_END(L"shutdown DebuggingServer (if active)");
+	TIMER_BEGIN(L"shutdown DebuggingServer (if active)");
+	delete g_DebuggingServer;
+	TIMER_END(L"shutdown DebuggingServer (if active)");
 
 	delete &g_L10n;
 
@@ -957,8 +957,8 @@
 
 	// before scripting 
 	// JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
-	//if (g_JSDebuggerEnabled)
-	//	g_DebuggingServer = new CDebuggingServer();
+	if (g_JSDebuggerEnabled)
+		g_DebuggingServer = new CDebuggingServer();
 
 	// Optionally start profiler HTTP output automatically
 	// (By default it's only enabled by a hotkey, for security/performance)
Index: source/scriptinterface/DebuggingServer.cpp
===================================================================
--- source/scriptinterface/DebuggingServer.cpp	(revision 16085)
+++ source/scriptinterface/DebuggingServer.cpp	(working copy)
@@ -17,8 +17,8 @@
  
 // JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
 #include "precompiled.h" // needs to be here for Windows builds
-/* 
 
+
 #include "DebuggingServer.h"
 #include "ThreadDebugger.h"
 #include "ps/CLogger.h"
@@ -174,7 +174,6 @@
 	return m_SettingSimultaneousThreadBreak;
 }
 
-
 static Status AddFileResponse(const VfsPath& pathname, const CFileInfo& UNUSED(fileInfo), const uintptr_t cbData)
 {
 	std::vector<std::string>& templates = *(std::vector<std::string>*)cbData;
@@ -252,6 +251,24 @@
 		{
 			EnumVfsJSFiles(stream);
 		}
+		else if (uri == "/GetFile")
+		{
+			std::string filename;
+			if (!GetWebArgs(conn, request_info, "filename", filename))
+				return handled;
+			GetFile(filename, stream);
+		}
+		else if (uri == "/ToggleBreakpoint")
+		{
+			std::string filename;
+			uint line;
+			if (!GetWebArgs(conn, request_info, "filename", filename) ||
+				!GetWebArgs(conn, request_info, "line", line))
+			{
+				return handled;
+			}
+			ToggleBreakPoint(filename, line);
+		}
 		else if (uri == "/GetAllCallstacks")
 		{
 			GetAllCallstacks(stream);
@@ -262,50 +279,12 @@
 			if (!GetWebArgs(conn, request_info, "threadDebuggerID", threadDebuggerID))
 				return handled;
 			// TODO: handle the return value
-			SetNextDbgCmd(threadDebuggerID, DBG_CMD_CONTINUE);	
+			SetNextDbgCmd(threadDebuggerID, DBG_CMD_CONTINUE);
 		}
 		else if (uri == "/Break")
 		{
 			SetBreakRequestedByUser(true);
 		}
-		else if (uri == "/SetSettingSimultaneousThreadBreak")
-		{
-			std::string strEnabled;
-			bool bEnabled = false;
-			if (!GetWebArgs(conn, request_info, "enabled", strEnabled))
-				return handled;
-			// TODO: handle the return value
-			if (strEnabled == "true")
-				bEnabled = true;
-			else if (strEnabled == "false")
-				bEnabled = false;
-			else
-				return handled; // TODO: return an error state
-			SetSettingSimultaneousThreadBreak(bEnabled);
-		}
-		else if (uri == "/GetSettingSimultaneousThreadBreak")
-		{
-			stream << "{ \"Enabled\" : " << (GetSettingSimultaneousThreadBreak() ? "true" : "false") << " } ";
-		}
-		else if (uri == "/SetSettingBreakOnException")
-		{
-			std::string strEnabled;
-			bool bEnabled = false;
-			if (!GetWebArgs(conn, request_info, "enabled", strEnabled))
-				return handled;
-			// TODO: handle the return value
-			if (strEnabled == "true")
-				bEnabled = true;
-			else if (strEnabled == "false")
-				bEnabled = false;
-			else
-				return handled; // TODO: return an error state
-			SetSettingBreakOnException(bEnabled);
-		}
-		else if (uri == "/GetSettingBreakOnException")
-		{
-			stream << "{ \"Enabled\" : " << (GetSettingBreakOnException() ? "true" : "false") << " } ";
-		}
 		else if (uri == "/Step")
 		{
 			uint threadDebuggerID;
@@ -334,7 +313,7 @@
 		{
 			uint nestingLevel;
 			uint threadDebuggerID;
-			if (!GetWebArgs(conn, request_info, "nestingLevel", nestingLevel) || 
+			if (!GetWebArgs(conn, request_info, "nestingLevel", nestingLevel) ||
 				!GetWebArgs(conn, request_info, "threadDebuggerID", threadDebuggerID))
 			{
 				return handled;
@@ -345,7 +324,7 @@
 		{
 			uint nestingLevel;
 			uint threadDebuggerID;
-			if (!GetWebArgs(conn, request_info, "nestingLevel", nestingLevel) || 
+			if (!GetWebArgs(conn, request_info, "nestingLevel", nestingLevel) ||
 				!GetWebArgs(conn, request_info, "threadDebuggerID", threadDebuggerID))
 			{
 				return handled;
@@ -352,6 +331,44 @@
 			}
 			GetStackFrameData(stream, nestingLevel, threadDebuggerID, STACK_INFO_THIS);
 		}
+		else if (uri == "/SetSettingSimultaneousThreadBreak")
+		{
+			std::string strEnabled;
+			bool bEnabled = false;
+			if (!GetWebArgs(conn, request_info, "enabled", strEnabled))
+				return handled;
+			// TODO: handle the return value
+			if (strEnabled == "true")
+				bEnabled = true;
+			else if (strEnabled == "false")
+				bEnabled = false;
+			else
+				return handled; // TODO: return an error state
+			SetSettingSimultaneousThreadBreak(bEnabled);
+		}
+		else if (uri == "/GetSettingSimultaneousThreadBreak")
+		{
+			stream << "{ \"Enabled\" : " << (GetSettingSimultaneousThreadBreak() ? "true" : "false") << " } ";
+		}
+		else if (uri == "/SetSettingBreakOnException")
+		{
+			std::string strEnabled;
+			bool bEnabled = false;
+			if (!GetWebArgs(conn, request_info, "enabled", strEnabled))
+				return handled;
+			// TODO: handle the return value
+			if (strEnabled == "true")
+				bEnabled = true;
+			else if (strEnabled == "false")
+				bEnabled = false;
+			else
+				return handled; // TODO: return an error state
+			SetSettingBreakOnException(bEnabled);
+		}
+		else if (uri == "/GetSettingBreakOnException")
+		{
+			//stream << "{ \"Enabled\" : " << (GetSettingBreakOnException() ? "true" : "false") << " } ";
+		}
 		else if (uri == "/GetCurrentGlobalObject")
 		{
 			uint threadDebuggerID;
@@ -361,24 +378,6 @@
 			}
 			GetStackFrameData(stream, 0, threadDebuggerID, STACK_INFO_GLOBALOBJECT);
 		}
-		else if (uri == "/ToggleBreakpoint")
-		{
-			std::string filename;
-			uint line;
-			if (!GetWebArgs(conn, request_info, "filename", filename) ||
-				!GetWebArgs(conn, request_info, "line", line))
-			{
-				return handled;
-			}
-			ToggleBreakPoint(filename, line);
-		}
-		else if (uri == "/GetFile")
-		{
-			std::string filename;
-			if (!GetWebArgs(conn, request_info, "filename", filename))
-				return handled;
-			GetFile(filename, stream);
-		}
 		else
 		{
 			mg_printf(conn, "%s", header404);
@@ -568,4 +567,3 @@
 	ENSURE(m_BreakPointsLockID == breakPointsLockID); 
 	SDL_SemPost(m_BreakPointsSem);
 }
-*/
\ No newline at end of file
Index: source/scriptinterface/DebuggingServer.h
===================================================================
--- source/scriptinterface/DebuggingServer.h	(revision 16085)
+++ source/scriptinterface/DebuggingServer.h	(working copy)
@@ -17,137 +17,137 @@
 
 // JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
 
-//#ifndef INCLUDED_DEBUGGINGSERVER
-//#define INCLUDED_DEBUGGINGSERVER
-//
-//#include "third_party/mongoose/mongoose.h"
-//#include "ScriptInterface.h"
-//
-//#include "lib/external_libraries/libsdl.h"
-//
-//class CBreakPoint;
-//class CThreadDebugger;
-//
-//enum DBGCMD { DBG_CMD_NONE=0, DBG_CMD_CONTINUE, DBG_CMD_SINGLESTEP, DBG_CMD_STEPINTO, DBG_CMD_STEPOUT };
-//enum STACK_INFO { STACK_INFO_LOCALS=0, STACK_INFO_THIS, STACK_INFO_GLOBALOBJECT };
-//
-//class CDebuggingServer
-//{
-//public:
-//	CDebuggingServer();
-//	~CDebuggingServer();
-//	
-//	/** @brief Register a new ScriptInerface for debugging the scripts it executes
-//	 *
-//	 * @param name A name for the ScriptInterface (will be sent to the debugging client an probably displayed to the user)
-//	 * @param pScriptInterface A pointer to the ScriptInterface. This pointer must stay valid until UnRegisterScriptInterface ist called!
-//	 */
-//	void RegisterScriptinterface(std::string name, ScriptInterface* pScriptInterface);
-//	
-//	/** @brief Unregister a ScriptInerface that was previously registered using RegisterScriptinterface. 
-//	 *
-//	 * @param pScriptInterface A pointer to the ScriptInterface
-//	 */
-//	void UnRegisterScriptinterface(ScriptInterface* pScriptInterface);
-//
-//	
-//	// Mongoose callback when request comes from a client 
-//	void* MgDebuggingServerCallback(mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info);	
-//	
-//	/** @brief Aquire exclusive read and write access to the list of breakpoints.
-//	 *
-//	 * @param breakPoints A pointer to the list storing all breakpoints.
-//	 *
-//	 * @return  A number you need to pass to ReleaseBreakPointAccess().
-//	 *
-//	 * Make sure to call ReleaseBreakPointAccess after you don't need access any longer.
-//	 * Using this function you get exclusive access and other threads won't be able to access the breakpoints until you call ReleaseBreakPointAccess!
-//	 */
-//	double AquireBreakPointAccess(std::list<CBreakPoint>** breakPoints);
-//	
-//	/** @brief See AquireBreakPointAccess(). You must not access the pointer returend by AquireBreakPointAccess() any longer after you call this function.
-//	 * 	
-//	 * @param breakPointsLockID The number you got when aquiring the access. It's used to make sure that this function never gets
-//	 *          used by the wrong thread.        
-//	 */	
-//	void ReleaseBreakPointAccess(double breakPointsLockID);
-//	
-//	
-//	/// Called from multiple Mongoose threads and multiple ScriptInterface threads
-//	bool GetBreakRequestedByThread();
-//	bool GetBreakRequestedByUser();
-//	// Should other threads be stopped as soon as possible after a breakpoint is triggered in a thread
-//	bool GetSettingSimultaneousThreadBreak();
-//	// Should the debugger break on any JS-Exception? If set to false, it will only break when the exceptions text is "Breakpoint".
-//	bool GetSettingBreakOnException();
-//	void SetBreakRequestedByThread(bool Enabled);
-//	void SetBreakRequestedByUser(bool Enabled);
-//	
-//private:
-//	static const char* header400;
-//
-//	/// Webserver helper function (can be called by multiple mongooser threads)
-//	bool GetWebArgs(struct mg_connection *conn, const struct mg_request_info* request_info, std::string argName, uint& arg);
-//	bool GetWebArgs(struct mg_connection *conn, const struct mg_request_info* request_info, std::string argName, std::string& arg);
-//	
-//	/// Functions that are made available via http (can be called by multiple mongoose threads)
-//	void GetThreadDebuggerStatus(std::stringstream& response);
-//	void ToggleBreakPoint(std::string filename, uint line);
-//	void GetAllCallstacks(std::stringstream& response);
-//	void GetStackFrameData(std::stringstream& response, uint nestingLevel, uint threadDebuggerID, STACK_INFO stackInfoKind);
-//	bool SetNextDbgCmd(uint threadDebuggerID, DBGCMD dbgCmd);
-//	void SetSettingSimultaneousThreadBreak(bool Enabled);
-//	void SetSettingBreakOnException(bool Enabled);
-//	
-//	/** @brief Returns a list of the full vfs paths to all files with the extension .js found in the vfs root
-//	 * 
-//	 *  @param response This will contain the list as JSON array.
-//	 */
-//	void EnumVfsJSFiles(std::stringstream& response);
-//	
-//	/** @brief Get the content of a .js file loaded into vfs
-//	 *
-//	 * @param filename A full vfs path (as returned by EnumVfsJSFiles).
-//	 * @param response This will contain the contents of the requested file.
-//	 */
-//	void GetFile(std::string filename, std::stringstream& response);
-//	
-//	/// Shared between multiple mongoose threads
-//	
-//
-//	bool m_SettingSimultaneousThreadBreak;
-//	bool m_SettingBreakOnException;
-//	
-//	/// Shared between multiple scriptinterface threads
-//	uint m_LastThreadDebuggerID;
-//	
-//	/// Shared between multiple scriptinerface threads and multiple mongoose threads
-//	std::list<CThreadDebugger*> m_ThreadDebuggers;
-//	
-//	// The CThreadDebuggers will check this value and break the thread if it's true.
-//	// This only works for JS code, so C++ code will not break until it executes JS-code again.
-//	bool m_BreakRequestedByThread;
-//	bool m_BreakRequestedByUser;
-//	
-//	// The breakpoint is uniquely identified using filename an line-number.
-//	// Since the filename is the whole vfs path it should really be unique.
-//	std::list<CBreakPoint> m_BreakPoints;
-//	
-//	/// Used for controlling access to m_BreakPoints
-//	SDL_sem* m_BreakPointsSem;
-//	double m_BreakPointsLockID;
-//	
-//	/// Mutexes used to ensure thread-safety. Currently we just use one Mutex (m_Mutex) and if we detect possible sources
-//	/// of deadlocks, we use the second mutex for some members to avoid it.
-//	CMutex m_Mutex;
-//	CMutex m_Mutex1;
-//	
-//	/// Not important for this class' thread-safety
-//	void EnableHTTP();
-//	mg_context* m_MgContext;
-//};
-//
-//extern CDebuggingServer* g_DebuggingServer;
-//
-//
-//#endif // INCLUDED_DEBUGGINGSERVER
+#ifndef INCLUDED_DEBUGGINGSERVER
+#define INCLUDED_DEBUGGINGSERVER
+
+#include "third_party/mongoose/mongoose.h"
+#include "ScriptInterface.h"
+
+#include "lib/external_libraries/libsdl.h"
+
+class CBreakPoint;
+class CThreadDebugger;
+
+enum DBGCMD { DBG_CMD_NONE=0, DBG_CMD_CONTINUE, DBG_CMD_SINGLESTEP, DBG_CMD_STEPINTO, DBG_CMD_STEPOUT };
+enum STACK_INFO { STACK_INFO_LOCALS=0, STACK_INFO_THIS, STACK_INFO_GLOBALOBJECT };
+
+class CDebuggingServer
+{
+public:
+	CDebuggingServer();
+	~CDebuggingServer();
+	
+	/** @brief Register a new ScriptInerface for debugging the scripts it executes
+	 *
+	 * @param name A name for the ScriptInterface (will be sent to the debugging client an probably displayed to the user)
+	 * @param pScriptInterface A pointer to the ScriptInterface. This pointer must stay valid until UnRegisterScriptInterface ist called!
+	 */
+	void RegisterScriptinterface(std::string name, ScriptInterface* pScriptInterface);
+	
+	/** @brief Unregister a ScriptInerface that was previously registered using RegisterScriptinterface. 
+	 *
+	 * @param pScriptInterface A pointer to the ScriptInterface
+	 */
+	void UnRegisterScriptinterface(ScriptInterface* pScriptInterface);
+
+	
+	// Mongoose callback when request comes from a client 
+	void* MgDebuggingServerCallback(mg_event event, struct mg_connection *conn, const struct mg_request_info *request_info);	
+	
+	/** @brief Aquire exclusive read and write access to the list of breakpoints.
+	 *
+	 * @param breakPoints A pointer to the list storing all breakpoints.
+	 *
+	 * @return  A number you need to pass to ReleaseBreakPointAccess().
+	 *
+	 * Make sure to call ReleaseBreakPointAccess after you don't need access any longer.
+	 * Using this function you get exclusive access and other threads won't be able to access the breakpoints until you call ReleaseBreakPointAccess!
+	 */
+	double AquireBreakPointAccess(std::list<CBreakPoint>** breakPoints);
+	
+	/** @brief See AquireBreakPointAccess(). You must not access the pointer returend by AquireBreakPointAccess() any longer after you call this function.
+	 * 	
+	 * @param breakPointsLockID The number you got when aquiring the access. It's used to make sure that this function never gets
+	 *          used by the wrong thread.        
+	 */	
+	void ReleaseBreakPointAccess(double breakPointsLockID);
+	
+	
+	/// Called from multiple Mongoose threads and multiple ScriptInterface threads
+	bool GetBreakRequestedByThread();
+	bool GetBreakRequestedByUser();
+	// Should other threads be stopped as soon as possible after a breakpoint is triggered in a thread
+	bool GetSettingSimultaneousThreadBreak();
+	// Should the debugger break on any JS-Exception? If set to false, it will only break when the exceptions text is "Breakpoint".
+	bool GetSettingBreakOnException();
+	void SetBreakRequestedByThread(bool Enabled);
+	void SetBreakRequestedByUser(bool Enabled);
+	
+private:
+	static const char* header400;
+
+	/// Webserver helper function (can be called by multiple mongooser threads)
+	bool GetWebArgs(struct mg_connection *conn, const struct mg_request_info* request_info, std::string argName, uint& arg);
+	bool GetWebArgs(struct mg_connection *conn, const struct mg_request_info* request_info, std::string argName, std::string& arg);
+	
+	/// Functions that are made available via http (can be called by multiple mongoose threads)
+	void GetThreadDebuggerStatus(std::stringstream& response);
+	void ToggleBreakPoint(std::string filename, uint line);
+	void GetAllCallstacks(std::stringstream& response);
+	void GetStackFrameData(std::stringstream& response, uint nestingLevel, uint threadDebuggerID, STACK_INFO stackInfoKind);
+	bool SetNextDbgCmd(uint threadDebuggerID, DBGCMD dbgCmd);
+	void SetSettingSimultaneousThreadBreak(bool Enabled);
+	void SetSettingBreakOnException(bool Enabled);
+	
+	/** @brief Returns a list of the full vfs paths to all files with the extension .js found in the vfs root
+	 * 
+	 *  @param response This will contain the list as JSON array.
+	 */
+	void EnumVfsJSFiles(std::stringstream& response);
+	
+	/** @brief Get the content of a .js file loaded into vfs
+	 *
+	 * @param filename A full vfs path (as returned by EnumVfsJSFiles).
+	 * @param response This will contain the contents of the requested file.
+	 */
+	void GetFile(std::string filename, std::stringstream& response);
+	
+	/// Shared between multiple mongoose threads
+	
+
+	bool m_SettingSimultaneousThreadBreak;
+	bool m_SettingBreakOnException;
+	
+	/// Shared between multiple scriptinterface threads
+	uint m_LastThreadDebuggerID;
+	
+	/// Shared between multiple scriptinerface threads and multiple mongoose threads
+	std::list<CThreadDebugger*> m_ThreadDebuggers;
+	
+	// The CThreadDebuggers will check this value and break the thread if it's true.
+	// This only works for JS code, so C++ code will not break until it executes JS-code again.
+	bool m_BreakRequestedByThread;
+	bool m_BreakRequestedByUser;
+	
+	// The breakpoint is uniquely identified using filename an line-number.
+	// Since the filename is the whole vfs path it should really be unique.
+	std::list<CBreakPoint> m_BreakPoints;
+	
+	/// Used for controlling access to m_BreakPoints
+	SDL_sem* m_BreakPointsSem;
+	double m_BreakPointsLockID;
+	
+	/// Mutexes used to ensure thread-safety. Currently we just use one Mutex (m_Mutex) and if we detect possible sources
+	/// of deadlocks, we use the second mutex for some members to avoid it.
+	CMutex m_Mutex;
+	CMutex m_Mutex1;
+	
+	/// Not important for this class' thread-safety
+	void EnableHTTP();
+	mg_context* m_MgContext;
+};
+
+extern CDebuggingServer* g_DebuggingServer;
+
+
+#endif // INCLUDED_DEBUGGINGSERVER
Index: source/scriptinterface/ScriptInterface.cpp
===================================================================
--- source/scriptinterface/ScriptInterface.cpp	(revision 16085)
+++ source/scriptinterface/ScriptInterface.cpp	(working copy)
@@ -19,7 +19,7 @@
 
 #include "ScriptInterface.h"
 #include "ScriptRuntime.h"
-// #include "DebuggingServer.h" // JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
+#include "DebuggingServer.h" // JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
 #include "ScriptStats.h"
 #include "AutoRooters.h"
 
@@ -416,14 +416,17 @@
 	}
 	
 	// JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
-	/*
+	
 	if (g_JSDebuggerEnabled && g_DebuggingServer != NULL)
 	{
 		if(!JS_SetDebugMode(GetContext(), true))
 			LOGERROR(L"Failed to set Spidermonkey to debug mode!");
+		
+		if(!JS_SetDebugModeForAllCompartments(GetContext(), true))
+			LOGERROR(L"Failed to set Spidermonkey to debug mode!");
 		else
 			g_DebuggingServer->RegisterScriptinterface(debugName, this);
-	} */
+	}
 
 	m_CxPrivate.pScriptInterface = this;
 	JS_SetContextPrivate(m->m_cx, (void*)&m_CxPrivate);
@@ -439,8 +442,8 @@
 	
 	// Unregister from the Debugger class
 	// JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
-	//if (g_JSDebuggerEnabled && g_DebuggingServer != NULL)
-	//	g_DebuggingServer->UnRegisterScriptinterface(this);
+	if (g_JSDebuggerEnabled && g_DebuggingServer != NULL)
+		g_DebuggingServer->UnRegisterScriptinterface(this);
 }
 
 void ScriptInterface::ShutDown()
Index: source/scriptinterface/ThreadDebugger.cpp
===================================================================
--- source/scriptinterface/ThreadDebugger.cpp	(revision 16085)
+++ source/scriptinterface/ThreadDebugger.cpp	(working copy)
@@ -17,8 +17,8 @@
  
  // JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
 #include "precompiled.h" // needs to be here for Windows builds
- /*
 
+
 #include "ThreadDebugger.h"
 #include "lib/utf8.h"
 #include "ps/CLogger.h"
@@ -26,6 +26,16 @@
 #include <map>
 #include <queue>
 
+//Operators
+bool operator==(JS::FrameDescription& a, JS::FrameDescription& b)
+{
+	return a.fun == b.fun;
+}
+
+bool operator!=(JS::FrameDescription& a, JS::FrameDescription& b)
+{
+	return a.fun != b.fun;
+}
 // Hooks
 
 CMutex ThrowHandlerMutex;
@@ -37,7 +47,7 @@
 }
 
 CMutex TrapHandlerMutex;
-static JSTrapStatus TrapHandler_(JSContext* cx, JSScript* script, jsbytecode* pc, jsval* rval, jsval closure) 
+static JSTrapStatus TrapHandler_(JSContext* cx, JSScript* script, jsbytecode* pc, jsval* rval, jsval closure)
 {
 	CScopeLock lock(TrapHandlerMutex);
 	CThreadDebugger* pThreadDebugger = (CThreadDebugger*) JSVAL_TO_PRIVATE(closure);
@@ -71,11 +81,12 @@
 }
 
 CMutex DestroyScriptHookMutex;
-void DestroyScriptHook_(JSContext* cx, JSScript* script, void* callerdata)
+void DestroyScriptHook_(JSFreeOp* UNUSED(fop), JSScript* script, void* callerdata)
 {
 	CScopeLock lock(DestroyScriptHookMutex);
 	CThreadDebugger* pThreadDebugger = (CThreadDebugger*) callerdata;
-	return pThreadDebugger->DestroyScriptHook(cx, script);
+
+	return pThreadDebugger->DestroyScriptHook(NULL, script);
 }
 
 CMutex StepOutHandlerMutex;
@@ -95,7 +106,7 @@
 }
 
 CMutex CallHookMutex;
-static void* CallHook_(JSContext* cx, JSStackFrame* fp, JSBool before, JSBool* UNUSED(ok), void* closure)
+static void* CallHook_(JSContext* cx, JSAbstractFramePtr fp, bool UNUSED(isConstruncting), JSBool before, JSBool* UNUSED(ok), void* closure)
 {
 	CScopeLock lock(CallHookMutex);
 	CThreadDebugger* pThreadDebugger = (CThreadDebugger*) closure;
@@ -102,10 +113,12 @@
 	if (before)
 	{
 		JSScript* script;
-		script = JS_GetFrameScript(cx, fp);
+		script = fp.script();
 		const char* fileName = JS_GetScriptFilename(cx, script);
+
 		uint lineno = JS_GetScriptBaseLineNumber(cx, script);
-		JSFunction* fun = JS_GetFrameFunction(cx, fp);
+		
+		JSFunction* fun = fp.maybeFun();
 		pThreadDebugger->ExecuteHook(cx, fileName, lineno, script, fun, closure);
 	}
 	
@@ -149,7 +162,7 @@
 	// and spidermonkey throws errors if it detects a pointer on the stack.
 	// We only use the pointer for comparing it with the current stack pointer and we don't try to access it, so it
 	// shouldn't be a problem.
-	JSStackFrame** m_pLastBreakFrame;
+	JS::FrameDescription** m_pLastBreakFrame;
 	uint m_ObjectReferenceID;
 
 	/// shared between multiple mongoose threads and one scriptinterface thread
@@ -174,7 +187,7 @@
 	: m_NextDbgCmd(DBG_CMD_NONE)
 	, m_pScriptInterface(NULL)
 	, m_pDebuggingServer(NULL)
-	, m_pLastBreakFrame(new JSStackFrame*)
+, m_pLastBreakFrame(new JS::FrameDescription*)
 	, m_IsInBreak(false)
 { }
 
@@ -293,8 +306,8 @@
 	// Remove all the hooks because they store a pointer to this object
 	JS_SetExecuteHook(m->m_pScriptInterface->GetJSRuntime(), NULL, NULL);
 	JS_SetCallHook(m->m_pScriptInterface->GetJSRuntime(), NULL, NULL);
-	JS_SetNewScriptHook(m->m_pScriptInterface->GetJSRuntime(), NULL, NULL);
-	JS_SetDestroyScriptHook(m->m_pScriptInterface->GetJSRuntime(), NULL, NULL);
+	JS_SetNewScriptHookProc(m->m_pScriptInterface->GetJSRuntime(), NULL, NULL);
+	JS_SetDestroyScriptHookProc(m->m_pScriptInterface->GetJSRuntime(), NULL, NULL);
 }
 
 void CThreadDebugger::ReturnActiveBreakPoints(jsbytecode* pBytecode)
@@ -333,8 +346,8 @@
 	m->m_pDebuggingServer = pDebuggingServer;
 	JS_SetExecuteHook(m->m_pScriptInterface->GetJSRuntime(), CallHook_, (void*)this);
 	JS_SetCallHook(m->m_pScriptInterface->GetJSRuntime(), CallHook_, (void*)this);
-	JS_SetNewScriptHook(m->m_pScriptInterface->GetJSRuntime(), NewScriptHook_, (void*)this);
-	JS_SetDestroyScriptHook(m->m_pScriptInterface->GetJSRuntime(), DestroyScriptHook_, (void*)this);
+	JS_SetNewScriptHookProc(m->m_pScriptInterface->GetJSRuntime(), NewScriptHook_, (void*)this);
+	JS_SetDestroyScriptHookProc(m->m_pScriptInterface->GetJSRuntime(), DestroyScriptHook_, (void*)this);
 	JS_SetThrowHook(m->m_pScriptInterface->GetJSRuntime(), ThrowHandler_, (void*)this);
 	
 	if (m->m_pDebuggingServer->GetSettingSimultaneousThreadBreak())
@@ -352,16 +365,18 @@
 	//          a higher line number.
 	// 2. We are in a different Frame and m_pLastBreakFrame is not a parent of the current frame (because we stepped out of the function)
 	uint line = JS_PCToLineNumber(cx, script, pc);
-	JSStackFrame* iter = NULL;
-	JSStackFrame* pStackFrame;
-	pStackFrame = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
 	uint lastBreakLine = GetLastBreakLine() ;
+	JS::StackDescription* description = JS::DescribeStack(cx, NULL);
+	JS::FrameDescription* pStackFrame = description->frames;
+	JSTrapStatus result = JSTRAP_CONTINUE;
+
 	jsval val = JSVAL_VOID;
-	if ((*m->m_pLastBreakFrame == pStackFrame && lastBreakLine != line) || 
-		(*m->m_pLastBreakFrame != pStackFrame && !CurrentFrameIsChildOf(*m->m_pLastBreakFrame)))
-		return BreakHandler(cx, script, pc, rval, val, BREAK_SRC_INTERRUP);
-	else
-		return JSTRAP_CONTINUE;
+	if ((**m->m_pLastBreakFrame == *pStackFrame && lastBreakLine != line) ||
+		(**m->m_pLastBreakFrame != *pStackFrame && !CurrentFrameIsChildOf(description, *m->m_pLastBreakFrame)))
+		result = BreakHandler(cx, script, pc, rval, val, BREAK_SRC_INTERRUP);
+
+	JS::FreeStackDescription(cx, description);
+	return result;
 }
 
 JSTrapStatus CThreadDebugger::StepIntoHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void* UNUSED(closure))
@@ -369,16 +384,17 @@
 	// We break when we are on the same stack frame but not on the same line 
 	// or when we are on another stack frame.
 	uint line = JS_PCToLineNumber(cx, script, pc);
-	JSStackFrame* iter = NULL;
-	JSStackFrame* pStackFrame;
-	pStackFrame = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
+	JS::StackDescription* description = JS::DescribeStack(cx, NULL);
+	JS::FrameDescription* pStackFrame = description->frames;
 	uint lastBreakLine = GetLastBreakLine();
+	JSTrapStatus result = JSTRAP_CONTINUE;
 	
 	jsval val = JSVAL_VOID;
-	if ((*m->m_pLastBreakFrame == pStackFrame && lastBreakLine != line) || *m->m_pLastBreakFrame != pStackFrame)
-		return BreakHandler(cx, script, pc, rval, val, BREAK_SRC_INTERRUP);
-	else
-		return JSTRAP_CONTINUE;
+	if ((**m->m_pLastBreakFrame == *pStackFrame && lastBreakLine != line) || **m->m_pLastBreakFrame != *pStackFrame)
+		result = BreakHandler(cx, script, pc, rval, val, BREAK_SRC_INTERRUP);
+	
+	JS::FreeStackDescription(cx, description);
+	return result;
 }
 
 JSTrapStatus CThreadDebugger::StepOutHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void* UNUSED(closure))
@@ -385,29 +401,30 @@
 {
 	// We break when we are in a different Frame and m_pLastBreakFrame is not a parent of the current frame 
 	// (because we stepped out of the function)
-	JSStackFrame* iter = NULL;
-	JSStackFrame* pStackFrame;
-	pStackFrame = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
-	if (pStackFrame != *m->m_pLastBreakFrame && !CurrentFrameIsChildOf(*m->m_pLastBreakFrame))
+	
+	JS::StackDescription* description = JS::DescribeStack(cx, NULL);
+	JS::FrameDescription* pStackFrame = description->frames;
+	JSTrapStatus result = JSTRAP_CONTINUE;
+	
+	if (*pStackFrame != **m->m_pLastBreakFrame && !CurrentFrameIsChildOf(description, *m->m_pLastBreakFrame))
 	{
 		jsval val = JSVAL_VOID;
-		return BreakHandler(cx, script, pc, rval, val, BREAK_SRC_INTERRUP);
+		result = BreakHandler(cx, script, pc, rval, val, BREAK_SRC_INTERRUP);
 	}
-	else
-		return JSTRAP_CONTINUE;
+	
+	JS::FreeStackDescription(cx, description);
+	return result;
 }
 
-bool CThreadDebugger::CurrentFrameIsChildOf(JSStackFrame* pParentFrame)
+bool CThreadDebugger::CurrentFrameIsChildOf(JS::StackDescription* description, JS::FrameDescription* frame)
 {
-	JSStackFrame* iter = NULL;
-	JSStackFrame* fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
-	// Get the first parent Frame
-	fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
-	while (fp)
-	{
-		if (fp == pParentFrame) 
+	for (int i = 0; i < (int)description->nframes; i++) {
+		JS::FrameDescription* nextframe = (description->frames + i);
+		
+		if (*nextframe == *frame)
+		{
 			return true;
-		fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
+		}
 	}
 	return false;
 }
@@ -489,8 +506,9 @@
 		}
 		else if (nextDbgCmd == DBG_CMD_SINGLESTEP || nextDbgCmd == DBG_CMD_STEPINTO || nextDbgCmd == DBG_CMD_STEPOUT)
 		{
-			JSStackFrame* iter = NULL;
-			*m->m_pLastBreakFrame = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
+			JS::StackDescription* description = JS::DescribeStack(m->m_pScriptInterface->GetContext(), NULL);
+			*m->m_pLastBreakFrame = description->frames;
+			//JS::FreeStackDescription(m->m_pScriptInterface->GetContext(), description);
 			
 			if (!JS_SetSingleStepMode(cx, script, true))
 				LOGERROR(L"JS_SetSingleStepMode returned false!"); // TODO: When can this happen?
@@ -524,7 +542,7 @@
 			}
 			break;
 		}
-		else 
+		else
 			debug_warn("Invalid DBGCMD found in CThreadDebugger::BreakHandler!");
 	}
 	ClearTrapsToRemove();
@@ -545,6 +563,10 @@
 void CThreadDebugger::NewScriptHook(JSContext* cx, const char* filename, unsigned lineno, JSScript* script, JSFunction* UNUSED(fun), void* UNUSED(callerdata))
 {
 	uint scriptExtent = JS_GetScriptLineExtent (cx, script);
+
+	if (filename == NULL)
+		filename = "<No FileName>";
+
 	std::string stringFileName(filename);
 	if (stringFileName.empty())
 		return;
@@ -588,6 +610,10 @@
 
 void CThreadDebugger::DestroyScriptHook(JSContext* cx, JSScript* script)
 {
+	if (cx == NULL)
+	{
+		cx = m->m_pScriptInterface->GetContext();
+	}
 	uint scriptExtent = JS_GetScriptLineExtent (cx, script);
 	uint baseLine = JS_GetScriptBaseLineNumber(cx, script);
 	
@@ -649,38 +675,40 @@
 	ENSURE(GetIsInBreak());
 	
 	CScopeLock lock(m->m_Mutex);
-	
-	JSStackFrame *fp;
-	JSStackFrame *iter = 0;
-	jsint counter = 0;
-	
+
 	JSObject* jsArray;
 	jsArray = JS_NewArrayObject(m->m_pScriptInterface->GetContext(), 0, 0);
 	JSString* functionID;
-
-	fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
-
-	while (fp)
-	{
-		JSFunction* fun = 0;
-		fun = JS_GetFrameFunction(m->m_pScriptInterface->GetContext(), fp);
-		if (NULL == fun)
+	
+	JS::StackDescription* description = JS::DescribeStack(m->m_pScriptInterface->GetContext(), NULL);
+	
+	for (int i = 0; i < (int)description->nframes; i++) {
+		JS::FrameDescription* frame = (description->frames + i);
+		
+		if (frame->fun == NULL)
 			functionID = JS_NewStringCopyZ(m->m_pScriptInterface->GetContext(), "null");
 		else
 		{
-			functionID = JS_GetFunctionId(fun);
-			if (NULL == functionID)
+			functionID = JS_GetFunctionId(frame->fun);
+			if (functionID == NULL)
+				functionID = JS_GetFunctionDisplayId(frame->fun);
+				
+			if (functionID == NULL)
 				functionID = JS_NewStringCopyZ(m->m_pScriptInterface->GetContext(), "anonymous");
+			
+
 		}
-
-		JSBool ret = JS_DefineElement(m->m_pScriptInterface->GetContext(), jsArray, counter, STRING_TO_JSVAL(functionID), NULL, NULL, 0);
+		JSBool ret = JS_DefineElement(m->m_pScriptInterface->GetContext(), jsArray, i, STRING_TO_JSVAL(functionID), NULL, NULL, 0);
 		ENSURE(ret);
-		fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
-		counter++;
 	}
 	
+	JS::FreeStackDescription(m->m_pScriptInterface->GetContext(), description);
+	
+	JS::RootedValue rv(m->m_pScriptInterface->GetContext(),OBJECT_TO_JSVAL(jsArray));
+	JS::MutableHandleValue mhv(&rv);
+	
 	m->m_Callstack.clear();
-	m->m_Callstack = m->m_pScriptInterface->StringifyJSON(OBJECT_TO_JSVAL(jsArray), false).c_str();
+	m->m_Callstack = m->m_pScriptInterface->StringifyJSON(mhv, false).c_str();
 }
 
 void CThreadDebugger::GetStackFrameData(std::stringstream& response, uint nestingLevel, STACK_INFO stackInfoKind)
@@ -721,46 +749,121 @@
 	ENSURE(GetIsInBreak());
 	
 	CScopeLock lock(m->m_Mutex);
-	JSStackFrame *iter = 0;
-	uint counter = 0;
-	jsval val;
 	
 	if (stackInfo == STACK_INFO_GLOBALOBJECT)
 	{
-		JSObject* obj;
-		obj = JS_GetGlobalForScopeChain(m->m_pScriptInterface->GetContext());
-		m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(OBJECT_TO_JSVAL(obj), false);
+		//Get global function
+		JSObject* global;
+		global = JS_GetGlobalForScopeChain(m->m_pScriptInterface->GetContext());
+		m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(OBJECT_TO_JSVAL(global), false);
 	}
 	else
 	{
-		JSStackFrame *fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
-		while (fp)
+		JS::StackDescription* description = JS::DescribeStack(m->m_pScriptInterface->GetContext(), NULL);
+		JS::FrameDescription* frame = (description->frames + nestingLevel);
+		
+		JSBrokenFrameIterator bFrame(m->m_pScriptInterface->GetContext());
+		for (uint i = 0; i < nestingLevel; i++) {
+			bFrame = ++bFrame;
+		}
+		JSAbstractFramePtr aFrame = (JSAbstractFramePtr)bFrame.abstractFramePtr();
+		JSObject* callobject = aFrame.callObject(m->m_pScriptInterface->GetContext()); //need the call to build evaluateInStackFrame
+		
+		const char* fileName = JS_GetScriptFilename(m->m_pScriptInterface->GetContext(), frame->script);
+
+		if (stackInfo == STACK_INFO_LOCALS)
 		{
-			if (counter == nestingLevel)
+			bool bbt = m->m_pDebuggingServer->GetBreakRequestedByThread();
+			bool bbu = m->m_pDebuggingServer->GetBreakRequestedByUser();
+			
+			m->m_pDebuggingServer->SetBreakRequestedByThread(false);
+			m->m_pDebuggingServer->SetBreakRequestedByUser(false);
+			
+			if (JS_FunctionHasLocalNames(m->m_pScriptInterface->GetContext(),frame->fun))
 			{
-				if (stackInfo == STACK_INFO_LOCALS)
-				{
-					JSObject* obj;
-					obj = JS_GetFrameCallObject(m->m_pScriptInterface->GetContext(), fp);
-					//obj = JS_GetFrameScopeChain(m->m_pScriptInterface->GetContext(), fp);
-					m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(OBJECT_TO_JSVAL(obj), false);
+				void* lArray;
+				uintptr_t* aNames = JS_GetFunctionLocalNameArray(m->m_pScriptInterface->GetContext(), frame->fun, &lArray);
+				
+				JSObject* locals = JS_NewObject(m->m_pScriptInterface->GetContext(), NULL, NULL, NULL);
+
+				uintptr_t last = 0xCDCDCDCDCDCDCDCD;
+				while (*aNames != last) {
+					JSAtom* atom = JS_LocalNameToAtom(*aNames);
+					JSString* jsName = JS_AtomKey(atom);
+					const char * lName = JS_EncodeString(m->m_pScriptInterface->GetContext(), jsName);
+					
+					JS::RootedValue rLocal(m->m_pScriptInterface->GetContext());
+					JS::MutableHandleValue vLocal(&rLocal);
+					
+					aFrame.evaluateInStackFrame(m->m_pScriptInterface->GetContext(), lName, strlen(lName), fileName, frame->lineno, vLocal);
+					
+
+					JS_DefineProperty(m->m_pScriptInterface->GetContext(), locals, lName , vLocal, NULL, NULL, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
+					
+					++aNames;
 				}
-				else if (stackInfo == STACK_INFO_THIS)
-				{
-					if (JS_GetFrameThis(m->m_pScriptInterface->GetContext(), fp, &val))
-						m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(val, false);
-					else
-						m->m_StackFrameData[stackInfo][nestingLevel] = "";
-				}
+				
+				JS_ReleaseFunctionLocalNameArray(m->m_pScriptInterface->GetContext(), lArray);
+				m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(JS::ObjectValue(*locals), false);
+
 			}
-			
-			counter++;
-			fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
+			m->m_pDebuggingServer->SetBreakRequestedByThread(bbt);
+			m->m_pDebuggingServer->SetBreakRequestedByUser(bbu);
+
 		}
+		else if (stackInfo == STACK_INFO_THIS)
+		{
+			JS::RootedValue jThis(m->m_pScriptInterface->GetContext());
+			JS::MutableHandleValue mjThis(&jThis);
+			aFrame.getThisValue(m->m_pScriptInterface->GetContext(), mjThis);
+			m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(mjThis, false);
+		}
+		
+		JS::FreeStackDescription(m->m_pScriptInterface->GetContext(), description);
 	}
+	
+	
+	
+//	JSStackFrame *iter = 0;
+//	uint counter = 0;
+//	jsval val;
+//	
+//	if (stackInfo == STACK_INFO_GLOBALOBJECT)
+//	{
+//		JSObject* obj;
+//		obj = JS_GetGlobalForScopeChain(m->m_pScriptInterface->GetContext());
+//		m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(OBJECT_TO_JSVAL(obj), false);
+//	}
+//	else
+//	{
+//		JSStackFrame *fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
+//		while (fp)
+//		{
+//			if (counter == nestingLevel)
+//			{
+//				if (stackInfo == STACK_INFO_LOCALS)
+//				{
+//					JSObject* obj;
+//					obj = JS_GetFrameCallObject(m->m_pScriptInterface->GetContext(), fp);
+//					//obj = JS_GetFrameScopeChain(m->m_pScriptInterface->GetContext(), fp);
+//					m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(OBJECT_TO_JSVAL(obj), false);
+//				}
+//				else if (stackInfo == STACK_INFO_THIS)
+//				{
+//					if (JS_GetFrameThis(m->m_pScriptInterface->GetContext(), fp, &val))
+//						m->m_StackFrameData[stackInfo][nestingLevel] = StringifyCyclicJSON(val, false);
+//					else
+//						m->m_StackFrameData[stackInfo][nestingLevel] = "";
+//				}
+//			}
+//			
+//			counter++;
+//			fp = JS_FrameIterator(m->m_pScriptInterface->GetContext(), &iter);
+//		}
+//	}
 }
-*/
 
+
 /*
  * TODO: This is very hacky and ugly and should be improved. 
  * It replaces cyclic references with a notification that cyclic references are not supported. 
@@ -774,7 +877,7 @@
  *    the rest of the game and because this part of code should be replaced anyway in the future.
  */
  
- /*
+
 namespace CyclicRefWorkaround
 {
 	std::set<JSObject*> g_ProcessedObjects;
@@ -785,7 +888,7 @@
 	
 	struct Stringifier
 	{
-		static JSBool callback(const jschar* buf, uint32 len, void* data)
+		static JSBool callback(const jschar* buf, Uint32 len, void* data)
 		{
 			utf16string str(buf, buf+len);
 			std::wstring strw(str.begin(), str.end());
@@ -797,8 +900,8 @@
 
 		std::stringstream stream;
 	};
-	
-	JSBool replacer(JSContext* cx, uintN UNUSED(argc), jsval* vp)
+
+	JSBool replacer(JSContext *cx, unsigned UNUSED(argc), JS::Value *vp)
 	{
 		jsval value = JS_ARGV(cx, vp)[1];
 		jsval key = JS_ARGV(cx, vp)[0];
@@ -807,7 +910,7 @@
 		else
 			g_countSameKeys = 0;
 		
-		if (JSVAL_IS_OBJECT(value))
+		if (value.isObject())
 		{	
 			// Work around a spidermonkey bug that causes replacer to be called twice with the same key:
 			// https://bugzilla.mozilla.org/show_bug.cgi?id=636079
@@ -851,7 +954,7 @@
 		jsval execString;
 		if (JS_GetPendingException(m->m_pScriptInterface->GetContext(), &exec))
 		{
-			if (JSVAL_IS_OBJECT(exec))
+			if (exec.isObject())
 			{
 				JS_GetProperty(m->m_pScriptInterface->GetContext(), JSVAL_TO_OBJECT(exec), "message", &execString);
 			
@@ -936,4 +1039,4 @@
 	CScopeLock lock(m->m_Mutex);
 	return m->m_ID;
 }
-*/
+
Index: source/scriptinterface/ThreadDebugger.h
===================================================================
--- source/scriptinterface/ThreadDebugger.h	(revision 16085)
+++ source/scriptinterface/ThreadDebugger.h	(working copy)
@@ -17,169 +17,169 @@
  
  // JS debugger temporarily disabled during the SpiderMonkey upgrade (check trac ticket #2348 for details)
 
-//#ifndef INCLUDED_THREADDEBUGGER
-//#define INCLUDED_THREADDEBUGGER
-//
-//#include "DebuggingServer.h"
-//#include "ScriptInterface.h"
-//#include "scriptinterface/ScriptExtraHeaders.h"
-//
-//// These Breakpoint classes are not implemented threadsafe. The class using the Breakpoints is responsible to make sure that 
-//// only one thread accesses the Breakpoint at a time
-//class CBreakPoint
-//{
-//public:
-//	CBreakPoint() : m_UserLine(0) { }
-//	
-//	uint m_UserLine;
-//	std::string m_Filename;
-//};
-//
-//// Only use this with one ScriptInterface/CThreadDebugger!
-//class CActiveBreakPoint : public CBreakPoint
-//{
-//public:
-//	CActiveBreakPoint()
-//		: m_ActualLine(m_UserLine)
-//		, m_Script(NULL)
-//		, m_Pc(NULL)
-//		, m_ToRemove(false)
-//	{ }
-//
-//	CActiveBreakPoint(CBreakPoint breakPoint)
-//		: CBreakPoint(breakPoint) // using default copy constructor
-//		, m_ActualLine(m_UserLine)
-//		, m_Script(NULL)
-//		, m_Pc(NULL)
-//		, m_ToRemove(false)
-//	{ }
-//	
-//	uint m_ActualLine;
-//	JSScript* m_Script;
-//	jsbytecode* m_Pc;
-//	bool m_ToRemove;
-//};
-//
-//enum BREAK_SRC { BREAK_SRC_TRAP, BREAK_SRC_INTERRUP, BREAK_SRC_EXCEPTION };
-//
-//struct ThreadDebugger_impl;
-//
-//class CThreadDebugger
-//{
-//public:
-//	CThreadDebugger();
-//	~CThreadDebugger();
-//
-//	/** @brief Initialize the object (required before using the object!).
-//	 *
-//	 * @param	id A unique identifier greater than 0 for the object inside its CDebuggingServer object.
-//	 * @param 	name A name that will be can be displayed by the UI to identify the thread.
-//	 * @param	pScriptInterface Pointer to a scriptinterface. All Hooks, breakpoint traps etc. will be registered in this 
-//	 *          scriptinterface and will be called by the thread this scriptinterface is running in.
-//	 * @param	pDebuggingServer Pointer to the DebuggingServer object this Object should belong to.
-//	 *
-//	 * @return	Return value.
-//	 */
-//	void Initialize(uint id, std::string name, ScriptInterface* pScriptInterface, CDebuggingServer* pDebuggingServer);
-//	
-//	
-//	// A bunch of hooks used to get information from spidermonkey.
-//	// These hooks are used internally only but have to be public because they need to be accessible from the global hook functions.
-//	// Spidermonkey requires function pointers as hooks, which only works if the functions are global or static (not part of an object).
-//	// These global functions in ThreadDebugger.cpp are just wrappers for the following member functions.
-//	
-//	/** Simply calls BreakHandler with BREAK_SRC_TRAP */
-//	JSTrapStatus TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, jsval closure);
-//	/** Hook to capture exceptions and breakpoints in code (throw "Breakpoint";) */
-//	JSTrapStatus ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval);
-//	/** All other hooks call this one if the execution should be paused. It puts the program in a wait-loop and 
-//	 *  waits for weak-up events (continue, step etc.). */
-//	JSTrapStatus BreakHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, jsval closure, BREAK_SRC breakSrc);
-//	JSTrapStatus StepHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure);
-//	JSTrapStatus StepIntoHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure);
-//	JSTrapStatus StepOutHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure);
-//	/** This is an interrup-hook that can be called multiple times per line of code and is used to break into the execution
-//	  * without previously setting a breakpoint and to break other threads when one thread triggers a breakpoint */
-//	JSTrapStatus CheckForBreakRequestHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure);
-//	/** The callback function which gets executed for each new script that gets loaded and each function inside a script.
-//	 *   We use it for "Execute-Hooks" and "Call-Hooks" in terms of Spidermonkey.
-//	 *   This hook actually sets the traps (Breakpoints) "on the fly" that have been defined by the user previously.
-//	 */
-//	void ExecuteHook(JSContext *cx, const char *filename, unsigned lineno, JSScript *script, JSFunction *fun, void *callerdata);
-//	/** This hook is used to update the mapping between filename plus line-numbers and jsbytecode pointers */
-//	void NewScriptHook(JSContext *cx, const char *filename, unsigned lineno, JSScript *script, JSFunction *fun, void *callerdata);
-//	/** This hook makes sure that invalid mappings between filename plus line-number and jsbytecode points get deleted */
-//	void DestroyScriptHook(JSContext *cx, JSScript *script);
-//	
-//
-//	void ClearTrap(CActiveBreakPoint* activeBreakPoint);
-//	
-//	/** @brief Checks if a mapping for the specified filename and line number exists in this CThreadDebugger's context
-//	 */	
-//	bool CheckIfMappingPresent(std::string filename, uint line);
-//	
-//	/** @brief Checks if a mapping exists for each breakpoint in the list of breakpoints that aren't set yet.
-//	 *         If there is a mapping, it removes the breakpoint from the list of unset breakpoints (from CDebuggingServer),
-//	 *         adds it to the list of active breakpoints (CThreadDebugger) and sets a trap.
-//	 *         Threading: m_Mutex is locked in this call
-//	 */	
-//	void SetAllNewTraps();
-//	
-//	/** @brief Sets a new trap and stores the information in the CActiveBreakPoint pointer
-//	 *         Make sure that a mapping exists before calling this function
-//	 *         Threading: Locking m_Mutex is required by the callee
-//	 */	
-//	void SetNewTrap(CActiveBreakPoint* activeBreakPoint, std::string filename, uint line);
-//
-//	/** @brief Toggle a breakpoint if it's active in this threadDebugger object.
-//	 *         Threading: Locking m_Mutex is required by the callee
-//	 *
-//	 * @param	filename full vfs path to the script filename
-//	 * @param 	userLine linenumber where the USER set the breakpoint (UserLine)
-//	 *
-//	 * @return	true if the breakpoint's state was changed
-//	 */
-//	bool ToggleBreakPoint(std::string filename, uint userLine);
-//	
-//	
-//	void GetCallstack(std::stringstream& response);
-//	void GetStackFrameData(std::stringstream& response, uint nestingLevel, STACK_INFO stackInfoKind);
-//	
-//	/** @brief Compares the object's associated scriptinterface with the pointer passed as parameter.
-//	 * @return true if equal
-//	 */
-//	bool CompareScriptInterfacePtr(ScriptInterface* pScriptInterface) const;
-//	
-//	// Getter/Setters for members that need to be threadsafe
-//	std::string GetBreakFileName();
-//	bool GetIsInBreak();
-//	uint GetLastBreakLine();
-//	std::string GetName();
-//	uint GetID();
+#ifndef INCLUDED_THREADDEBUGGER
+#define INCLUDED_THREADDEBUGGER
+
+#include "DebuggingServer.h"
+#include "ScriptInterface.h"
+#include "scriptinterface/ScriptExtraHeaders.h"
+
+// These Breakpoint classes are not implemented threadsafe. The class using the Breakpoints is responsible to make sure that 
+// only one thread accesses the Breakpoint at a time
+class CBreakPoint
+{
+public:
+	CBreakPoint() : m_UserLine(0) { }
+	
+	uint m_UserLine;
+	std::string m_Filename;
+};
+
+// Only use this with one ScriptInterface/CThreadDebugger!
+class CActiveBreakPoint : public CBreakPoint
+{
+public:
+	CActiveBreakPoint()
+		: m_ActualLine(m_UserLine)
+		, m_Script(NULL)
+		, m_Pc(NULL)
+		, m_ToRemove(false)
+	{ }
+
+	CActiveBreakPoint(CBreakPoint breakPoint)
+		: CBreakPoint(breakPoint) // using default copy constructor
+		, m_ActualLine(m_UserLine)
+		, m_Script(NULL)
+		, m_Pc(NULL)
+		, m_ToRemove(false)
+	{ }
+	
+	uint m_ActualLine;
+	JSScript* m_Script;
+	jsbytecode* m_Pc;
+	bool m_ToRemove;
+};
+
+enum BREAK_SRC { BREAK_SRC_TRAP, BREAK_SRC_INTERRUP, BREAK_SRC_EXCEPTION };
+
+struct ThreadDebugger_impl;
+
+class CThreadDebugger
+{
+public:
+	CThreadDebugger();
+	~CThreadDebugger();
+
+	/** @brief Initialize the object (required before using the object!).
+	 *
+	 * @param	id A unique identifier greater than 0 for the object inside its CDebuggingServer object.
+	 * @param 	name A name that will be can be displayed by the UI to identify the thread.
+	 * @param	pScriptInterface Pointer to a scriptinterface. All Hooks, breakpoint traps etc. will be registered in this 
+	 *          scriptinterface and will be called by the thread this scriptinterface is running in.
+	 * @param	pDebuggingServer Pointer to the DebuggingServer object this Object should belong to.
+	 *
+	 * @return	Return value.
+	 */
+	void Initialize(uint id, std::string name, ScriptInterface* pScriptInterface, CDebuggingServer* pDebuggingServer);
+	
+	
+	// A bunch of hooks used to get information from spidermonkey.
+	// These hooks are used internally only but have to be public because they need to be accessible from the global hook functions.
+	// Spidermonkey requires function pointers as hooks, which only works if the functions are global or static (not part of an object).
+	// These global functions in ThreadDebugger.cpp are just wrappers for the following member functions.
+	
+	/** Simply calls BreakHandler with BREAK_SRC_TRAP */
+	JSTrapStatus TrapHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, jsval closure);
+	/** Hook to capture exceptions and breakpoints in code (throw "Breakpoint";) */
+	JSTrapStatus ThrowHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval);
+	/** All other hooks call this one if the execution should be paused. It puts the program in a wait-loop and
+	 *  waits for weak-up events (continue, step etc.). */
+	JSTrapStatus BreakHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, jsval closure, BREAK_SRC breakSrc);
+	JSTrapStatus StepHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure);
+	JSTrapStatus StepIntoHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure);
+	JSTrapStatus StepOutHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure);
+	/** This is an interrup-hook that can be called multiple times per line of code and is used to break into the execution
+	  * without previously setting a breakpoint and to break other threads when one thread triggers a breakpoint */
+	JSTrapStatus CheckForBreakRequestHandler(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval, void *closure);
+	/** The callback function which gets executed for each new script that gets loaded and each function inside a script.
+	 *   We use it for "Execute-Hooks" and "Call-Hooks" in terms of Spidermonkey.
+	 *   This hook actually sets the traps (Breakpoints) "on the fly" that have been defined by the user previously.
+	 */
+	void ExecuteHook(JSContext *cx, const char *filename, unsigned lineno, JSScript *script, JSFunction *fun, void *callerdata);
+	/** This hook is used to update the mapping between filename plus line-numbers and jsbytecode pointers */
+	void NewScriptHook(JSContext *cx, const char *filename, unsigned lineno, JSScript *script, JSFunction *fun, void *callerdata);
+	/** This hook makes sure that invalid mappings between filename plus line-number and jsbytecode points get deleted */
+	void DestroyScriptHook(JSContext *cx, JSScript *script);
+	
+
+	void ClearTrap(CActiveBreakPoint* activeBreakPoint);
+	
+	/** @brief Checks if a mapping for the specified filename and line number exists in this CThreadDebugger's context
+	 */	
+	bool CheckIfMappingPresent(std::string filename, uint line);
+	
+	/** @brief Checks if a mapping exists for each breakpoint in the list of breakpoints that aren't set yet.
+	 *         If there is a mapping, it removes the breakpoint from the list of unset breakpoints (from CDebuggingServer),
+	 *         adds it to the list of active breakpoints (CThreadDebugger) and sets a trap.
+	 *         Threading: m_Mutex is locked in this call
+	 */	
+	void SetAllNewTraps();
+	
+	/** @brief Sets a new trap and stores the information in the CActiveBreakPoint pointer
+	 *         Make sure that a mapping exists before calling this function
+	 *         Threading: Locking m_Mutex is required by the callee
+	 */	
+	void SetNewTrap(CActiveBreakPoint* activeBreakPoint, std::string filename, uint line);
+
+	/** @brief Toggle a breakpoint if it's active in this threadDebugger object.
+	 *         Threading: Locking m_Mutex is required by the callee
+	 *
+	 * @param	filename full vfs path to the script filename
+	 * @param 	userLine linenumber where the USER set the breakpoint (UserLine)
+	 *
+	 * @return	true if the breakpoint's state was changed
+	 */
+	bool ToggleBreakPoint(std::string filename, uint userLine);
+	
+	
+	void GetCallstack(std::stringstream& response);
+	void GetStackFrameData(std::stringstream& response, uint nestingLevel, STACK_INFO stackInfoKind);
+	
+	/** @brief Compares the object's associated scriptinterface with the pointer passed as parameter.
+	 * @return true if equal
+	 */
+	bool CompareScriptInterfacePtr(ScriptInterface* pScriptInterface) const;
+	
+	// Getter/Setters for members that need to be threadsafe
+	std::string GetBreakFileName();
+	bool GetIsInBreak();
+	uint GetLastBreakLine();
+	std::string GetName();
+	uint GetID();
 //	void ContinueExecution();
-//	void SetNextDbgCmd(DBGCMD dbgCmd);
-//	DBGCMD GetNextDbgCmd();
-//	// The callee is responsible for locking m_Mutex
-//	void AddStackInfoRequest(STACK_INFO requestType, uint nestingLevel, SDL_sem* semaphore);
-//	
-//	
-//private:
-//	// Getters/Setters for members that need to be threadsafe
-//	void SetBreakFileName(std::string breakFileName);
-//	void SetLastBreakLine(uint breakLine);
-//	void SetIsInBreak(bool isInBreak);
-//	
-//	// Other threadsafe functions
-//	void SaveCallstack();
-//	
-//	/// Used only in the scriptinterface's thread.
-//	void ClearTrapsToRemove();
-//	bool CurrentFrameIsChildOf(JSStackFrame* pParentFrame);
-//	void ReturnActiveBreakPoints(jsbytecode* pBytecode);
-//	void SaveStackFrameData(STACK_INFO stackInfo, uint nestingLevel);
-//	std::string StringifyCyclicJSON(jsval obj, bool indent);
-//
-//	std::auto_ptr<ThreadDebugger_impl> m;
-//};
-//
-//#endif // INCLUDED_THREADDEBUGGER
+	void SetNextDbgCmd(DBGCMD dbgCmd);
+	DBGCMD GetNextDbgCmd();
+	// The callee is responsible for locking m_Mutex
+	void AddStackInfoRequest(STACK_INFO requestType, uint nestingLevel, SDL_sem* semaphore);
+	
+	
+private:
+	// Getters/Setters for members that need to be threadsafe
+	void SetBreakFileName(std::string breakFileName);
+	void SetLastBreakLine(uint breakLine);
+	void SetIsInBreak(bool isInBreak);
+	
+	// Other threadsafe functions
+	void SaveCallstack();
+	
+	/// Used only in the scriptinterface's thread.
+	void ClearTrapsToRemove();
+	bool CurrentFrameIsChildOf(JS::StackDescription* description, JS::FrameDescription* frame);
+	void ReturnActiveBreakPoints(jsbytecode* pBytecode);
+	void SaveStackFrameData(STACK_INFO stackInfo, uint nestingLevel);
+	std::string StringifyCyclicJSON(jsval obj, bool indent);
+
+	std::auto_ptr<ThreadDebugger_impl> m;
+};
+
+#endif // INCLUDED_THREADDEBUGGER