зеркало из https://github.com/mozilla/pjs.git
- Doc-comments for nsIScriptContext methods I added or modified.
- Rename nsIScriptContext::CompileFunction to CompileEventHandler, and add BindCompiledEventHandler, to reflect function name restrictions and help brutal sharing. - Add adjunct-interface nsIScriptEventHandlerOwner to nsIScriptObjectOwner.h; this interface is queried for by nsEventListenerManger.cpp to test and fill the XUL prototype event handler "cache". - PR_LOG JS warnings, and look in javascript.options.{strict,werror} for those options. - Implement nsIScriptEventHandlerOwner in nsXULElement, keeping pointers to pre-compiled event handlers in nsXULPrototypeAttribute. (bug 13218, r=waterson@netscape.com,vidur@netscape.com)
This commit is contained in:
Родитель
f44c56f451
Коммит
f3855ca6b0
|
@ -552,7 +552,7 @@ nsEventListenerManager::AddScriptEventListener(nsIScriptContext* aContext,
|
|||
rv = aScriptObjectOwner->GetScriptObject(aContext, (void**)&scriptObject);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
rv = aContext->CompileFunction(scriptObject, aName, aBody);
|
||||
rv = aContext->CompileEventHandler(scriptObject, aName, aBody, nsnull);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
@ -587,26 +587,41 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
|
|||
if (NS_SUCCEEDED(result)) {
|
||||
JSObject* jsobj;
|
||||
result = owner->GetScriptObject(scriptCX, (void**)&jsobj);
|
||||
// This should never happen for anything but content
|
||||
// XXX I don't like that we have to reference content
|
||||
// from here. The alternative is to store the event handler
|
||||
// string on the JS object itself.
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(owner);
|
||||
NS_ASSERTION(content, "only content should have event handler attributes");
|
||||
if (content) {
|
||||
nsAutoString eventString;
|
||||
if (NS_SUCCEEDED(aDOMEvent->GetType(eventString))) {
|
||||
nsAutoString eventString;
|
||||
if (NS_SUCCEEDED(aDOMEvent->GetType(eventString))) {
|
||||
eventString.Insert("on", 0, 2);
|
||||
nsCOMPtr<nsIAtom> atom = getter_AddRefs(NS_NewAtom(eventString));
|
||||
|
||||
eventString.Insert("on", 0, 2);
|
||||
nsCOMPtr<nsIAtom> atom = getter_AddRefs(NS_NewAtom(eventString));
|
||||
nsAutoString handlerBody;
|
||||
result = content->GetAttribute(kNameSpaceID_None, atom, handlerBody);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = scriptCX->CompileFunction(jsobj, atom, handlerBody);
|
||||
nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner = do_QueryInterface(owner);
|
||||
void* handler = nsnull;
|
||||
|
||||
if (handlerOwner) {
|
||||
result = handlerOwner->GetCompiledEventHandler(atom, &handler);
|
||||
if (NS_SUCCEEDED(result) && handler) {
|
||||
result = scriptCX->BindCompiledEventHandler(jsobj, atom, handler);
|
||||
aListenerStruct->mHandlerIsString &= ~aSubType;
|
||||
}
|
||||
}
|
||||
|
||||
if (aListenerStruct->mHandlerIsString & aSubType) {
|
||||
// This should never happen for anything but content
|
||||
// XXX I don't like that we have to reference content
|
||||
// from here. The alternative is to store the event handler
|
||||
// string on the JS object itself.
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(owner);
|
||||
NS_ASSERTION(content, "only content should have event handler attributes");
|
||||
if (content) {
|
||||
nsAutoString handlerBody;
|
||||
result = content->GetAttribute(kNameSpaceID_None, atom, handlerBody);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = scriptCX->CompileEventHandler(jsobj, atom, handlerBody, &handler);
|
||||
aListenerStruct->mHandlerIsString &= ~aSubType;
|
||||
if (handlerOwner)
|
||||
handlerOwner->SetCompiledEventHandler(atom, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,14 +124,14 @@ static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID);
|
|||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIXMLContentIID, NS_IXMLCONTENT_IID);
|
||||
|
||||
static NS_DEFINE_CID(kEventListenerManagerCID, NS_EVENTLISTENERMANAGER_CID);
|
||||
static NS_DEFINE_CID(kEventListenerManagerCID, NS_EVENTLISTENERMANAGER_CID);
|
||||
static NS_DEFINE_IID(kIDOMEventTargetIID, NS_IDOMEVENTTARGET_IID);
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static NS_DEFINE_CID(kXULContentUtilsCID, NS_XULCONTENTUTILS_CID);
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static NS_DEFINE_CID(kXULContentUtilsCID, NS_XULCONTENTUTILS_CID);
|
||||
|
||||
static NS_DEFINE_IID(kIXULPopupListenerIID, NS_IXULPOPUPLISTENER_IID);
|
||||
static NS_DEFINE_CID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID);
|
||||
static NS_DEFINE_IID(kIXULPopupListenerIID, NS_IXULPOPUPLISTENER_IID);
|
||||
static NS_DEFINE_CID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID);
|
||||
|
||||
static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
|
||||
|
||||
|
@ -247,6 +247,13 @@ nsIAtom* nsXULElement::kTreeRowAtom;
|
|||
nsIAtom* nsXULElement::kEditorAtom;
|
||||
nsIAtom* nsXULElement::kWindowAtom;
|
||||
nsIAtom* nsXULElement::kNullAtom;
|
||||
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
PRUint32 nsXULPrototypeAttribute::gNumElements;
|
||||
PRUint32 nsXULPrototypeAttribute::gNumAttributes;
|
||||
PRUint32 nsXULPrototypeAttribute::gNumEventHandlers;
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsXULElement
|
||||
|
||||
|
@ -261,6 +268,9 @@ nsXULElement::nsXULElement()
|
|||
mSlots(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
nsXULPrototypeAttribute::gNumElements++;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -294,7 +304,7 @@ nsXULElement::Init()
|
|||
kTreeRowAtom = NS_NewAtom("treerow");
|
||||
kEditorAtom = NS_NewAtom("editor");
|
||||
kWindowAtom = NS_NewAtom("window");
|
||||
kNullAtom = NS_NewAtom("");
|
||||
kNullAtom = NS_NewAtom("");
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kNameSpaceManagerCID,
|
||||
nsnull,
|
||||
|
@ -365,7 +375,7 @@ nsXULElement::~nsXULElement()
|
|||
NS_IF_RELEASE(kTreeRowAtom);
|
||||
NS_IF_RELEASE(kEditorAtom);
|
||||
NS_IF_RELEASE(kWindowAtom);
|
||||
NS_IF_RELEASE(kNullAtom);
|
||||
NS_IF_RELEASE(kNullAtom);
|
||||
|
||||
NS_IF_RELEASE(gNameSpaceManager);
|
||||
|
||||
|
@ -426,6 +436,9 @@ nsXULElement::Create(nsXULPrototypeElement* aPrototype,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (found) {
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
nsXULPrototypeAttribute::gNumEventHandlers++;
|
||||
#endif
|
||||
rv = element->AddScriptEventListener(attr->mName, attr->mValue, iid);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
@ -510,6 +523,9 @@ nsXULElement::QueryInterface(REFNSIID iid, void** result)
|
|||
else if (iid.Equals(kIScriptObjectOwnerIID)) {
|
||||
*result = NS_STATIC_CAST(nsIScriptObjectOwner*, this);
|
||||
}
|
||||
else if (iid.Equals(NS_GET_IID(nsIScriptEventHandlerOwner))) {
|
||||
*result = NS_STATIC_CAST(nsIScriptEventHandlerOwner*, this);
|
||||
}
|
||||
else if (iid.Equals(kIDOMEventReceiverIID)) {
|
||||
*result = NS_STATIC_CAST(nsIDOMEventReceiver*, this);
|
||||
}
|
||||
|
@ -1483,6 +1499,45 @@ nsXULElement::SetScriptObject(void *aScriptObject)
|
|||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsIScriptEventHandlerOwner interface
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULElement::GetCompiledEventHandler(nsIAtom *aName, void** aHandler)
|
||||
{
|
||||
*aHandler = nsnull;
|
||||
if (mPrototype) {
|
||||
for (PRInt32 i = 0; i < mPrototype->mNumAttributes; ++i) {
|
||||
nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]);
|
||||
|
||||
if ((attr->mNameSpaceID == kNameSpaceID_None) &&
|
||||
(attr->mName == aName)) {
|
||||
*aHandler = attr->mEventHandler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULElement::SetCompiledEventHandler(nsIAtom *aName, void* aHandler)
|
||||
{
|
||||
if (mPrototype) {
|
||||
for (PRInt32 i = 0; i < mPrototype->mNumAttributes; ++i) {
|
||||
nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]);
|
||||
|
||||
if ((attr->mNameSpaceID == kNameSpaceID_None) &&
|
||||
(attr->mName == aName)) {
|
||||
attr->mEventHandler = aHandler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsIJSScriptObject interface
|
||||
|
||||
|
@ -2136,8 +2191,8 @@ nsXULElement::SetAttribute(PRInt32 aNameSpaceID,
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsXULElement::GetAttribute(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aName,
|
||||
nsString& aResult) const
|
||||
nsIAtom* aName,
|
||||
nsString& aResult) const
|
||||
{
|
||||
NS_ASSERTION(nsnull != aName, "must have attribute name");
|
||||
if (nsnull == aName) {
|
||||
|
@ -2199,18 +2254,21 @@ nsXULElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotif
|
|||
if (! Attributes())
|
||||
return NS_OK;
|
||||
|
||||
// Check to see if the CLASS attribute is being unset. If so, we need to delete our
|
||||
// class list.
|
||||
if (mDocument && (aNameSpaceID == kNameSpaceID_None) && (aName == kClassAtom)) {
|
||||
// Check to see if the CLASS attribute is being unset. If so, we need to
|
||||
// delete our class list.
|
||||
// XXXbe fuse common (mDocument && aNameSpaceId == kNameSpaceID_None)
|
||||
if (mDocument &&
|
||||
(aNameSpaceID == kNameSpaceID_None) &&
|
||||
(aName == kClassAtom)) {
|
||||
Attributes()->UpdateClassList("");
|
||||
}
|
||||
|
||||
if (mDocument && (aNameSpaceID == kNameSpaceID_None) && aName == kStyleAtom) {
|
||||
if (mDocument &&
|
||||
(aNameSpaceID == kNameSpaceID_None) &&
|
||||
aName == kStyleAtom) {
|
||||
|
||||
nsCOMPtr <nsIURI> docURL;
|
||||
if (nsnull != mDocument) {
|
||||
mDocument->GetBaseURL(*getter_AddRefs(docURL));
|
||||
}
|
||||
mDocument->GetBaseURL(*getter_AddRefs(docURL));
|
||||
|
||||
Attributes()->UpdateStyleRule(docURL, "");
|
||||
// XXX Some kind of special document update might need to happen here.
|
||||
|
@ -2222,34 +2280,34 @@ nsXULElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotif
|
|||
nsCOMPtr<nsIAtom> tag;
|
||||
GetTag(*getter_AddRefs(tag));
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
// See if we're a treeitem atom.
|
||||
// XXX Forgive me father, for I know exactly what I do, and I'm
|
||||
// doing it anyway. Need to make an nsIRDFNodeList interface that
|
||||
// I can QI to for additions and removals of nodes. For now
|
||||
// do an evil cast.
|
||||
nsCOMPtr<nsIRDFNodeList> nodeList;
|
||||
if (tag && (tag.get() == kTreeItemAtom) && (aName == kSelectedAtom)) {
|
||||
nsCOMPtr<nsIDOMXULTreeElement> treeElement;
|
||||
GetParentTree(getter_AddRefs(treeElement));
|
||||
if (treeElement) {
|
||||
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||
treeElement->GetSelectedItems(getter_AddRefs(nodes));
|
||||
nodeList = do_QueryInterface(nodes);
|
||||
// See if we're a treeitem atom.
|
||||
// XXX Forgive me father, for I know exactly what I do, and I'm
|
||||
// doing it anyway. Need to make an nsIRDFNodeList interface that
|
||||
// I can QI to for additions and removals of nodes. For now
|
||||
// do an evil cast.
|
||||
nsCOMPtr<nsIRDFNodeList> nodeList;
|
||||
if (tag && (tag.get() == kTreeItemAtom) && (aName == kSelectedAtom)) {
|
||||
nsCOMPtr<nsIDOMXULTreeElement> treeElement;
|
||||
GetParentTree(getter_AddRefs(treeElement));
|
||||
if (treeElement) {
|
||||
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||
treeElement->GetSelectedItems(getter_AddRefs(nodes));
|
||||
nodeList = do_QueryInterface(nodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tag && (tag.get() == kTreeCellAtom) && (aName == kSelectedAtom)) {
|
||||
nsCOMPtr<nsIDOMXULTreeElement> treeElement;
|
||||
GetParentTree(getter_AddRefs(treeElement));
|
||||
if (treeElement) {
|
||||
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||
treeElement->GetSelectedCells(getter_AddRefs(nodes));
|
||||
nodeList = do_QueryInterface(nodes);
|
||||
else if (tag && (tag.get() == kTreeCellAtom) && (aName == kSelectedAtom)) {
|
||||
nsCOMPtr<nsIDOMXULTreeElement> treeElement;
|
||||
GetParentTree(getter_AddRefs(treeElement));
|
||||
if (treeElement) {
|
||||
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||
treeElement->GetSelectedCells(getter_AddRefs(nodes));
|
||||
nodeList = do_QueryInterface(nodes);
|
||||
}
|
||||
}
|
||||
if (nodeList) {
|
||||
// Remove this node from the list.
|
||||
nodeList->RemoveNode(this);
|
||||
}
|
||||
}
|
||||
if (nodeList) {
|
||||
// Remove this node from the list.
|
||||
nodeList->RemoveNode(this);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Know how to remove POPUP event listeners when an attribute is unset?
|
||||
|
@ -2263,7 +2321,8 @@ nsXULElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotif
|
|||
PRInt32 i;
|
||||
for (i = 0; i < count; i++) {
|
||||
nsXULAttribute* attr = NS_REINTERPRET_CAST(nsXULAttribute*, Attributes()->ElementAt(i));
|
||||
if ((attr->GetNameSpaceID() == aNameSpaceID) && (attr->GetName() == aName)) {
|
||||
if ((attr->GetNameSpaceID() == aNameSpaceID) &&
|
||||
(attr->GetName() == aName)) {
|
||||
attr->GetValue(oldValue);
|
||||
Attributes()->RemoveElementAt(i);
|
||||
NS_RELEASE(attr);
|
||||
|
@ -2275,50 +2334,50 @@ nsXULElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotif
|
|||
|
||||
// XUL Only. Find out if we have a broadcast listener for this element.
|
||||
if (successful) {
|
||||
// Check to see if the OBSERVES attribute is being unset. If so, we need to remove
|
||||
// ourselves completely.
|
||||
if (mDocument && (aNameSpaceID == kNameSpaceID_None) &&
|
||||
(aName == kObservesAtom))
|
||||
{
|
||||
// Do a getElementById to retrieve the broadcaster.
|
||||
nsCOMPtr<nsIDOMElement> broadcaster;
|
||||
nsCOMPtr<nsIDOMXULDocument> domDoc = do_QueryInterface(mDocument);
|
||||
domDoc->GetElementById(oldValue, getter_AddRefs(broadcaster));
|
||||
if (broadcaster) {
|
||||
nsCOMPtr<nsIDOMXULElement> xulBroadcaster = do_QueryInterface(broadcaster);
|
||||
if (xulBroadcaster) {
|
||||
xulBroadcaster->RemoveBroadcastListener("*", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BroadcastListeners()) {
|
||||
PRInt32 count = BroadcastListeners()->Count();
|
||||
for (PRInt32 i = 0; i < count; i++)
|
||||
// Check to see if the OBSERVES attribute is being unset. If so, we
|
||||
// need to remove ourselves completely.
|
||||
if (mDocument &&
|
||||
(aNameSpaceID == kNameSpaceID_None) &&
|
||||
(aName == kObservesAtom))
|
||||
{
|
||||
XULBroadcastListener* xulListener =
|
||||
NS_REINTERPRET_CAST(XULBroadcastListener*, BroadcastListeners()->ElementAt(i));
|
||||
|
||||
nsAutoString str;
|
||||
aName->ToString(str);
|
||||
if (xulListener->ObservingAttribute(str) &&
|
||||
(aName != kIdAtom)) {
|
||||
// XXX Should have a function that knows which attributes are special.
|
||||
// Unset the attribute in the broadcast listener.
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
element = do_QueryInterface(xulListener->mListener);
|
||||
if (element)
|
||||
element->RemoveAttribute(str);
|
||||
// Do a getElementById to retrieve the broadcaster.
|
||||
nsCOMPtr<nsIDOMElement> broadcaster;
|
||||
nsCOMPtr<nsIDOMXULDocument> domDoc = do_QueryInterface(mDocument);
|
||||
domDoc->GetElementById(oldValue, getter_AddRefs(broadcaster));
|
||||
if (broadcaster) {
|
||||
nsCOMPtr<nsIDOMXULElement> xulBroadcaster = do_QueryInterface(broadcaster);
|
||||
if (xulBroadcaster) {
|
||||
xulBroadcaster->RemoveBroadcastListener("*", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify document
|
||||
if (NS_SUCCEEDED(rv) && aNotify && (nsnull != mDocument)) {
|
||||
mDocument->AttributeChanged(NS_STATIC_CAST(nsIStyledContent*, this),
|
||||
aNameSpaceID, aName,
|
||||
NS_STYLE_HINT_UNKNOWN);
|
||||
}
|
||||
|
||||
if (BroadcastListeners()) {
|
||||
PRInt32 count = BroadcastListeners()->Count();
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
XULBroadcastListener* xulListener =
|
||||
NS_REINTERPRET_CAST(XULBroadcastListener*, BroadcastListeners()->ElementAt(i));
|
||||
|
||||
nsAutoString str;
|
||||
aName->ToString(str);
|
||||
if (xulListener->ObservingAttribute(str) &&
|
||||
(aName != kIdAtom)) {
|
||||
// XXX Should have a function that knows which attributes are special.
|
||||
// Unset the attribute in the broadcast listener.
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
element = do_QueryInterface(xulListener->mListener);
|
||||
if (element)
|
||||
element->RemoveAttribute(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify document
|
||||
if (NS_SUCCEEDED(rv) && aNotify && (nsnull != mDocument)) {
|
||||
mDocument->AttributeChanged(NS_STATIC_CAST(nsIStyledContent*, this),
|
||||
aNameSpaceID, aName,
|
||||
NS_STYLE_HINT_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
// End XUL Only Code
|
||||
|
@ -3094,11 +3153,11 @@ nsXULElement::GetID(nsIAtom*& aResult) const
|
|||
GetAttribute(kNameSpaceID_None, kIdAtom, value);
|
||||
|
||||
if (value.Length() > 0)
|
||||
aResult = NS_NewAtom(value); // The NewAtom call does the AddRef.
|
||||
aResult = NS_NewAtom(value); // The NewAtom call does the AddRef.
|
||||
else
|
||||
{
|
||||
aResult = kNullAtom;
|
||||
NS_ADDREF(kNullAtom);
|
||||
aResult = kNullAtom;
|
||||
NS_ADDREF(kNullAtom);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -78,11 +78,63 @@ class nsXULAttributes;
|
|||
class nsXULPrototypeAttribute
|
||||
{
|
||||
public:
|
||||
nsXULPrototypeAttribute() : mNameSpaceID(kNameSpaceID_Unknown) {}
|
||||
nsXULPrototypeAttribute()
|
||||
: mNameSpaceID(kNameSpaceID_Unknown),
|
||||
mEventHandler(nsnull)
|
||||
{
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
gNumAttributes++;
|
||||
#endif
|
||||
}
|
||||
|
||||
PRInt32 mNameSpaceID;
|
||||
nsCOMPtr<nsIAtom> mName;
|
||||
nsString mValue;
|
||||
void* mEventHandler;
|
||||
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
/**
|
||||
If enough attributes, on average, are event handlers, it pays to keep
|
||||
mEventHandler here, instead of maintaining a separate mapping in each
|
||||
nsXULElement associating certain mName values to their mEventHandlers.
|
||||
Assume we don't need to keep mNameSpaceID along with mName in such an
|
||||
event-handler-only name-to-function-pointer mapping.
|
||||
|
||||
Let
|
||||
minAttrSize = sizeof(mNameSpaceID) + sizeof(mName) + sizeof(mValue)
|
||||
mappingSize = sizeof(mName) + sizeof(mEventHandler)
|
||||
elemOverhead = nElems * sizeof(void*)
|
||||
|
||||
Then
|
||||
nAttrs * minAttrSize + nEventHandlers * mappingSize + elemOverhead
|
||||
> nAttrs * (minAttrSize + mappingSize - sizeof(mName))
|
||||
which simplifies to
|
||||
nEventHandlers * mappingSize + elemOverhead
|
||||
> nAttrs * (mappingSize - sizeof(mName))
|
||||
or
|
||||
nEventHandlers + (nElems * sizeof(void*)) / mappingSize
|
||||
> nAttrs * (1 - sizeof(mName) / mappingSize)
|
||||
|
||||
If nsCOMPtr and all other pointers are the same size, this reduces to
|
||||
nEventHandlers + nElems / 2 > nAttrs / 2
|
||||
|
||||
To measure how many attributes are event handlers, compile XUL source
|
||||
with XUL_PROTOTYPE_ATTRIBUTE_METERING and watch the counters below.
|
||||
Plug into the above relation -- if true, it pays to put mEventHandler
|
||||
in nsXULPrototypeAttribute rather than to keep a separate mapping.
|
||||
|
||||
Recent numbers after opening four browser windows:
|
||||
nElems 3537, nAttrs 2528, nEventHandlers 1042
|
||||
giving 1042 + 3537/2 > 2528/2 or 2810 > 1264.
|
||||
|
||||
As it happens, mEventHandler also makes this struct power-of-2 sized,
|
||||
8 words on most architectures, which makes for strength-reduced array
|
||||
index-to-pointer calculations.
|
||||
*/
|
||||
static PRUint32 gNumElements;
|
||||
static PRUint32 gNumAttributes;
|
||||
static PRUint32 gNumEventHandlers;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -249,6 +301,7 @@ class nsXULElement : public nsIStyledContent,
|
|||
public nsIDOMXULElement,
|
||||
public nsIDOMEventReceiver,
|
||||
public nsIScriptObjectOwner,
|
||||
public nsIScriptEventHandlerOwner,
|
||||
public nsIJSScriptObject,
|
||||
public nsIStyleRule,
|
||||
public nsIChromeEventHandler
|
||||
|
@ -389,6 +442,10 @@ public:
|
|||
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext, void** aScriptObject);
|
||||
NS_IMETHOD SetScriptObject(void *aScriptObject);
|
||||
|
||||
// nsIScriptEventHandlerOwner
|
||||
NS_IMETHOD GetCompiledEventHandler(nsIAtom *aName, void** aHandler);
|
||||
NS_IMETHOD SetCompiledEventHandler(nsIAtom *aName, void* aHandler);
|
||||
|
||||
// nsIJSScriptObject
|
||||
virtual PRBool AddProperty(JSContext *aContext, jsval aID, jsval *aVp);
|
||||
virtual PRBool DeleteProperty(JSContext *aContext, jsval aID, jsval *aVp);
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* Copyright (C) 1998-1999 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifndef nsIScriptContext_h__
|
||||
|
@ -70,7 +70,7 @@ public:
|
|||
* @param aLineNo the starting line number for the script for error messages
|
||||
* @param aVersion the script language version to use when executing
|
||||
* @param aRetValue the result of executing the script
|
||||
* @param aIsUndefined true if the result of executing the script is the
|
||||
* @param aIsUndefined true if the result of executing the script is the
|
||||
* undefined value
|
||||
*
|
||||
* @return NS_OK if the script was valid and got executed
|
||||
|
@ -120,24 +120,66 @@ public:
|
|||
* or nsnull to use a default scope
|
||||
* @param aRetValue the result of executing the script, may be null in
|
||||
* which case no result string is computed
|
||||
* @param aIsUndefined true if the result of executing the script is the
|
||||
* @param aIsUndefined true if the result of executing the script is the
|
||||
* undefined value, may be null for "don't care"
|
||||
*
|
||||
* @return NS_OK if the script was valid and got executed
|
||||
*
|
||||
*/
|
||||
*/
|
||||
NS_IMETHOD ExecuteScript(void* aScriptObject,
|
||||
void *aScopeObject,
|
||||
nsString* aRetValue,
|
||||
PRBool* aIsUndefined) = 0;
|
||||
|
||||
NS_IMETHOD CompileFunction(void *aObj, nsIAtom *aName,
|
||||
const nsString& aBody) = 0;
|
||||
/**
|
||||
* Compile the event handler named by atom aName, with function body aBody
|
||||
* into a function returned on success via *aFunction. Bind the lowercase
|
||||
* ASCII name to the function in scope aObj, or in the context's global if
|
||||
* aObj is null.
|
||||
*
|
||||
* @param aObj an object telling the scope in which to bind the compiled
|
||||
* event handler function, or nsnull to use a default scope
|
||||
* @param aName an nsIAtom pointer naming the function; it must be lowercase
|
||||
* and ASCII, and should not be longer than 63 chars. This bound on
|
||||
* length is enforced only by assertions, so caveat caller!
|
||||
* @param aBody the event handler function's body
|
||||
* @param aFunction the out parameter in which a void pointer to the compiled
|
||||
* function is returned on success; may be null, meaning "don't care"
|
||||
*
|
||||
* @return NS_OK if the function body was valid and got compiled
|
||||
*/
|
||||
NS_IMETHOD CompileEventHandler(void *aObj,
|
||||
nsIAtom *aName,
|
||||
const nsString& aBody,
|
||||
void** aFunction) = 0;
|
||||
|
||||
NS_IMETHOD CallFunction(void *aObj, void *aFunction,
|
||||
PRUint32 argc, void *argv,
|
||||
NS_IMETHOD CallFunction(void *aObj, void *aFunction,
|
||||
PRUint32 argc, void *argv,
|
||||
PRBool *aBoolResult) = 0;
|
||||
|
||||
/**
|
||||
* Bind an already-compiled event handler function to a name in the given
|
||||
* scope object. The same restrictions on aName (lowercase ASCII, not too
|
||||
* long) applies here as for CompileEventHandler.
|
||||
*
|
||||
* @param aObj an object telling the scope in which to bind the compiled
|
||||
* event handler function
|
||||
* @param aName an nsIAtom pointer naming the function; it must be lowercase
|
||||
* and ASCII, and should not be longer than 63 chars. This bound on
|
||||
* length is enforced only by assertions, so caveat caller!
|
||||
* @param aFunction the function to name, created by an earlier call to
|
||||
* CompileEventHandler
|
||||
* @return NS_OK if the function was successfully bound to the name
|
||||
*/
|
||||
NS_IMETHOD BindCompiledEventHandler(void *aObj,
|
||||
nsIAtom *aName,
|
||||
void *aFunction) = 0;
|
||||
|
||||
/**
|
||||
* Set the default scripting language version for this context, which must
|
||||
* be a context specific to a particular scripting language.
|
||||
*
|
||||
**/
|
||||
NS_IMETHOD SetDefaultLanguageVersion(const char* aVersion) = 0;
|
||||
|
||||
/**
|
||||
|
@ -172,7 +214,7 @@ public:
|
|||
* Check to see if context is as yet intialized. Used to prevent
|
||||
* reentrancy issues during the initialization process.
|
||||
*
|
||||
* @return NS_OK if initialized, NS_COMFALSE if not
|
||||
* @return NS_OK if initialized, NS_COMFALSE if not
|
||||
*
|
||||
*/
|
||||
NS_IMETHOD IsContextInitialized() = 0;
|
||||
|
@ -181,7 +223,7 @@ public:
|
|||
* Add a reference to a script object. For garbage collected systems
|
||||
* the address of a slot to be used as a root is also provided. For
|
||||
* reference counted systems, the object is provided.
|
||||
*
|
||||
*
|
||||
* @param aSlot Slot to use as a root for garbage collected systems
|
||||
* @param aScriptObject Script object being referenced
|
||||
* @param aName Name of the reference (could be null)
|
||||
|
@ -192,7 +234,7 @@ public:
|
|||
const char *aName) = 0;
|
||||
|
||||
/**
|
||||
* Remove a reference to a script object. For garbage collected
|
||||
* Remove a reference to a script object. For garbage collected
|
||||
* systems, this is equivalent to removing a root.
|
||||
*
|
||||
* @param aSlot Slot corresponding to the removed root
|
||||
|
@ -209,7 +251,7 @@ public:
|
|||
* @return NS_OK if the method is successful
|
||||
*/
|
||||
NS_IMETHOD GC() = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Get the name space manager for this context.
|
||||
* @return NS_OK if the method is successful
|
||||
|
|
|
@ -72,4 +72,27 @@ public:
|
|||
NS_IMETHOD SetScriptObject(void* aScriptObject) = 0;
|
||||
};
|
||||
|
||||
class nsIAtom;
|
||||
|
||||
#define NS_ISCRIPTEVENTHANDLEROWNER_IID \
|
||||
{ /* 2ad54ae0-a839-11d3-ba97-00104ba02d3d */ \
|
||||
0x2ad54ae0, 0xa839, 0x11d3, \
|
||||
{0xba, 0x97, 0x00, 0x10, 0x4b, 0xa0, 0x2d, 0x3d} }
|
||||
|
||||
/**
|
||||
* Associate a compiled event handler with its target object, which owns it
|
||||
* This is an adjunct to nsIScriptObjectOwner that nsIEventListenerManager's
|
||||
* implementation queries for, in order to avoid recompiling a recurrent or
|
||||
* prototype-inherited event handler.
|
||||
*/
|
||||
class nsIScriptEventHandlerOwner : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISCRIPTEVENTHANDLEROWNER_IID)
|
||||
|
||||
NS_IMETHOD GetCompiledEventHandler(nsIAtom *aName, void** aHandler) = 0;
|
||||
|
||||
NS_IMETHOD SetCompiledEventHandler(nsIAtom *aName, void* aHandler) = 0;
|
||||
};
|
||||
|
||||
#endif // nsIScriptObjectOwner_h__
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
* Contributor(s):
|
||||
*/
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
#include <ctype.h>
|
||||
#endif
|
||||
#include "nsJSEnvironment.h"
|
||||
#include "nsIScriptObjectOwner.h"
|
||||
#include "nsIScriptContextOwner.h"
|
||||
|
@ -46,14 +48,24 @@
|
|||
#include "nsIXPCSecurityManager.h"
|
||||
#include "nsIJSContextStack.h"
|
||||
#include "nsIJSRuntimeService.h"
|
||||
#include "nsIPref.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
// Force PR_LOGGING so we can get JS strict warnings even in release builds
|
||||
#define FORCE_PR_LOG 1
|
||||
#include "prlog.h"
|
||||
|
||||
#include "nsIJVMManager.h"
|
||||
#include "nsILiveConnectManager.h"
|
||||
|
||||
const size_t gStackSize = 8192;
|
||||
|
||||
static NS_DEFINE_IID(kCScriptNameSetRegistryCID, NS_SCRIPT_NAMESET_REGISTRY_CID);
|
||||
static NS_DEFINE_IID(kPrefServiceCID, NS_PREF_CID);
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
static PRLogModuleInfo* gJSDiagnostics = nsnull;
|
||||
#endif
|
||||
|
||||
void PR_CALLBACK
|
||||
NS_ScriptErrorReporter(JSContext *cx,
|
||||
|
@ -86,6 +98,25 @@ NS_ScriptErrorReporter(JSContext *cx,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef PR_LOGGING
|
||||
if (report) {
|
||||
if (!gJSDiagnostics)
|
||||
gJSDiagnostics = PR_NewLogModule("JSDiagnostics");
|
||||
|
||||
if (gJSDiagnostics) {
|
||||
PR_LOG(gJSDiagnostics,
|
||||
JSREPORT_IS_WARNING(report->flags) ? PR_LOG_WARNING : PR_LOG_ERROR,
|
||||
("file %s, line %u: %s\n%s%s",
|
||||
report->filename, report->lineno, message,
|
||||
report->linebuf ? report->linebuf : "",
|
||||
(report->linebuf &&
|
||||
report->linebuf[strlen(report->linebuf)-1] != '\n')
|
||||
? "\n"
|
||||
: ""));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
|
||||
|
@ -93,8 +124,33 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime)
|
|||
{
|
||||
mRefCnt = 0;
|
||||
mContext = JS_NewContext(aRuntime, gStackSize);
|
||||
if (mContext)
|
||||
if (mContext) {
|
||||
JS_SetContextPrivate(mContext, (void *)this);
|
||||
|
||||
// Check for the JS strict option, which enables extra error checks
|
||||
nsresult rv;
|
||||
PRBool strict, werror;
|
||||
NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
uint32 options = 0;
|
||||
#ifdef JSOPTION_STRICT
|
||||
if (NS_SUCCEEDED(prefs->GetBoolPref("javascript.options.strict",
|
||||
&strict)) &&
|
||||
strict) {
|
||||
options |= JSOPTION_STRICT;
|
||||
}
|
||||
#endif
|
||||
#ifdef JSOPTION_WERROR
|
||||
if (NS_SUCCEEDED(prefs->GetBoolPref("javascript.options.werror",
|
||||
&werror)) &&
|
||||
werror) {
|
||||
options |= JSOPTION_WERROR;
|
||||
}
|
||||
#endif
|
||||
if (options)
|
||||
JS_SetOptions(mContext, options);
|
||||
}
|
||||
}
|
||||
mIsInitialized = PR_FALSE;
|
||||
mNumEvaluations = 0;
|
||||
mSecurityManager = nsnull;
|
||||
|
@ -354,10 +410,10 @@ nsJSContext::ExecuteScript(void* aScriptObject,
|
|||
mRef = nsnull;
|
||||
mTerminationFunc = nsnull;
|
||||
ok = ::JS_ExecuteScript(mContext,
|
||||
(JSObject*) aScopeObject,
|
||||
(JSScript*) JS_GetPrivate(mContext,
|
||||
(JSObject*)aScriptObject),
|
||||
&val);
|
||||
(JSObject*) aScopeObject,
|
||||
(JSScript*) JS_GetPrivate(mContext,
|
||||
(JSObject*)aScriptObject),
|
||||
&val);
|
||||
|
||||
if (ok) {
|
||||
// If all went well, convert val to a string (XXXbe unless undefined?).
|
||||
|
@ -388,8 +444,32 @@ nsJSContext::ExecuteScript(void* aScriptObject,
|
|||
|
||||
const char *gEventArgv[] = {"event"};
|
||||
|
||||
void
|
||||
AtomToEventHandlerName(nsIAtom *aName, char *charName, PRUint32 charNameSize)
|
||||
{
|
||||
// optimized to avoid ns*Str*.h explicit/implicit copying and malloc'ing
|
||||
// even nsCAutoString may call an Append that copy-constructs an nsStr from
|
||||
// a const PRUnichar*
|
||||
const PRUnichar *name;
|
||||
aName->GetUnicode(&name);
|
||||
char c;
|
||||
PRUint32 i = 0;
|
||||
|
||||
do {
|
||||
NS_ASSERTION(name[i] < 128, "non-ASCII event handler name");
|
||||
c = char(name[i]);
|
||||
|
||||
// The HTML content sink must have folded to lowercase already.
|
||||
NS_ASSERTION(c == '\0' || islower(c), "non-alphabetic event handler name");
|
||||
|
||||
NS_ASSERTION(i < charNameSize, "overlong event handler name");
|
||||
charName[i++] = c;
|
||||
} while (c != '\0');
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSContext::CompileFunction(void *aObj, nsIAtom *aName, const nsString& aBody)
|
||||
nsJSContext::CompileEventHandler(void *aObj, nsIAtom *aName, const nsString& aBody,
|
||||
void** aFunction)
|
||||
{
|
||||
JSPrincipals *jsprin = nsnull;
|
||||
|
||||
|
@ -405,35 +485,24 @@ nsJSContext::CompileFunction(void *aObj, nsIAtom *aName, const nsString& aBody)
|
|||
}
|
||||
}
|
||||
|
||||
// optimized to avoid ns*Str*.h explicit/implicit copying and malloc'ing
|
||||
// even nsCAutoString may call an Append that copy-constructs an nsStr from
|
||||
// a const PRUnichar*
|
||||
const PRUnichar *name;
|
||||
aName->GetUnicode(&name);
|
||||
char c, charName[64];
|
||||
int i = 0;
|
||||
char charName[64];
|
||||
AtomToEventHandlerName(aName, charName, sizeof charName);
|
||||
|
||||
do {
|
||||
NS_ASSERTION(name[i] < 128, "non-ASCII DOM function name");
|
||||
c = char(name[i]);
|
||||
NS_ASSERTION(c == '\0' || isalpha(c), "non-alphabetic DOM function name");
|
||||
|
||||
NS_ASSERTION(i < sizeof charName, "overlong DOM function name");
|
||||
charName[i++] = tolower(c);
|
||||
} while (c != '\0');
|
||||
|
||||
JSBool ok = JS_CompileUCFunctionForPrincipals(mContext,
|
||||
(JSObject*)aObj, jsprin,
|
||||
charName, 1, gEventArgv,
|
||||
(jschar*)aBody.GetUnicode(),
|
||||
aBody.Length(),
|
||||
//XXXbe filename, lineno:
|
||||
nsnull, 0)
|
||||
!= 0;
|
||||
JSFunction* fun = JS_CompileUCFunctionForPrincipals(mContext,
|
||||
(JSObject*)aObj, jsprin,
|
||||
charName, 1, gEventArgv,
|
||||
(jschar*)aBody.GetUnicode(),
|
||||
aBody.Length(),
|
||||
//XXXbe filename, lineno:
|
||||
nsnull, 0);
|
||||
|
||||
if (jsprin)
|
||||
JSPRINCIPALS_DROP(mContext, jsprin);
|
||||
return ok ? NS_OK : NS_ERROR_FAILURE;
|
||||
if (!fun)
|
||||
return NS_ERROR_FAILURE;
|
||||
if (aFunction)
|
||||
*aFunction = (void*) fun;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -477,6 +546,24 @@ nsJSContext::CallFunction(void *aObj, void *aFunction, PRUint32 argc,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSContext::BindCompiledEventHandler(void *aObj, nsIAtom *aName, void *aFunction)
|
||||
{
|
||||
char charName[64];
|
||||
AtomToEventHandlerName(aName, charName, sizeof charName);
|
||||
|
||||
JSObject *funobj = JS_GetFunctionObject((JSFunction *)aFunction);
|
||||
if (!funobj)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (!::JS_DefineProperty(mContext, (JSObject *)aObj, charName,
|
||||
OBJECT_TO_JSVAL(funobj), nsnull, nsnull,
|
||||
JSPROP_ENUMERATE | JSPROP_PERMANENT)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSContext::SetDefaultLanguageVersion(const char* aVersion)
|
||||
{
|
||||
|
|
|
@ -79,11 +79,16 @@ public:
|
|||
void *aScopeObject,
|
||||
nsString* aRetValue,
|
||||
PRBool* aIsUndefined);
|
||||
NS_IMETHOD CompileFunction(void *aObj, nsIAtom *aName,
|
||||
const nsString& aBody);
|
||||
NS_IMETHOD CompileEventHandler(void *aObj,
|
||||
nsIAtom *aName,
|
||||
const nsString& aBody,
|
||||
void** aFunction);
|
||||
NS_IMETHOD CallFunction(void *aObj, void *aFunction,
|
||||
PRUint32 argc, void *argv,
|
||||
PRBool *aBoolResult);
|
||||
NS_IMETHOD BindCompiledEventHandler(void *aObj,
|
||||
nsIAtom *aName,
|
||||
void *aFunction);
|
||||
NS_IMETHOD SetDefaultLanguageVersion(const char* aVersion);
|
||||
NS_IMETHOD_(nsIScriptGlobalObject*) GetGlobalObject();
|
||||
NS_IMETHOD_(void*) GetNativeContext();
|
||||
|
|
|
@ -552,7 +552,7 @@ nsEventListenerManager::AddScriptEventListener(nsIScriptContext* aContext,
|
|||
rv = aScriptObjectOwner->GetScriptObject(aContext, (void**)&scriptObject);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
rv = aContext->CompileFunction(scriptObject, aName, aBody);
|
||||
rv = aContext->CompileEventHandler(scriptObject, aName, aBody, nsnull);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
|
@ -587,26 +587,41 @@ nsEventListenerManager::HandleEventSubType(nsListenerStruct* aListenerStruct,
|
|||
if (NS_SUCCEEDED(result)) {
|
||||
JSObject* jsobj;
|
||||
result = owner->GetScriptObject(scriptCX, (void**)&jsobj);
|
||||
// This should never happen for anything but content
|
||||
// XXX I don't like that we have to reference content
|
||||
// from here. The alternative is to store the event handler
|
||||
// string on the JS object itself.
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(owner);
|
||||
NS_ASSERTION(content, "only content should have event handler attributes");
|
||||
if (content) {
|
||||
nsAutoString eventString;
|
||||
if (NS_SUCCEEDED(aDOMEvent->GetType(eventString))) {
|
||||
nsAutoString eventString;
|
||||
if (NS_SUCCEEDED(aDOMEvent->GetType(eventString))) {
|
||||
eventString.Insert("on", 0, 2);
|
||||
nsCOMPtr<nsIAtom> atom = getter_AddRefs(NS_NewAtom(eventString));
|
||||
|
||||
eventString.Insert("on", 0, 2);
|
||||
nsCOMPtr<nsIAtom> atom = getter_AddRefs(NS_NewAtom(eventString));
|
||||
nsAutoString handlerBody;
|
||||
result = content->GetAttribute(kNameSpaceID_None, atom, handlerBody);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = scriptCX->CompileFunction(jsobj, atom, handlerBody);
|
||||
nsCOMPtr<nsIScriptEventHandlerOwner> handlerOwner = do_QueryInterface(owner);
|
||||
void* handler = nsnull;
|
||||
|
||||
if (handlerOwner) {
|
||||
result = handlerOwner->GetCompiledEventHandler(atom, &handler);
|
||||
if (NS_SUCCEEDED(result) && handler) {
|
||||
result = scriptCX->BindCompiledEventHandler(jsobj, atom, handler);
|
||||
aListenerStruct->mHandlerIsString &= ~aSubType;
|
||||
}
|
||||
}
|
||||
|
||||
if (aListenerStruct->mHandlerIsString & aSubType) {
|
||||
// This should never happen for anything but content
|
||||
// XXX I don't like that we have to reference content
|
||||
// from here. The alternative is to store the event handler
|
||||
// string on the JS object itself.
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(owner);
|
||||
NS_ASSERTION(content, "only content should have event handler attributes");
|
||||
if (content) {
|
||||
nsAutoString handlerBody;
|
||||
result = content->GetAttribute(kNameSpaceID_None, atom, handlerBody);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = scriptCX->CompileEventHandler(jsobj, atom, handlerBody, &handler);
|
||||
aListenerStruct->mHandlerIsString &= ~aSubType;
|
||||
if (handlerOwner)
|
||||
handlerOwner->SetCompiledEventHandler(atom, handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,14 +124,14 @@ static NS_DEFINE_IID(kIScriptObjectOwnerIID, NS_ISCRIPTOBJECTOWNER_IID);
|
|||
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
||||
static NS_DEFINE_IID(kIXMLContentIID, NS_IXMLCONTENT_IID);
|
||||
|
||||
static NS_DEFINE_CID(kEventListenerManagerCID, NS_EVENTLISTENERMANAGER_CID);
|
||||
static NS_DEFINE_CID(kEventListenerManagerCID, NS_EVENTLISTENERMANAGER_CID);
|
||||
static NS_DEFINE_IID(kIDOMEventTargetIID, NS_IDOMEVENTTARGET_IID);
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static NS_DEFINE_CID(kXULContentUtilsCID, NS_XULCONTENTUTILS_CID);
|
||||
static NS_DEFINE_CID(kNameSpaceManagerCID, NS_NAMESPACEMANAGER_CID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static NS_DEFINE_CID(kXULContentUtilsCID, NS_XULCONTENTUTILS_CID);
|
||||
|
||||
static NS_DEFINE_IID(kIXULPopupListenerIID, NS_IXULPOPUPLISTENER_IID);
|
||||
static NS_DEFINE_CID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID);
|
||||
static NS_DEFINE_IID(kIXULPopupListenerIID, NS_IXULPOPUPLISTENER_IID);
|
||||
static NS_DEFINE_CID(kXULPopupListenerCID, NS_XULPOPUPLISTENER_CID);
|
||||
|
||||
static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
|
||||
|
||||
|
@ -247,6 +247,13 @@ nsIAtom* nsXULElement::kTreeRowAtom;
|
|||
nsIAtom* nsXULElement::kEditorAtom;
|
||||
nsIAtom* nsXULElement::kWindowAtom;
|
||||
nsIAtom* nsXULElement::kNullAtom;
|
||||
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
PRUint32 nsXULPrototypeAttribute::gNumElements;
|
||||
PRUint32 nsXULPrototypeAttribute::gNumAttributes;
|
||||
PRUint32 nsXULPrototypeAttribute::gNumEventHandlers;
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsXULElement
|
||||
|
||||
|
@ -261,6 +268,9 @@ nsXULElement::nsXULElement()
|
|||
mSlots(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
nsXULPrototypeAttribute::gNumElements++;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -294,7 +304,7 @@ nsXULElement::Init()
|
|||
kTreeRowAtom = NS_NewAtom("treerow");
|
||||
kEditorAtom = NS_NewAtom("editor");
|
||||
kWindowAtom = NS_NewAtom("window");
|
||||
kNullAtom = NS_NewAtom("");
|
||||
kNullAtom = NS_NewAtom("");
|
||||
|
||||
rv = nsComponentManager::CreateInstance(kNameSpaceManagerCID,
|
||||
nsnull,
|
||||
|
@ -365,7 +375,7 @@ nsXULElement::~nsXULElement()
|
|||
NS_IF_RELEASE(kTreeRowAtom);
|
||||
NS_IF_RELEASE(kEditorAtom);
|
||||
NS_IF_RELEASE(kWindowAtom);
|
||||
NS_IF_RELEASE(kNullAtom);
|
||||
NS_IF_RELEASE(kNullAtom);
|
||||
|
||||
NS_IF_RELEASE(gNameSpaceManager);
|
||||
|
||||
|
@ -426,6 +436,9 @@ nsXULElement::Create(nsXULPrototypeElement* aPrototype,
|
|||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (found) {
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
nsXULPrototypeAttribute::gNumEventHandlers++;
|
||||
#endif
|
||||
rv = element->AddScriptEventListener(attr->mName, attr->mValue, iid);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
@ -510,6 +523,9 @@ nsXULElement::QueryInterface(REFNSIID iid, void** result)
|
|||
else if (iid.Equals(kIScriptObjectOwnerIID)) {
|
||||
*result = NS_STATIC_CAST(nsIScriptObjectOwner*, this);
|
||||
}
|
||||
else if (iid.Equals(NS_GET_IID(nsIScriptEventHandlerOwner))) {
|
||||
*result = NS_STATIC_CAST(nsIScriptEventHandlerOwner*, this);
|
||||
}
|
||||
else if (iid.Equals(kIDOMEventReceiverIID)) {
|
||||
*result = NS_STATIC_CAST(nsIDOMEventReceiver*, this);
|
||||
}
|
||||
|
@ -1483,6 +1499,45 @@ nsXULElement::SetScriptObject(void *aScriptObject)
|
|||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsIScriptEventHandlerOwner interface
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULElement::GetCompiledEventHandler(nsIAtom *aName, void** aHandler)
|
||||
{
|
||||
*aHandler = nsnull;
|
||||
if (mPrototype) {
|
||||
for (PRInt32 i = 0; i < mPrototype->mNumAttributes; ++i) {
|
||||
nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]);
|
||||
|
||||
if ((attr->mNameSpaceID == kNameSpaceID_None) &&
|
||||
(attr->mName == aName)) {
|
||||
*aHandler = attr->mEventHandler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULElement::SetCompiledEventHandler(nsIAtom *aName, void* aHandler)
|
||||
{
|
||||
if (mPrototype) {
|
||||
for (PRInt32 i = 0; i < mPrototype->mNumAttributes; ++i) {
|
||||
nsXULPrototypeAttribute* attr = &(mPrototype->mAttributes[i]);
|
||||
|
||||
if ((attr->mNameSpaceID == kNameSpaceID_None) &&
|
||||
(attr->mName == aName)) {
|
||||
attr->mEventHandler = aHandler;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// nsIJSScriptObject interface
|
||||
|
||||
|
@ -2136,8 +2191,8 @@ nsXULElement::SetAttribute(PRInt32 aNameSpaceID,
|
|||
|
||||
NS_IMETHODIMP
|
||||
nsXULElement::GetAttribute(PRInt32 aNameSpaceID,
|
||||
nsIAtom* aName,
|
||||
nsString& aResult) const
|
||||
nsIAtom* aName,
|
||||
nsString& aResult) const
|
||||
{
|
||||
NS_ASSERTION(nsnull != aName, "must have attribute name");
|
||||
if (nsnull == aName) {
|
||||
|
@ -2199,18 +2254,21 @@ nsXULElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotif
|
|||
if (! Attributes())
|
||||
return NS_OK;
|
||||
|
||||
// Check to see if the CLASS attribute is being unset. If so, we need to delete our
|
||||
// class list.
|
||||
if (mDocument && (aNameSpaceID == kNameSpaceID_None) && (aName == kClassAtom)) {
|
||||
// Check to see if the CLASS attribute is being unset. If so, we need to
|
||||
// delete our class list.
|
||||
// XXXbe fuse common (mDocument && aNameSpaceId == kNameSpaceID_None)
|
||||
if (mDocument &&
|
||||
(aNameSpaceID == kNameSpaceID_None) &&
|
||||
(aName == kClassAtom)) {
|
||||
Attributes()->UpdateClassList("");
|
||||
}
|
||||
|
||||
if (mDocument && (aNameSpaceID == kNameSpaceID_None) && aName == kStyleAtom) {
|
||||
if (mDocument &&
|
||||
(aNameSpaceID == kNameSpaceID_None) &&
|
||||
aName == kStyleAtom) {
|
||||
|
||||
nsCOMPtr <nsIURI> docURL;
|
||||
if (nsnull != mDocument) {
|
||||
mDocument->GetBaseURL(*getter_AddRefs(docURL));
|
||||
}
|
||||
mDocument->GetBaseURL(*getter_AddRefs(docURL));
|
||||
|
||||
Attributes()->UpdateStyleRule(docURL, "");
|
||||
// XXX Some kind of special document update might need to happen here.
|
||||
|
@ -2222,34 +2280,34 @@ nsXULElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotif
|
|||
nsCOMPtr<nsIAtom> tag;
|
||||
GetTag(*getter_AddRefs(tag));
|
||||
if (aNameSpaceID == kNameSpaceID_None) {
|
||||
// See if we're a treeitem atom.
|
||||
// XXX Forgive me father, for I know exactly what I do, and I'm
|
||||
// doing it anyway. Need to make an nsIRDFNodeList interface that
|
||||
// I can QI to for additions and removals of nodes. For now
|
||||
// do an evil cast.
|
||||
nsCOMPtr<nsIRDFNodeList> nodeList;
|
||||
if (tag && (tag.get() == kTreeItemAtom) && (aName == kSelectedAtom)) {
|
||||
nsCOMPtr<nsIDOMXULTreeElement> treeElement;
|
||||
GetParentTree(getter_AddRefs(treeElement));
|
||||
if (treeElement) {
|
||||
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||
treeElement->GetSelectedItems(getter_AddRefs(nodes));
|
||||
nodeList = do_QueryInterface(nodes);
|
||||
// See if we're a treeitem atom.
|
||||
// XXX Forgive me father, for I know exactly what I do, and I'm
|
||||
// doing it anyway. Need to make an nsIRDFNodeList interface that
|
||||
// I can QI to for additions and removals of nodes. For now
|
||||
// do an evil cast.
|
||||
nsCOMPtr<nsIRDFNodeList> nodeList;
|
||||
if (tag && (tag.get() == kTreeItemAtom) && (aName == kSelectedAtom)) {
|
||||
nsCOMPtr<nsIDOMXULTreeElement> treeElement;
|
||||
GetParentTree(getter_AddRefs(treeElement));
|
||||
if (treeElement) {
|
||||
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||
treeElement->GetSelectedItems(getter_AddRefs(nodes));
|
||||
nodeList = do_QueryInterface(nodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tag && (tag.get() == kTreeCellAtom) && (aName == kSelectedAtom)) {
|
||||
nsCOMPtr<nsIDOMXULTreeElement> treeElement;
|
||||
GetParentTree(getter_AddRefs(treeElement));
|
||||
if (treeElement) {
|
||||
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||
treeElement->GetSelectedCells(getter_AddRefs(nodes));
|
||||
nodeList = do_QueryInterface(nodes);
|
||||
else if (tag && (tag.get() == kTreeCellAtom) && (aName == kSelectedAtom)) {
|
||||
nsCOMPtr<nsIDOMXULTreeElement> treeElement;
|
||||
GetParentTree(getter_AddRefs(treeElement));
|
||||
if (treeElement) {
|
||||
nsCOMPtr<nsIDOMNodeList> nodes;
|
||||
treeElement->GetSelectedCells(getter_AddRefs(nodes));
|
||||
nodeList = do_QueryInterface(nodes);
|
||||
}
|
||||
}
|
||||
if (nodeList) {
|
||||
// Remove this node from the list.
|
||||
nodeList->RemoveNode(this);
|
||||
}
|
||||
}
|
||||
if (nodeList) {
|
||||
// Remove this node from the list.
|
||||
nodeList->RemoveNode(this);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX Know how to remove POPUP event listeners when an attribute is unset?
|
||||
|
@ -2263,7 +2321,8 @@ nsXULElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotif
|
|||
PRInt32 i;
|
||||
for (i = 0; i < count; i++) {
|
||||
nsXULAttribute* attr = NS_REINTERPRET_CAST(nsXULAttribute*, Attributes()->ElementAt(i));
|
||||
if ((attr->GetNameSpaceID() == aNameSpaceID) && (attr->GetName() == aName)) {
|
||||
if ((attr->GetNameSpaceID() == aNameSpaceID) &&
|
||||
(attr->GetName() == aName)) {
|
||||
attr->GetValue(oldValue);
|
||||
Attributes()->RemoveElementAt(i);
|
||||
NS_RELEASE(attr);
|
||||
|
@ -2275,50 +2334,50 @@ nsXULElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName, PRBool aNotif
|
|||
|
||||
// XUL Only. Find out if we have a broadcast listener for this element.
|
||||
if (successful) {
|
||||
// Check to see if the OBSERVES attribute is being unset. If so, we need to remove
|
||||
// ourselves completely.
|
||||
if (mDocument && (aNameSpaceID == kNameSpaceID_None) &&
|
||||
(aName == kObservesAtom))
|
||||
{
|
||||
// Do a getElementById to retrieve the broadcaster.
|
||||
nsCOMPtr<nsIDOMElement> broadcaster;
|
||||
nsCOMPtr<nsIDOMXULDocument> domDoc = do_QueryInterface(mDocument);
|
||||
domDoc->GetElementById(oldValue, getter_AddRefs(broadcaster));
|
||||
if (broadcaster) {
|
||||
nsCOMPtr<nsIDOMXULElement> xulBroadcaster = do_QueryInterface(broadcaster);
|
||||
if (xulBroadcaster) {
|
||||
xulBroadcaster->RemoveBroadcastListener("*", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (BroadcastListeners()) {
|
||||
PRInt32 count = BroadcastListeners()->Count();
|
||||
for (PRInt32 i = 0; i < count; i++)
|
||||
// Check to see if the OBSERVES attribute is being unset. If so, we
|
||||
// need to remove ourselves completely.
|
||||
if (mDocument &&
|
||||
(aNameSpaceID == kNameSpaceID_None) &&
|
||||
(aName == kObservesAtom))
|
||||
{
|
||||
XULBroadcastListener* xulListener =
|
||||
NS_REINTERPRET_CAST(XULBroadcastListener*, BroadcastListeners()->ElementAt(i));
|
||||
|
||||
nsAutoString str;
|
||||
aName->ToString(str);
|
||||
if (xulListener->ObservingAttribute(str) &&
|
||||
(aName != kIdAtom)) {
|
||||
// XXX Should have a function that knows which attributes are special.
|
||||
// Unset the attribute in the broadcast listener.
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
element = do_QueryInterface(xulListener->mListener);
|
||||
if (element)
|
||||
element->RemoveAttribute(str);
|
||||
// Do a getElementById to retrieve the broadcaster.
|
||||
nsCOMPtr<nsIDOMElement> broadcaster;
|
||||
nsCOMPtr<nsIDOMXULDocument> domDoc = do_QueryInterface(mDocument);
|
||||
domDoc->GetElementById(oldValue, getter_AddRefs(broadcaster));
|
||||
if (broadcaster) {
|
||||
nsCOMPtr<nsIDOMXULElement> xulBroadcaster = do_QueryInterface(broadcaster);
|
||||
if (xulBroadcaster) {
|
||||
xulBroadcaster->RemoveBroadcastListener("*", this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify document
|
||||
if (NS_SUCCEEDED(rv) && aNotify && (nsnull != mDocument)) {
|
||||
mDocument->AttributeChanged(NS_STATIC_CAST(nsIStyledContent*, this),
|
||||
aNameSpaceID, aName,
|
||||
NS_STYLE_HINT_UNKNOWN);
|
||||
}
|
||||
|
||||
if (BroadcastListeners()) {
|
||||
PRInt32 count = BroadcastListeners()->Count();
|
||||
for (PRInt32 i = 0; i < count; i++) {
|
||||
XULBroadcastListener* xulListener =
|
||||
NS_REINTERPRET_CAST(XULBroadcastListener*, BroadcastListeners()->ElementAt(i));
|
||||
|
||||
nsAutoString str;
|
||||
aName->ToString(str);
|
||||
if (xulListener->ObservingAttribute(str) &&
|
||||
(aName != kIdAtom)) {
|
||||
// XXX Should have a function that knows which attributes are special.
|
||||
// Unset the attribute in the broadcast listener.
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
element = do_QueryInterface(xulListener->mListener);
|
||||
if (element)
|
||||
element->RemoveAttribute(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Notify document
|
||||
if (NS_SUCCEEDED(rv) && aNotify && (nsnull != mDocument)) {
|
||||
mDocument->AttributeChanged(NS_STATIC_CAST(nsIStyledContent*, this),
|
||||
aNameSpaceID, aName,
|
||||
NS_STYLE_HINT_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
// End XUL Only Code
|
||||
|
@ -3094,11 +3153,11 @@ nsXULElement::GetID(nsIAtom*& aResult) const
|
|||
GetAttribute(kNameSpaceID_None, kIdAtom, value);
|
||||
|
||||
if (value.Length() > 0)
|
||||
aResult = NS_NewAtom(value); // The NewAtom call does the AddRef.
|
||||
aResult = NS_NewAtom(value); // The NewAtom call does the AddRef.
|
||||
else
|
||||
{
|
||||
aResult = kNullAtom;
|
||||
NS_ADDREF(kNullAtom);
|
||||
aResult = kNullAtom;
|
||||
NS_ADDREF(kNullAtom);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -78,11 +78,63 @@ class nsXULAttributes;
|
|||
class nsXULPrototypeAttribute
|
||||
{
|
||||
public:
|
||||
nsXULPrototypeAttribute() : mNameSpaceID(kNameSpaceID_Unknown) {}
|
||||
nsXULPrototypeAttribute()
|
||||
: mNameSpaceID(kNameSpaceID_Unknown),
|
||||
mEventHandler(nsnull)
|
||||
{
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
gNumAttributes++;
|
||||
#endif
|
||||
}
|
||||
|
||||
PRInt32 mNameSpaceID;
|
||||
nsCOMPtr<nsIAtom> mName;
|
||||
nsString mValue;
|
||||
void* mEventHandler;
|
||||
|
||||
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
|
||||
/**
|
||||
If enough attributes, on average, are event handlers, it pays to keep
|
||||
mEventHandler here, instead of maintaining a separate mapping in each
|
||||
nsXULElement associating certain mName values to their mEventHandlers.
|
||||
Assume we don't need to keep mNameSpaceID along with mName in such an
|
||||
event-handler-only name-to-function-pointer mapping.
|
||||
|
||||
Let
|
||||
minAttrSize = sizeof(mNameSpaceID) + sizeof(mName) + sizeof(mValue)
|
||||
mappingSize = sizeof(mName) + sizeof(mEventHandler)
|
||||
elemOverhead = nElems * sizeof(void*)
|
||||
|
||||
Then
|
||||
nAttrs * minAttrSize + nEventHandlers * mappingSize + elemOverhead
|
||||
> nAttrs * (minAttrSize + mappingSize - sizeof(mName))
|
||||
which simplifies to
|
||||
nEventHandlers * mappingSize + elemOverhead
|
||||
> nAttrs * (mappingSize - sizeof(mName))
|
||||
or
|
||||
nEventHandlers + (nElems * sizeof(void*)) / mappingSize
|
||||
> nAttrs * (1 - sizeof(mName) / mappingSize)
|
||||
|
||||
If nsCOMPtr and all other pointers are the same size, this reduces to
|
||||
nEventHandlers + nElems / 2 > nAttrs / 2
|
||||
|
||||
To measure how many attributes are event handlers, compile XUL source
|
||||
with XUL_PROTOTYPE_ATTRIBUTE_METERING and watch the counters below.
|
||||
Plug into the above relation -- if true, it pays to put mEventHandler
|
||||
in nsXULPrototypeAttribute rather than to keep a separate mapping.
|
||||
|
||||
Recent numbers after opening four browser windows:
|
||||
nElems 3537, nAttrs 2528, nEventHandlers 1042
|
||||
giving 1042 + 3537/2 > 2528/2 or 2810 > 1264.
|
||||
|
||||
As it happens, mEventHandler also makes this struct power-of-2 sized,
|
||||
8 words on most architectures, which makes for strength-reduced array
|
||||
index-to-pointer calculations.
|
||||
*/
|
||||
static PRUint32 gNumElements;
|
||||
static PRUint32 gNumAttributes;
|
||||
static PRUint32 gNumEventHandlers;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -249,6 +301,7 @@ class nsXULElement : public nsIStyledContent,
|
|||
public nsIDOMXULElement,
|
||||
public nsIDOMEventReceiver,
|
||||
public nsIScriptObjectOwner,
|
||||
public nsIScriptEventHandlerOwner,
|
||||
public nsIJSScriptObject,
|
||||
public nsIStyleRule,
|
||||
public nsIChromeEventHandler
|
||||
|
@ -389,6 +442,10 @@ public:
|
|||
NS_IMETHOD GetScriptObject(nsIScriptContext* aContext, void** aScriptObject);
|
||||
NS_IMETHOD SetScriptObject(void *aScriptObject);
|
||||
|
||||
// nsIScriptEventHandlerOwner
|
||||
NS_IMETHOD GetCompiledEventHandler(nsIAtom *aName, void** aHandler);
|
||||
NS_IMETHOD SetCompiledEventHandler(nsIAtom *aName, void* aHandler);
|
||||
|
||||
// nsIJSScriptObject
|
||||
virtual PRBool AddProperty(JSContext *aContext, jsval aID, jsval *aVp);
|
||||
virtual PRBool DeleteProperty(JSContext *aContext, jsval aID, jsval *aVp);
|
||||
|
|
Загрузка…
Ссылка в новой задаче