Bug 987672 - Use a more reliable Function constructor and |bind| implementation for marquee event handler compilation. r=bz

This commit is contained in:
Bobby Holley 2014-03-25 12:36:39 -03:00
parent cbaedea4c8
commit b43cea4e4c
2 changed files with 20 additions and 7 deletions

View File

@ -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.

View File

@ -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;