diff --git a/dom/xbl/test/file_bug821850.xhtml b/dom/xbl/test/file_bug821850.xhtml
index 08440b7ab9b..37c02cbd744 100644
--- a/dom/xbl/test/file_bug821850.xhtml
+++ b/dom/xbl/test/file_bug821850.xhtml
@@ -59,6 +59,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=821850
is(document.QueryInterface(Components.interfaces.nsIDOMDocument),
document, "Should be able to QI the document");
+ // Make sure standard constructors work right in the presence of
+ // sandboxPrototype and Xray-resolved constructors.
+ is(window.Function, XPCNativeWrapper(window.wrappedJSObject.Function),
+ "window.Function comes from the window, not the global");
+ ok(Function != window.Function, "Function constructors are distinct");
+ is(Object.getPrototypeOf(Function.prototype), Object.getPrototypeOf({foo: 42}),
+ "Function constructor is local");
+
// This gets invoked by an event handler.
window.finish = function() {
// Content messed with stuff. Make sure we still see the right thing.
diff --git a/layout/style/xbl-marquee/xbl-marquee.xml b/layout/style/xbl-marquee/xbl-marquee.xml
index 50e96449e3e..35bccd8840a 100644
--- a/layout/style/xbl-marquee/xbl-marquee.xml
+++ b/layout/style/xbl-marquee/xbl-marquee.xml
@@ -259,13 +259,18 @@
case "string":
if (!aIgnoreNextCall) {
try {
- // Work around bug 872772 by wrapping the cross-compartment-
- // wrapped function in a function from this scope.
- //
- // NB: Make sure to wrap the constructor in parentheses to
- // deal with the weird precedence of |new| in JS.
- var contentFn = new (XPCNativeWrapper.unwrap(window).Function)("event", aValue);
- this["_on" + aName] = function(e) { return contentFn.call(this, e); };
+ // Things to watch out for here:
+ // * Weird |new| precedence.
+ // * Getting the correct constructor (via Xrays).
+ // * Waiving the constructor before invoking it, so that we can
+ // call it (since XBL gets opaque non-callable wrappers to content).
+ // * The fact that contentFn is transitively waived, which we need
+ // in order to be able to invoke it.
+ // * Using the local |bind| to be sure that it does the right thing.
+ // Note that the underlying function still executes in the content
+ // scope.
+ var contentFn = new (XPCNativeWrapper.unwrap(window.Function))("event", aValue);
+ this["_on" + aName] = Function.prototype.bind.call(contentFn, this);
}
catch(e) {
return false;