diff --git a/browser/devtools/debugger/test/browser.ini b/browser/devtools/debugger/test/browser.ini
index a53f9dc5873d..9f701ec82980 100644
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -47,6 +47,7 @@ support-files =
doc_frame-parameters.html
doc_function-display-name.html
doc_function-search.html
+ doc_global-method-override.html
doc_iframes.html
doc_included-script.html
doc_inline-debugger-statement.html
@@ -122,6 +123,7 @@ support-files =
[browser_dbg_event-listeners.js]
[browser_dbg_file-reload.js]
[browser_dbg_function-display-name.js]
+[browser_dbg_global-method-override.js]
[browser_dbg_globalactor.js]
[browser_dbg_host-layout.js]
[browser_dbg_iframes.js]
diff --git a/browser/devtools/debugger/test/browser_dbg_global-method-override.js b/browser/devtools/debugger/test/browser_dbg_global-method-override.js
new file mode 100644
index 000000000000..0f204eeddb05
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_global-method-override.js
@@ -0,0 +1,20 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests that scripts that override properties of the global object, like
+ * toString don't break the debugger. The test page used to cause the debugger
+ * to throw when trying to attach to the thread actor.
+ */
+
+const TAB_URL = EXAMPLE_URL + "doc_global-method-override.html";
+
+function test() {
+ initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+ let gDebugger = aPanel.panelWin;
+ ok(gDebugger, "Should have a debugger available.");
+ is(gDebugger.gThreadClient.state, "attached", "Debugger should be attached.");
+
+ closeDebuggerAndFinish(aPanel);
+ });
+}
diff --git a/browser/devtools/debugger/test/doc_global-method-override.html b/browser/devtools/debugger/test/doc_global-method-override.html
new file mode 100644
index 000000000000..d8cf750fc159
--- /dev/null
+++ b/browser/devtools/debugger/test/doc_global-method-override.html
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+ Debugger global method override test page
+
+
+
+
+
diff --git a/toolkit/devtools/server/actors/script.js b/toolkit/devtools/server/actors/script.js
index 945684ff0649..ace0e9a83d10 100644
--- a/toolkit/devtools/server/actors/script.js
+++ b/toolkit/devtools/server/actors/script.js
@@ -436,7 +436,10 @@ function ThreadActor(aHooks, aGlobal)
this._state = "detached";
this._frameActors = [];
this._hooks = aHooks;
- this.global = aGlobal;
+ this.global = this.globalSafe = aGlobal;
+ if (aGlobal && aGlobal.wrappedJSObject) {
+ this.global = aGlobal.wrappedJSObject;
+ }
// A map of actorID -> actor for breakpoints created and managed by the server.
this._hiddenBreakpoints = new Map();
@@ -1763,7 +1766,7 @@ ThreadActor.prototype = {
// Clear DOM event breakpoints.
// XPCShell tests don't use actual DOM windows for globals and cause
// removeListenerForAllEvents to throw.
- if (this.global && !this.global.toString().contains("Sandbox")) {
+ if (this.globalSafe && !this.globalSafe.toString().contains("Sandbox")) {
let els = Cc["@mozilla.org/eventlistenerservice;1"]
.getService(Ci.nsIEventListenerService);
els.removeListenerForAllEvents(this.global, this._allEventsListener, true);
diff --git a/toolkit/devtools/server/actors/webbrowser.js b/toolkit/devtools/server/actors/webbrowser.js
index f13b2b91d5b8..ac3ba31eab9d 100644
--- a/toolkit/devtools/server/actors/webbrowser.js
+++ b/toolkit/devtools/server/actors/webbrowser.js
@@ -655,7 +655,7 @@ BrowserTabActor.prototype = {
this._contextPool = new ActorPool(this.conn);
this.conn.addActorPool(this._contextPool);
- this.threadActor = new ThreadActor(this, this.window.wrappedJSObject);
+ this.threadActor = new ThreadActor(this, this.window);
this._contextPool.addActor(this.threadActor);
},
diff --git a/toolkit/devtools/server/tests/unit/testactors.js b/toolkit/devtools/server/tests/unit/testactors.js
index 14ce07eeee6b..cafc756de9c1 100644
--- a/toolkit/devtools/server/tests/unit/testactors.js
+++ b/toolkit/devtools/server/tests/unit/testactors.js
@@ -57,6 +57,7 @@ function TestTabActor(aConnection, aGlobal)
{
this.conn = aConnection;
this._global = aGlobal;
+ this._global.wrappedJSObject = aGlobal;
this._threadActor = new ThreadActor(this, this._global);
this.conn.addActor(this._threadActor);
this._attached = false;
diff --git a/toolkit/devtools/server/tests/unit/testcompatactors.js b/toolkit/devtools/server/tests/unit/testcompatactors.js
index f901c15aaba5..bdcb420fbe05 100644
--- a/toolkit/devtools/server/tests/unit/testcompatactors.js
+++ b/toolkit/devtools/server/tests/unit/testcompatactors.js
@@ -113,5 +113,6 @@ function createRootActor()
DebuggerServer.addTestGlobal = function addTestGlobal(aGlobal)
{
+ aGlobal.wrappedJSObject = aGlobal;
gTestGlobals.push(aGlobal);
}