Bug 773945, remove nsXULElement::mPrototype, part 1, r=bz

This commit is contained in:
Olli Pettay 2012-07-14 14:28:35 +03:00
parent 4e94797ac0
commit ea0631cee7
6 changed files with 21 additions and 267 deletions

View File

@ -40,7 +40,6 @@
#include "nsMutationEvent.h"
#include "nsIXPConnect.h"
#include "nsDOMCID.h"
#include "nsIScriptEventHandlerOwner.h"
#include "nsFocusManager.h"
#include "nsIDOMElement.h"
#include "nsContentUtils.h"
@ -662,21 +661,8 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
NS_ASSERTION(!listener->GetHandler(), "What is there to compile?");
nsIScriptContext *context = listener->GetEventContext();
nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner =
do_QueryInterface(mTarget);
nsScriptObjectHolder<JSObject> handler(context);
if (handlerOwner) {
result = handlerOwner->GetCompiledEventHandler(aListenerStruct->mTypeAtom,
handler);
if (NS_SUCCEEDED(result) && handler) {
aListenerStruct->mHandlerIsString = false;
} else {
// Make sure there's nothing in the holder in the failure case
handler.set(nsnull);
}
}
if (aListenerStruct->mHandlerIsString) {
// OK, we didn't find an existing compiled event handler. Flag us
// as not a string so we don't keep trying to compile strings
@ -745,41 +731,29 @@ nsEventListenerManager::CompileEventHandlerInternal(nsListenerStruct *aListenerS
return NS_ERROR_FAILURE;
}
PRUint32 argCount;
const char **argNames;
// If no content, then just use kNameSpaceID_None for the
// namespace ID. In practice, it doesn't matter since SVG is
// the only thing with weird arg names and SVG doesn't map event
// listeners to the window.
nsContentUtils::GetEventArgNames(content ?
content->GetNameSpaceID() :
kNameSpaceID_None,
aListenerStruct->mTypeAtom,
&argCount, &argNames);
if (handlerOwner) {
// Always let the handler owner compile the event
// handler, as it may want to use a special
// context or scope object.
result = handlerOwner->CompileEventHandler(context,
aListenerStruct->mTypeAtom,
*body,
url.get(), lineNo,
handler);
} else {
PRUint32 argCount;
const char **argNames;
// If no content, then just use kNameSpaceID_None for the
// namespace ID. In practice, it doesn't matter since SVG is
// the only thing with weird arg names and SVG doesn't map event
// listeners to the window.
nsContentUtils::GetEventArgNames(content ?
content->GetNameSpaceID() :
kNameSpaceID_None,
aListenerStruct->mTypeAtom,
&argCount, &argNames);
result = context->CompileEventHandler(aListenerStruct->mTypeAtom,
argCount, argNames,
*body,
url.get(), lineNo,
SCRIPTVERSION_DEFAULT, // for now?
handler);
if (result == NS_ERROR_ILLEGAL_VALUE) {
NS_WARNING("Probably a syntax error in the event handler!");
return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;
}
NS_ENSURE_SUCCESS(result, result);
result = context->CompileEventHandler(aListenerStruct->mTypeAtom,
argCount, argNames,
*body,
url.get(), lineNo,
SCRIPTVERSION_DEFAULT, // for now?
handler);
if (result == NS_ERROR_ILLEGAL_VALUE) {
NS_WARNING("Probably a syntax error in the event handler!");
return NS_SUCCESS_LOSS_OF_INSIGNIFICANT_DATA;
}
NS_ENSURE_SUCCESS(result, result);
}
if (handler) {

View File

@ -104,32 +104,6 @@
namespace css = mozilla::css;
/**
* A tearoff class for nsXULElement to implement nsIScriptEventHandlerOwner.
*/
class nsScriptEventHandlerOwnerTearoff MOZ_FINAL : public nsIScriptEventHandlerOwner
{
public:
nsScriptEventHandlerOwnerTearoff(nsXULElement* aElement)
: mElement(aElement) {}
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS(nsScriptEventHandlerOwnerTearoff)
// nsIScriptEventHandlerOwner
virtual nsresult CompileEventHandler(nsIScriptContext* aContext,
nsIAtom *aName,
const nsAString& aBody,
const char* aURL,
PRUint32 aLineNo,
nsScriptObjectHolder<JSObject>& aHandler);
virtual nsresult GetCompiledEventHandler(nsIAtom *aName,
nsScriptObjectHolder<JSObject>& aHandler);
private:
nsRefPtr<nsXULElement> mElement;
};
//----------------------------------------------------------------------
static NS_DEFINE_CID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID);
@ -350,8 +324,6 @@ NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(nsXULElement)
NS_INTERFACE_TABLE_ENTRY(nsXULElement, nsIDOMXULElement)
NS_OFFSET_AND_INTERFACE_TABLE_END
NS_ELEMENT_INTERFACE_TABLE_TO_MAP_SEGUE
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIScriptEventHandlerOwner,
new nsScriptEventHandlerOwnerTearoff(this))
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMElementCSSInlineStyle,
new nsXULElementTearoff(this))
NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIFrameLoaderOwner,
@ -643,130 +615,7 @@ nsXULElement::PerformAccesskey(bool aKeyCausesActivation,
}
}
//----------------------------------------------------------------------
// nsIScriptEventHandlerOwner interface
NS_IMPL_CYCLE_COLLECTION_CLASS(nsScriptEventHandlerOwnerTearoff)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsScriptEventHandlerOwnerTearoff)
tmp->mElement = nsnull;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsScriptEventHandlerOwnerTearoff)
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mElement");
cb.NoteXPCOMChild(static_cast<nsIContent*>(tmp->mElement));
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsScriptEventHandlerOwnerTearoff)
NS_INTERFACE_MAP_ENTRY(nsIScriptEventHandlerOwner)
NS_INTERFACE_MAP_END_AGGREGATED(mElement)
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsScriptEventHandlerOwnerTearoff)
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsScriptEventHandlerOwnerTearoff)
nsresult
nsScriptEventHandlerOwnerTearoff::GetCompiledEventHandler(
nsIAtom *aName,
nsScriptObjectHolder<JSObject>& aHandler)
{
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheTests);
aHandler.drop();
nsXULPrototypeAttribute *attr =
mElement->FindPrototypeAttribute(kNameSpaceID_None, aName);
if (attr) {
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheHits);
aHandler.set(attr->mEventHandler);
}
return NS_OK;
}
nsresult
nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
nsIScriptContext* aContext,
nsIAtom *aName,
const nsAString& aBody,
const char* aURL,
PRUint32 aLineNo,
nsScriptObjectHolder<JSObject>& aHandler)
{
nsresult rv;
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheSets);
// XXX sXBL/XBL2 issue! Owner or current document?
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mElement->OwnerDoc());
nsIScriptContext* context = NULL;
nsXULPrototypeElement* elem = mElement->mPrototype;
if (elem && xuldoc) {
// It'll be shared among the instances of the prototype.
// Use the prototype document's special context. Because
// scopeObject is null, the JS engine has no other source of
// <the-new-shared-event-handler>.__proto__ than to look in
// cx->globalObject for Function.prototype. That prototype
// keeps the global object alive, so if we use this document's
// global object, we'll be putting something in the prototype
// that protects this document's global object from GC.
nsCOMPtr<nsIScriptGlobalObjectOwner> globalOwner;
rv = xuldoc->GetScriptGlobalObjectOwner(getter_AddRefs(globalOwner));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(globalOwner, NS_ERROR_UNEXPECTED);
nsIScriptGlobalObject* global = globalOwner->GetScriptGlobalObject();
NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED);
context = global->GetScriptContext();
// It could be possible the language has been setup on aContext but
// not on the global - we don't demand-create language contexts on the
// nsGlobalWindow
NS_ASSERTION(context,
"Failed to get a language context from the global!?");
NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
}
else {
context = aContext;
}
// Compile the event handler
PRUint32 argCount;
const char **argNames;
nsContentUtils::GetEventArgNames(kNameSpaceID_XUL, aName, &argCount,
&argNames);
nsCxPusher pusher;
if (!pusher.Push(context->GetNativeContext())) {
return NS_ERROR_FAILURE;
}
rv = context->CompileEventHandler(aName, argCount, argNames,
aBody, aURL, aLineNo,
SCRIPTVERSION_DEFAULT, // for now?
aHandler);
if (NS_FAILED(rv)) return rv;
nsXULPrototypeAttribute *attr =
mElement->FindPrototypeAttribute(kNameSpaceID_None, aName);
if (attr) {
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
// take a copy of the event handler, and tell the language about it.
if (aHandler) {
NS_ASSERTION(!attr->mEventHandler, "Leaking handler.");
if (!elem->mHoldsScriptObject) {
rv = nsContentUtils::HoldJSObjects(
elem, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode));
NS_ENSURE_SUCCESS(rv, rv);
}
elem->mHoldsScriptObject = true;
}
attr->mEventHandler = aHandler.get();
}
return NS_OK;
}
void
nsXULElement::AddListenerFor(const nsAttrName& aName,

View File

@ -25,7 +25,6 @@
#include "nsEventListenerManager.h"
#include "nsIRDFCompositeDataSource.h"
#include "nsIRDFResource.h"
#include "nsIScriptEventHandlerOwner.h"
#include "nsBindingManager.h"
#include "nsIURI.h"
#include "nsIXULTemplateBuilder.h"
@ -617,8 +616,6 @@ protected:
Create(nsXULPrototypeElement* aPrototype, nsINodeInfo *aNodeInfo,
bool aIsScriptable);
friend class nsScriptEventHandlerOwnerTearoff;
bool IsReadWriteTextElement() const
{
const nsIAtom* tag = Tag();

View File

@ -56,7 +56,6 @@ EXPORTS = \
nsIScriptGlobalObject.h \
nsIScriptGlobalObjectOwner.h \
nsIScriptNameSpaceManager.h \
nsIScriptEventHandlerOwner.h \
nsIScriptObjectPrincipal.h \
nsIScriptRuntime.h \
nsIScriptTimeoutHandler.h \

View File

@ -85,7 +85,6 @@
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsScriptNameSpaceManager.h"
#include "nsIScriptEventHandlerOwner.h"
#include "nsIJSNativeInitializer.h"
#include "nsJSEnvironment.h"

View File

@ -1,64 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsIScriptEventHandlerOwner_h__
#define nsIScriptEventHandlerOwner_h__
#include "nsISupports.h"
#include "nsIScriptContext.h"
#include "nsAString.h"
template<class> class nsScriptObjectHolder;
class nsIAtom;
#define NS_ISCRIPTEVENTHANDLEROWNER_IID \
{ 0xc8f35f71, 0x07d1, 0x4ff3, \
{ 0xa3, 0x2f, 0x65, 0xcb, 0x35, 0x64, 0xac, 0xe0 } }
/**
* Associate a compiled event handler with its target object, which owns it
* This is an adjunct to nsIScriptObjectOwner that nsEventListenerManager's
* implementation queries for, in order to avoid recompiling a recurrent or
* prototype-inherited event handler.
*/
class nsIScriptEventHandlerOwner : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCRIPTEVENTHANDLEROWNER_IID)
/**
* Compile the specified event handler. This does NOT bind it to
* anything. That's the caller's responsibility.
*
* @param aContext the context to use when creating event handler
* @param aName the name of the handler
* @param aBody the handler script body
* @param aURL the URL or filename for error messages
* @param aLineNo the starting line number of the script for error messages
* @param aHandler the holder for the compiled handler object
*/
virtual nsresult CompileEventHandler(nsIScriptContext* aContext,
nsIAtom *aName,
const nsAString& aBody,
const char* aURL,
PRUint32 aLineNo,
nsScriptObjectHolder<JSObject>& aHandler) = 0;
/**
* Retrieve an already-compiled event handler that can be bound to a
* target object using a script context.
*
* @param aName the name of the event handler to retrieve
* @param aHandler the holder for the compiled event handler.
*/
virtual nsresult GetCompiledEventHandler(nsIAtom *aName,
nsScriptObjectHolder<JSObject>& aHandler) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptEventHandlerOwner,
NS_ISCRIPTEVENTHANDLEROWNER_IID)
#endif // nsIScriptEventHandlerOwner_h__