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;