Bug 1088228 part 5. Use the new CloneFunctionObject in XBL. r=peterv

This commit is contained in:
Boris Zbarsky 2014-10-30 17:40:17 -04:00
Родитель 7156407be9
Коммит e08b9cd7ca
2 изменённых файлов: 22 добавлений и 21 удалений

Просмотреть файл

@ -18,6 +18,7 @@
#include "nsIXPConnect.h"
#include "xpcpublic.h"
#include "nsXBLPrototypeBinding.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/ScriptSettings.h"
using namespace mozilla;
@ -269,6 +270,7 @@ nsXBLProtoImplMethod::Write(nsIObjectOutputStream* aStream)
nsresult
nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAddonId)
{
MOZ_ASSERT(aBoundElement->IsElement());
NS_PRECONDITION(IsCompiled(), "Can't execute uncompiled method");
if (!GetCompiledMethod()) {
@ -295,23 +297,22 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAd
JS::Rooted<JSObject*> globalObject(cx, global->GetGlobalJSObject());
JS::Rooted<JS::Value> v(cx);
nsresult rv = nsContentUtils::WrapNative(cx, aBoundElement, &v);
NS_ENSURE_SUCCESS(rv, rv);
JS::Rooted<JSObject*> thisObject(cx, &v.toObject());
JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, globalObject, aAddonId));
NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
JSAutoCompartment ac(cx, scopeObject);
if (!JS_WrapObject(cx, &thisObject))
JS::AutoObjectVector scopeChain(cx);
if (!nsJSUtils::GetScopeChainForElement(cx, aBoundElement->AsElement(),
scopeChain)) {
return NS_ERROR_OUT_OF_MEMORY;
}
MOZ_ASSERT(scopeChain.length() != 0);
// Clone the function object, using thisObject as the parent so "this" is in
// the scope chain of the resulting function (for backwards compat to the
// days when this was an event handler).
// Clone the function object, using our scope chain (for backwards
// compat to the days when this was an event handler).
JS::Rooted<JSObject*> jsMethodObject(cx, GetCompiledMethod());
JS::Rooted<JSObject*> method(cx, ::JS_CloneFunctionObject(cx, jsMethodObject, thisObject));
JS::Rooted<JSObject*> method(cx, JS::CloneFunctionObject(cx, jsMethodObject,
scopeChain));
if (!method)
return NS_ERROR_OUT_OF_MEMORY;
@ -325,7 +326,7 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAd
if (scriptAllowed) {
JS::Rooted<JS::Value> retval(cx);
JS::Rooted<JS::Value> methodVal(cx, JS::ObjectValue(*method));
ok = ::JS::Call(cx, thisObject, methodVal, JS::HandleValueArray::empty(), &retval);
ok = ::JS::Call(cx, scopeChain[0], methodVal, JS::HandleValueArray::empty(), &retval);
}
if (!ok) {

Просмотреть файл

@ -44,6 +44,7 @@
#include "mozilla/BasicEvents.h"
#include "mozilla/JSEventHandler.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/EventHandlerBinding.h"
#include "mozilla/dom/ScriptSettings.h"
#include "xpcpublic.h"
@ -300,16 +301,15 @@ nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
MOZ_ASSERT(!js::IsCrossCompartmentWrapper(genericHandler));
// Wrap the native into the XBL scope. This creates a reflector in the document
// scope if one doesn't already exist, and potentially wraps it cross-
// compartment into our scope (via aAllowWrapping=true).
JS::Rooted<JS::Value> targetV(cx, JS::UndefinedValue());
rv = nsContentUtils::WrapNative(cx, scriptTarget, &targetV);
NS_ENSURE_SUCCESS(rv, rv);
// Build a scope chain in the XBL scope.
nsRefPtr<Element> targetElement = do_QueryObject(scriptTarget);
JS::AutoObjectVector scopeChain(cx);
ok = nsJSUtils::GetScopeChainForElement(cx, targetElement, scopeChain);
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
// Next, clone the generic handler to be parented to the target.
JS::Rooted<JSObject*> target(cx, &targetV.toObject());
JS::Rooted<JSObject*> bound(cx, JS_CloneFunctionObject(cx, genericHandler, target));
// Next, clone the generic handler with our desired scope chain.
JS::Rooted<JSObject*> bound(cx, JS::CloneFunctionObject(cx, genericHandler,
scopeChain));
NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE);
nsRefPtr<EventHandlerNonNull> handlerCallback =