From 32a1b814f20ce892a38105fb735a2ecbb2658554 Mon Sep 17 00:00:00 2001 From: "aaronr%us.ibm.com" Date: Wed, 16 Jan 2008 21:26:35 +0000 Subject: [PATCH] [XForms] NPOTDB implement if/while without virtual inheritance. Bug 388976, p=smaug r=jlc+aaronr git-svn-id: svn://10.0.0.236/trunk@243317 18797224-902f-48f8-a5cc-f745e15eee43 --- .../xforms/nsXFormsActionElement.cpp | 17 +- .../extensions/xforms/nsXFormsActionElement.h | 16 +- .../xforms/nsXFormsActionModuleBase.cpp | 44 +- .../xforms/nsXFormsActionModuleBase.h | 86 +- .../extensions/xforms/nsXFormsCaseElement.cpp | 3 +- .../xforms/nsXFormsChoicesElement.cpp | 3 +- .../extensions/xforms/nsXFormsControlStub.h | 6 +- .../extensions/xforms/nsXFormsCopyElement.cpp | 5 +- .../xforms/nsXFormsDispatchElement.cpp | 4 +- .../xforms/nsXFormsInsertDeleteElement.cpp | 1128 +++++++++-------- .../xforms/nsXFormsInstanceElement.cpp | 2 +- .../xforms/nsXFormsInstanceElement.h | 1 + .../extensions/xforms/nsXFormsLoadElement.cpp | 8 +- .../xforms/nsXFormsMessageElement.cpp | 41 +- .../xforms/nsXFormsModelElement.cpp | 2 +- .../extensions/xforms/nsXFormsModelElement.h | 1 + .../xforms/nsXFormsRebuildElement.cpp | 8 +- .../xforms/nsXFormsRecalculateElement.cpp | 8 +- .../xforms/nsXFormsRefreshElement.cpp | 8 +- .../xforms/nsXFormsResetElement.cpp | 8 +- .../xforms/nsXFormsRevalidateElement.cpp | 8 +- .../extensions/xforms/nsXFormsSendElement.cpp | 8 +- .../xforms/nsXFormsSetFocusElement.cpp | 8 +- .../xforms/nsXFormsSetIndexElement.cpp | 8 +- .../xforms/nsXFormsSetValueElement.cpp | 8 +- .../extensions/xforms/nsXFormsStubElement.h | 3 - .../xforms/nsXFormsSubmissionElement.h | 3 +- .../xforms/nsXFormsToggleElement.cpp | 8 +- 28 files changed, 757 insertions(+), 696 deletions(-) diff --git a/mozilla/extensions/xforms/nsXFormsActionElement.cpp b/mozilla/extensions/xforms/nsXFormsActionElement.cpp index 5d8159177ac..e9b0e5e2e59 100644 --- a/mozilla/extensions/xforms/nsXFormsActionElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsActionElement.cpp @@ -49,8 +49,7 @@ #define DEFERRED_REVALIDATE 0x04 #define DEFERRED_REFRESH 0x08 -nsXFormsActionElement::nsXFormsActionElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsActionElement::nsXFormsActionElement() : mElement(nsnull) { } @@ -155,6 +154,13 @@ PR_STATIC_CALLBACK(PLDHashOperator) DoDeferredActions(nsISupports * aModel, return PL_DHASH_NEXT; } +NS_IMETHODIMP +nsXFormsActionElement::HandleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement* aParentAction) +{ + return nsXFormsActionModuleBase::DoHandleAction(this, aEvent, aParentAction); +} + nsresult nsXFormsActionElement::HandleSingleAction(nsIDOMEvent* aEvent, nsIXFormsActionElement *aParentAction) @@ -291,6 +297,13 @@ nsXFormsActionElement::SetRefresh(nsIModelElementPrivate* aModel, return NS_OK; } +NS_IMETHODIMP +nsXFormsActionElement::GetCurrentEvent(nsIDOMEvent** aEvent) +{ + NS_IF_ADDREF(*aEvent = mCurrentEvent); + return NS_OK; +} + NS_HIDDEN_(nsresult) NS_NewXFormsActionElement(nsIXTFElement **aResult) { diff --git a/mozilla/extensions/xforms/nsXFormsActionElement.h b/mozilla/extensions/xforms/nsXFormsActionElement.h index 00f29f513e2..13a4a24665c 100644 --- a/mozilla/extensions/xforms/nsXFormsActionElement.h +++ b/mozilla/extensions/xforms/nsXFormsActionElement.h @@ -46,24 +46,30 @@ class nsIXTFElementWrapper; -class nsXFormsActionElement : public nsIXFormsActionElement, - public nsXFormsActionModuleBase +class nsXFormsActionElement : public nsXFormsStubElement, + public nsIXFormsActionElement, + public nsIXFormsActionModuleElement, + public nsIDOMEventListener, + public nsXFormsActionModuleHelper { public: nsXFormsActionElement(); NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIDOMEVENTLISTENER NS_DECL_NSIXFORMSACTIONELEMENT + NS_DECL_NSIXFORMSACTIONMODULEELEMENT NS_IMETHOD OnCreated(nsIXTFElementWrapper *aWrapper); NS_IMETHOD OnDestroyed(); NS_IMETHOD WillChangeDocument(nsIDOMDocument *aNewDocument); NS_IMETHOD DocumentChanged(nsIDOMDocument *aNewDocument); NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent); NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + + virtual nsIDOMElement* GetElement() { return mElement; } + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement* aParentAction); private: + nsIDOMElement* mElement; nsCOMPtr mParentAction; nsDataHashtable mDeferredUpdates; }; diff --git a/mozilla/extensions/xforms/nsXFormsActionModuleBase.cpp b/mozilla/extensions/xforms/nsXFormsActionModuleBase.cpp index 11c9a7d3056..e160a227769 100644 --- a/mozilla/extensions/xforms/nsXFormsActionModuleBase.cpp +++ b/mozilla/extensions/xforms/nsXFormsActionModuleBase.cpp @@ -58,8 +58,7 @@ #include "nsIPrefService.h" #include "nsServiceManagerUtils.h" -nsXFormsActionModuleBase::nsXFormsActionModuleBase(PRBool canIterate) : - nsXFormsStubElement(), mCanIterate(canIterate) +nsXFormsActionModuleBase::nsXFormsActionModuleBase() : mElement(nsnull) { } @@ -145,10 +144,17 @@ NS_IMETHODIMP nsXFormsActionModuleBase::HandleAction(nsIDOMEvent *aEvent, nsIXFormsActionElement *aParentAction) { - if (!mElement) - return NS_OK; + return nsXFormsActionModuleBase::DoHandleAction(this, aEvent, aParentAction); +} - mCurrentEvent = aEvent; +/* static */ nsresult +nsXFormsActionModuleBase::DoHandleAction(nsXFormsActionModuleHelper *aXFormsAction, + nsIDOMEvent *aEvent, + nsIXFormsActionElement *aParentAction) +{ + nsCOMPtr element = aXFormsAction->GetElement(); + NS_ENSURE_STATE(element); + aXFormsAction->SetCurrentEvent(aEvent); // Set the maximum run time for the loop (in microseconds). PRTime microseconds = nsXFormsUtils::waitLimit * PR_USEC_PER_SEC; @@ -159,17 +165,17 @@ nsXFormsActionModuleBase::HandleAction(nsIDOMEvent *aEvent, // Test the `if` and `while` attributes to determine whether this action // can be performed and should be repeated. PRBool usesWhile; - if (!CanPerformAction(&usesWhile)) { + if (!nsXFormsActionModuleBase::CanPerformAction(element, &usesWhile)) { return NS_OK; } - nsresult rv = HandleSingleAction(aEvent, aParentAction); + nsresult rv = aXFormsAction->HandleSingleAction(aEvent, aParentAction); NS_ENSURE_SUCCESS(rv, rv); // Repeat this action if it can iterate and if it uses the `while` // attribute (the expression of which must have evaluated to true to // arrive here). - if (!mCanIterate || !usesWhile) { + if (!aXFormsAction->CanIterate() || !usesWhile) { return NS_OK; } @@ -182,7 +188,7 @@ nsXFormsActionModuleBase::HandleAction(nsIDOMEvent *aEvent, // The remaining part of the loop prompts the user about cancelling the // loop, and is only executed if we've gone over the time limit. - PRBool stopWaiting = nsXFormsUtils::AskStopWaiting(mElement); + PRBool stopWaiting = nsXFormsUtils::AskStopWaiting(element); if (stopWaiting) { // Stop the loop @@ -193,18 +199,20 @@ nsXFormsActionModuleBase::HandleAction(nsIDOMEvent *aEvent, } } +/* static */ PRBool -nsXFormsActionModuleBase::CanPerformAction(PRBool *aUsesWhile, - nsIDOMNode *aContext, - PRInt32 aContextSize, - PRInt32 aContextPosition) +nsXFormsActionModuleBase::CanPerformAction(nsIDOMElement *aElement, + PRBool *aUsesWhile, + nsIDOMNode *aContext, + PRInt32 aContextSize, + PRInt32 aContextPosition) { *aUsesWhile = PR_FALSE; nsAutoString ifExpr; nsAutoString whileExpr; - mElement->GetAttribute(NS_LITERAL_STRING("if"), ifExpr); - mElement->GetAttribute(NS_LITERAL_STRING("while"), whileExpr); + aElement->GetAttribute(NS_LITERAL_STRING("if"), ifExpr); + aElement->GetAttribute(NS_LITERAL_STRING("while"), whileExpr); if (whileExpr.IsEmpty() && ifExpr.IsEmpty()) { return PR_TRUE; @@ -224,7 +232,7 @@ nsXFormsActionModuleBase::CanPerformAction(PRBool *aUsesWhile, nsCOMPtr bindElement; nsCOMPtr parentControl; PRBool outerBind; - rv = nsXFormsUtils::GetNodeContext(mElement, 0, + rv = nsXFormsUtils::GetNodeContext(aElement, 0, getter_AddRefs(model), getter_AddRefs(bindElement), &outerBind, @@ -237,7 +245,7 @@ nsXFormsActionModuleBase::CanPerformAction(PRBool *aUsesWhile, if (!whileExpr.IsEmpty()) { *aUsesWhile = PR_TRUE; - rv = nsXFormsUtils::EvaluateXPath(whileExpr, contextNode, mElement, + rv = nsXFormsUtils::EvaluateXPath(whileExpr, contextNode, aElement, nsIDOMXPathResult::BOOLEAN_TYPE, getter_AddRefs(res), aContextPosition, aContextSize); @@ -250,7 +258,7 @@ nsXFormsActionModuleBase::CanPerformAction(PRBool *aUsesWhile, } if (!ifExpr.IsEmpty()) { - rv = nsXFormsUtils::EvaluateXPath(ifExpr, contextNode, mElement, + rv = nsXFormsUtils::EvaluateXPath(ifExpr, contextNode, aElement, nsIDOMXPathResult::BOOLEAN_TYPE, getter_AddRefs(res), aContextPosition, aContextSize); diff --git a/mozilla/extensions/xforms/nsXFormsActionModuleBase.h b/mozilla/extensions/xforms/nsXFormsActionModuleBase.h index cf08dc24157..07dd782431b 100644 --- a/mozilla/extensions/xforms/nsXFormsActionModuleBase.h +++ b/mozilla/extensions/xforms/nsXFormsActionModuleBase.h @@ -48,38 +48,22 @@ #include "nsCOMPtr.h" #include "nsXFormsUtils.h" -class nsXFormsActionModuleBase : public nsIDOMEventListener, - public virtual nsXFormsStubElement, - public nsIXFormsActionModuleElement +class nsXFormsActionModuleHelper { -public: - nsXFormsActionModuleBase(PRBool canIterate = PR_FALSE); - virtual ~nsXFormsActionModuleBase(); - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_NSIXFORMSACTIONMODULEELEMENT - NS_DECL_NSIDOMEVENTLISTENER - NS_IMETHOD OnCreated(nsIXTFElementWrapper *aWrapper); - NS_IMETHOD OnDestroyed(); - NS_IMETHOD WillChangeDocument(nsIDOMDocument *aNewDocument); - NS_IMETHOD DocumentChanged(nsIDOMDocument *aNewDocument); - NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent); - NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent); -protected: /** - * Determine whether this action element should be executed, based upon - * optional `if` and `while` attributes. For each of these attributes - * that are present on an action element, the action is only performed if - * the boolean value of the XPath expression contained in the attribute is - * true. In addition, if the `while` attribute is used, the action is - * "executed repeatedly" until one of these attributes evaluates to false. - * This method indicates to the caller whether the action element uses a - * `while` attribute through the `usesWhile` parameter. + * nsXFormsActionModuleHelper provides the foundation that allows event + * iteration to work. Every xforms action needs to inherit from + * nsXFormsActionModuleHelper in some capacity; they can inherit indirectly + * through nsXFormsActionModuleBase or directly from + * nsXFormsActionModuleHelper in the cases where the action actually needs to + * have binding capabilities (like nsXFormsAlertElement, etc) */ - NS_HIDDEN_(PRBool) CanPerformAction(PRBool *usesWhile, - nsIDOMNode *contextNode = nsnull, - PRInt32 contextSize = 0, - PRInt32 contextPosition = 0); +public: + nsXFormsActionModuleHelper() : mCanIterate(PR_TRUE) {} + virtual nsIDOMElement* GetElement() = 0; + PRBool CanIterate() { return mCanIterate; } + void SetCurrentEvent(nsIDOMEvent* aEvent) { mCurrentEvent = aEvent; } /** * With the `while` attribute, actions can potentially be iterated. The * `HandleSingleAction` method processes one iteration of an action (that @@ -88,9 +72,9 @@ protected: * iteration of the action. */ virtual nsresult - HandleSingleAction(nsIDOMEvent* aEvent, + HandleSingleAction(nsIDOMEvent *aEvent, nsIXFormsActionElement *aParentAction) = 0; - +protected: /** * This signals whether or not this action can iterate. Technically, all * XForms 1.1 actions are allowed to iterate, but for some of them it @@ -106,5 +90,47 @@ protected: nsCOMPtr mCurrentEvent; }; +class nsXFormsActionModuleBase : public nsIDOMEventListener, + public nsXFormsStubElement, + public nsIXFormsActionModuleElement, + public nsXFormsActionModuleHelper +{ +public: + nsXFormsActionModuleBase(); + virtual ~nsXFormsActionModuleBase(); + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSIXFORMSACTIONMODULEELEMENT + NS_DECL_NSIDOMEVENTLISTENER + NS_IMETHOD OnCreated(nsIXTFElementWrapper *aWrapper); + NS_IMETHOD OnDestroyed(); + NS_IMETHOD WillChangeDocument(nsIDOMDocument *aNewDocument); + NS_IMETHOD DocumentChanged(nsIDOMDocument *aNewDocument); + NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent); + NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent); + + virtual nsIDOMElement *GetElement() { return mElement; } + + static nsresult DoHandleAction(nsXFormsActionModuleHelper *aXFormsAction, + nsIDOMEvent *aEvent, + nsIXFormsActionElement *aParentAction); + /** + * Determine whether this action element should be executed, based upon + * optional `if` and `while` attributes. For each of these attributes + * that are present on an action element, the action is only performed if + * the boolean value of the XPath expression contained in the attribute is + * true. In addition, if the `while` attribute is used, the action is + * "executed repeatedly" until one of these attributes evaluates to false. + * This method indicates to the caller whether the action element uses a + * `while` attribute through the `usesWhile` parameter. + */ + static PRBool CanPerformAction(nsIDOMElement *aElement, + PRBool *aUsesWhile, + nsIDOMNode *aContextNode = nsnull, + PRInt32 aContextSize = 0, + PRInt32 aContextPosition = 0); +protected: + nsIDOMElement *mElement; +}; + #endif diff --git a/mozilla/extensions/xforms/nsXFormsCaseElement.cpp b/mozilla/extensions/xforms/nsXFormsCaseElement.cpp index 2c857c65928..107e0a87c7f 100644 --- a/mozilla/extensions/xforms/nsXFormsCaseElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsCaseElement.cpp @@ -63,11 +63,12 @@ public: NS_IMETHOD DoneAddingChildren(); nsXFormsCaseElement() - : nsXFormsStubElement(), mSelected(PR_FALSE), mCachedSelectedAttr(PR_FALSE) + : mElement(nsnull), mSelected(PR_FALSE), mCachedSelectedAttr(PR_FALSE) { } protected: + nsIDOMElement* mElement; PRPackedBool mSelected; PRPackedBool mCachedSelectedAttr; }; diff --git a/mozilla/extensions/xforms/nsXFormsChoicesElement.cpp b/mozilla/extensions/xforms/nsXFormsChoicesElement.cpp index d194dffc8a0..81a13cb87a1 100644 --- a/mozilla/extensions/xforms/nsXFormsChoicesElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsChoicesElement.cpp @@ -51,7 +51,7 @@ class nsXFormsChoicesElement : public nsXFormsStubElement, public nsIXFormsSelectChild { public: - nsXFormsChoicesElement() : nsXFormsStubElement(), mDoneAddingChildren(PR_FALSE) {} + nsXFormsChoicesElement() : mElement(nsnull), mDoneAddingChildren(PR_FALSE) {} NS_DECL_ISUPPORTS_INHERITED @@ -69,6 +69,7 @@ public: NS_DECL_NSIXFORMSSELECTCHILD private: + nsIDOMElement* mElement; PRBool mDoneAddingChildren; void Refresh(); diff --git a/mozilla/extensions/xforms/nsXFormsControlStub.h b/mozilla/extensions/xforms/nsXFormsControlStub.h index 2e6f563e150..610f6f8bab2 100644 --- a/mozilla/extensions/xforms/nsXFormsControlStub.h +++ b/mozilla/extensions/xforms/nsXFormsControlStub.h @@ -64,7 +64,7 @@ class nsIDOMXPathResult; * Common stub for all XForms controls that inherit from nsIXFormsControl and * is bound to an instance node. */ -class nsXFormsControlStub : public virtual nsXFormsStubElement, +class nsXFormsControlStub : public nsXFormsStubElement, public nsIXFormsControl { public: @@ -159,7 +159,6 @@ public: /** Constructor */ nsXFormsControlStub() : - nsXFormsStubElement(), kStandardNotificationMask(nsIXTFElement::NOTIFY_WILL_SET_ATTRIBUTE | nsIXTFElement::NOTIFY_ATTRIBUTE_SET | nsIXTFElement::NOTIFY_WILL_REMOVE_ATTRIBUTE | @@ -178,6 +177,9 @@ public: {}; protected: + /** The nsIXTFElementWrapper */ + nsIDOMElement* mElement; + /** The node that the control is bound to. */ nsCOMPtr mBoundNode; diff --git a/mozilla/extensions/xforms/nsXFormsCopyElement.cpp b/mozilla/extensions/xforms/nsXFormsCopyElement.cpp index b1c479ccbea..814eb2ae73e 100644 --- a/mozilla/extensions/xforms/nsXFormsCopyElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsCopyElement.cpp @@ -56,7 +56,7 @@ class nsXFormsCopyElement : public nsXFormsStubElement, public nsIXFormsCopyElement { public: - nsXFormsCopyElement() : nsXFormsStubElement() {} + nsXFormsCopyElement() : mElement(nsnull) {} NS_DECL_ISUPPORTS_INHERITED @@ -67,6 +67,9 @@ public: // nsIXFormsCopyElement NS_DECL_NSIXFORMSCOPYELEMENT + +private: + nsIDOMElement *mElement; }; NS_IMPL_ISUPPORTS_INHERITED1(nsXFormsCopyElement, diff --git a/mozilla/extensions/xforms/nsXFormsDispatchElement.cpp b/mozilla/extensions/xforms/nsXFormsDispatchElement.cpp index 0dcd8701f97..a70fecc5ca4 100644 --- a/mozilla/extensions/xforms/nsXFormsDispatchElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsDispatchElement.cpp @@ -49,13 +49,11 @@ class nsXFormsDispatchElement : public nsXFormsActionModuleBase { public: nsXFormsDispatchElement(); -protected: nsresult HandleSingleAction(nsIDOMEvent* aEvent, nsIXFormsActionElement *aParentAction); }; -nsXFormsDispatchElement::nsXFormsDispatchElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsDispatchElement::nsXFormsDispatchElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp b/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp index a7344c6f1e8..2abcf0c6ac1 100644 --- a/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsInsertDeleteElement.cpp @@ -105,15 +105,11 @@ private: public: /** Constructor */ - nsXFormsInsertDeleteElement(PRBool aIsInsert) : - nsXFormsActionModuleBase(PR_TRUE), - mIsInsert(aIsInsert) - {} + nsXFormsInsertDeleteElement(PRBool aIsInsert) : mIsInsert(aIsInsert) {} NS_IMETHOD HandleAction(nsIDOMEvent* aEvent, nsIXFormsActionElement *aParentAction); -protected: /** * Normally, an action element implements the body of its action handler * using this method; however, since an `nsXFormsInsertDeleteElement` sets @@ -132,584 +128,612 @@ NS_IMETHODIMP nsXFormsInsertDeleteElement::HandleAction(nsIDOMEvent *aEvent, nsIXFormsActionElement *aParentAction) { - if (!mElement) + // Keep element alive while iterating. + nsCOMPtr element = mElement; + if (!element) return NS_OK; mCurrentEvent = aEvent; nsresult rv; - // - // Step 1 (Insert or Delete): Determine the insert/delete context. - // - // If the bind attribute is present or if the context attribute is not given, - // the insert context is the in-scope evaluation context. Otherwise, the - // XPath expression provided by the context attribute is evaluated using the - // in-scope evaluation context, and the first node rule is applied to obtain - // the insert context. - // - nsCOMPtr contextNodeset; - nsCOMPtr contextNode; - PRUint32 contextNodesetSize = 0; - PRInt32 contextPosition; - - // Get the in-scope evaluation context. The last parameter to GetNodeContext - // indicates whether it should try to get the context using @bind. We want to - // ignore @bind because it should not change the in-scope evaluation context - // for insert. - nsCOMPtr model; - nsCOMPtr bindElement; - nsCOMPtr parentControl; - PRBool outerBind; - rv = nsXFormsUtils::GetNodeContext(mElement, - nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, - getter_AddRefs(model), - getter_AddRefs(bindElement), - &outerBind, - getter_AddRefs(parentControl), - getter_AddRefs(contextNode), - &contextPosition, - (PRInt32*)&contextNodesetSize, - PR_FALSE); - - NS_ENSURE_SUCCESS(rv, rv); - - // Determine if the context node is specified via @context. - // If @bind is present, @context is ignored. - nsAutoString bindExpr; - nsAutoString contextExpr; - mElement->GetAttribute(NS_LITERAL_STRING("bind"), bindExpr); - mElement->GetAttribute(NS_LITERAL_STRING("context"), contextExpr); - - if (bindExpr.IsEmpty() && !contextExpr.IsEmpty()) { - // @context is specified and overrides the in-scope evaluation context. - // The insert context is the result of evaluating @context in the current - // in-scope evaluation context. - rv = nsXFormsUtils::EvaluateXPath(contextExpr, contextNode, mElement, - nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, - getter_AddRefs(contextNodeset)); + // Set the maximum run time for the loop (in microseconds). + PRTime microseconds = nsXFormsUtils::waitLimit * PR_USEC_PER_SEC; + PRTime runTime = 0, start = PR_Now(); + while (PR_TRUE) { + // + // Step 1 (Insert or Delete): Determine the insert/delete context. + // + // If the bind attribute is present or if the context attribute is not given, + // the insert context is the in-scope evaluation context. Otherwise, the + // XPath expression provided by the context attribute is evaluated using the + // in-scope evaluation context, and the first node rule is applied to obtain + // the insert context. + // + nsCOMPtr contextNodeset; + nsCOMPtr contextNode; + PRUint32 contextNodesetSize = 0; + PRInt32 contextPosition; + + // Get the in-scope evaluation context. The last parameter to GetNodeContext + // indicates whether it should try to get the context using @bind. We want to + // ignore @bind because it should not change the in-scope evaluation context + // for insert. + nsCOMPtr model; + nsCOMPtr bindElement; + nsCOMPtr parentControl; + PRBool outerBind; + rv = nsXFormsUtils::GetNodeContext(element, + nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, + getter_AddRefs(model), + getter_AddRefs(bindElement), + &outerBind, + getter_AddRefs(parentControl), + getter_AddRefs(contextNode), + &contextPosition, + (PRInt32*)&contextNodesetSize, + PR_FALSE); + NS_ENSURE_SUCCESS(rv, rv); - + + // Determine if the context node is specified via @context. + // If @bind is present, @context is ignored. + nsAutoString bindExpr; + nsAutoString contextExpr; + element->GetAttribute(NS_LITERAL_STRING("bind"), bindExpr); + element->GetAttribute(NS_LITERAL_STRING("context"), contextExpr); + + if (bindExpr.IsEmpty() && !contextExpr.IsEmpty()) { + // @context is specified and overrides the in-scope evaluation context. + // The insert context is the result of evaluating @context in the current + // in-scope evaluation context. + rv = nsXFormsUtils::EvaluateXPath(contextExpr, contextNode, element, + nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, + getter_AddRefs(contextNodeset)); + NS_ENSURE_SUCCESS(rv, rv); + + // The insert/delete action is terminated with no effect if the context + // is the empty node-set. + if (contextNodeset) { + rv = contextNodeset->GetSnapshotLength(&contextNodesetSize); + NS_ENSURE_SUCCESS(rv, rv); + + if (contextNodesetSize < 1) + return NS_OK; + + // Context node is the first node in the nodeset. + contextNodeset->SnapshotItem(0, getter_AddRefs(contextNode)); + contextPosition = 1; + } + } + // The insert/delete action is terminated with no effect if the context // is the empty node-set. - if (contextNodeset) { - rv = contextNodeset->GetSnapshotLength(&contextNodesetSize); - NS_ENSURE_SUCCESS(rv, rv); + if (!contextNode) + return NS_OK; - if (contextNodesetSize < 1) + // The insert action is terminated with no effect if the context attribute + // is given and the insert context does not evaluate to an element node. + if (mIsInsert && !contextExpr.IsEmpty()) { + PRUint16 nodeType; + contextNode->GetNodeType(&nodeType); + if (nodeType != nsIDOMNode::ELEMENT_NODE) return NS_OK; + } - // Context node is the first node in the nodeset. - contextNodeset->SnapshotItem(0, getter_AddRefs(contextNode)); - contextPosition = 1; + // Test the `if` and `while` attributes to determine whether this action + // can be performed and should be repeated. As the insert and delete + // actions can change their context, we do this testing here instead of + // relying on the default logic from our parent class' `HandleAction` + // (or `DoHandleAction`) definition. + PRBool usesWhile; + if (!nsXFormsActionModuleBase::CanPerformAction(element, &usesWhile, + contextNode, + contextNodesetSize, + contextPosition)) { + return NS_OK; } - } - - // The insert/delete action is terminated with no effect if the context - // is the empty node-set. - if (!contextNode) - return NS_OK; - - // The insert action is terminated with no effect if the context attribute - // is given and the insert context does not evaluate to an element node. - if (mIsInsert && !contextExpr.IsEmpty()) { - PRUint16 nodeType; - contextNode->GetNodeType(&nodeType); - if (nodeType != nsIDOMNode::ELEMENT_NODE) - return NS_OK; - } - - // Test the `if` and `while` attributes to determine whether this action - // can be performed and should be repeated. As the insert and delete - // actions can change their context, we do this testing here instead of - // relying on the default logic from our parent class' `HandleAction` - // definition. - PRBool usesWhile; - if (!CanPerformAction(&usesWhile, contextNode, - contextNodesetSize, contextPosition)) { - return NS_OK; - } - - // - // Step 2 (Insert or Delete): Determine the node-set binding. - // - // If the bind attribute is present, it directly determines the Node Set - // Binding node-set. If a nodeset attribute is present, it is evaluated - // within the context to determine the Node Set Binding node-set. - // - // A NodeSet binding attribute (@bind or @nodeset) is required unless - // the context attribute is present. - // - nsCOMPtr nodeset; - PRUint32 nodesetSize = 0; - nsAutoString nodesetExpr; - - if (bindExpr.IsEmpty()) { - mElement->GetAttribute(NS_LITERAL_STRING("nodeset"), nodesetExpr); - if (!nodesetExpr.IsEmpty()) { - // Evaluate the nodeset attribute within the insert context. - rv = nsXFormsUtils::EvaluateXPath(nodesetExpr, contextNode, mElement, - nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, - getter_AddRefs(nodeset)); - NS_ENSURE_SUCCESS(rv, rv); - } - } else { - PRBool usesModelBinding; - rv = nsXFormsUtils::EvaluateNodeBinding(mElement, - nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, - EmptyString(), - EmptyString(), - nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, - getter_AddRefs(model), - getter_AddRefs(nodeset), - &usesModelBinding); - NS_ENSURE_SUCCESS(rv, rv); - - if (!model) - return NS_OK; - } - - if (nodeset) { - rv = nodeset->GetSnapshotLength(&nodesetSize); - NS_ENSURE_SUCCESS(rv, rv); - } - - // The insert action is terminated with no effect if the context attribute - // is not given and the Node Set Binding node-set is the empty node-set. - // - // The delete action is terminated with no effect if the Node Set Binding - // node-set is the empty node-set. - if (!nodeset || nodesetSize < 1) { - if (!mIsInsert || (mIsInsert && contextExpr.IsEmpty())) - return NS_OK; - } - - // - // Step 3 (Insert): Determine the origin node-set. - // - nsCOMPtr originNodeset; - nsCOMPtr originNode; - PRUint32 originNodesetSize = 0; - - if (mIsInsert) { - // If the origin attribute is not given and the Node Set Binding node-set - // is empty, then the origin node-set is the empty node-set. Otherwise, - // if the origin attribute is not given, then the origin node-set consists - // of the last node of the Node Set Binding node-set (which we will obtain - // just before performing the insert). + // - // If the origin attribute is given, the origin node-set is the result of - // the evaluation of the origin attribute in the insert context. - nsAutoString origin; - mElement->GetAttribute(NS_LITERAL_STRING("origin"), origin); - - if (!origin.IsEmpty()) { - rv = nsXFormsUtils::EvaluateXPath(origin, contextNode, mElement, - nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, - getter_AddRefs(originNodeset)); - NS_ENSURE_SUCCESS(rv, rv); - - // The insert action is terminated with no effect if the origin node-set - // is the empty node-set. - if (!originNodeset) - return NS_OK; - - rv = originNodeset->GetSnapshotLength(&originNodesetSize); - NS_ENSURE_SUCCESS(rv, rv); - - // The insert action is terminated with no effect if the origin node-set - // is the empty node-set. - if (originNodesetSize < 1) - return NS_OK; - - // Context Info: 'origin-nodes' - nsCOMPtr contextInfo = - new nsXFormsContextInfo(mElement); - NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); - contextInfo->SetNodesetValue("origin-nodes", originNodeset); - mContextInfo.AppendObject(contextInfo); - } - } - - // - // Step 4 (Insert), Step 3 (Delete): - // Determine the insert/delete location node. - // - // Insert: If the Node Set Binding node-set is not specified or empty, the - // insert location node is the insert context node. Otherwise, if the at - // attribute is not given, then the insert location node is the last node - // of the Node Set Binding node-set. Otherwise, an insert location node is - // determined from the at attribute. - // - // Delete: If the at attribute is not specified, there is no delete location. - // Otherwise, the delete location is determined by evaluating the XPath - // expression specified by the at attribute. - // - - nsCOMPtr locationNode; - PRUint32 atInt = 0; - double atDoub = 0; - - nsAutoString atExpr; - mElement->GetAttribute(NS_LITERAL_STRING("at"), atExpr); - - if (mIsInsert) { - if (!nodeset || nodesetSize < 1) { - // The insert location node is the insert context node. - locationNode = contextNode; - } else if (atExpr.IsEmpty()) { - // The insert location node is the last node of the Node Set Binding - // node-set. - nodeset->SnapshotItem(nodesetSize - 1, getter_AddRefs(locationNode)); - NS_ENSURE_STATE(locationNode); - } - } - - if (!locationNode) { - // For insert, we have a nodeset and got past the special cases of an empty - // nodeset or no @at expression so the insert location node is determined by - // @at. + // Step 2 (Insert or Delete): Determine the node-set binding. // - // For delete, the delete location is determined by the @at expression if - // present; otherwise there is no delete location and each node in the - // Node Set Binding node-set is deleted, unless the node is the root - // document element of an instance. - if (!atExpr.IsEmpty()) { - // The evaluation context node is the first node in document order of - // the Node Set Binding node-set. - nsCOMPtr evalContextNode; - nodeset->SnapshotItem(0, getter_AddRefs(evalContextNode)); - - // The context size is the size of the Node Set Binding node-set and - // the context position is 1. - nsCOMPtr xpRes; - rv = nsXFormsUtils::EvaluateXPath(atExpr, evalContextNode, mElement, - nsIDOMXPathResult::NUMBER_TYPE, - getter_AddRefs(xpRes), 1, nodesetSize); - - if (xpRes) { - rv = xpRes->GetNumberValue(&atDoub); + // If the bind attribute is present, it directly determines the Node Set + // Binding node-set. If a nodeset attribute is present, it is evaluated + // within the context to determine the Node Set Binding node-set. + // + // A NodeSet binding attribute (@bind or @nodeset) is required unless + // the context attribute is present. + // + nsCOMPtr nodeset; + PRUint32 nodesetSize = 0; + nsAutoString nodesetExpr; + + if (bindExpr.IsEmpty()) { + element->GetAttribute(NS_LITERAL_STRING("nodeset"), nodesetExpr); + if (!nodesetExpr.IsEmpty()) { + // Evaluate the nodeset attribute within the insert context. + rv = nsXFormsUtils::EvaluateXPath(nodesetExpr, contextNode, element, + nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, + getter_AddRefs(nodeset)); NS_ENSURE_SUCCESS(rv, rv); } - - // Determine the insert/delete location. - if (atDoub < 1) { - atInt = 1; - } else { - // If the location is greater than the nodeset size or NaN, - // the location is the end of the nodeset. - // XXX: Need to check for NaN but isnan() is not portable. - atInt = (PRInt32) floor(atDoub+0.5); - if (atInt > nodesetSize) - atInt = nodesetSize; - } - - // The location node is the node in the Node Set Binding node-set at - // the position given by the location. - nodeset->SnapshotItem(atInt - 1, getter_AddRefs(locationNode)); - NS_ENSURE_STATE(locationNode); - } - } - - // Context Info: 'insert-location-node' or 'delete-location' - nsCOMPtr contextInfo; - if (mIsInsert) { - contextInfo = new nsXFormsContextInfo(mElement); - NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); - contextInfo->SetNodeValue("insert-location-node", locationNode); - mContextInfo.AppendObject(contextInfo); - } else { - contextInfo = new nsXFormsContextInfo(mElement); - NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); - contextInfo->SetNumberValue("delete-location", atInt); - mContextInfo.AppendObject(contextInfo); - } - - // - // Step 5 (Insert): Each node in the origin node-set is cloned in the - // order it appears in the origin node-set. If the origin node-set is empty - // (Step 3), the origin node-set consists of the last node of the Node Set - // Binding node-set. - // - // The clones are deep copies of the original nodes except the contents of - // nodes of type xsd:ID are modified to remain as unique values in the - // instance data after the clones are inserted. - // - // XXX: Need to modify the contents of nodes of type xsd:ID to remain - // unique. - - nsCOMArray cloneNodes; - nsCOMPtr cloneNodeset; - PRUint32 cloneNodesetSize = 0; - - if (mIsInsert) { - nsCOMPtr prototypeNode, newNode; - PRUint32 cloneIndex; - - // Get prototype node(s) and clone. - if (originNodesetSize < 1) { - // Origin nodeset is empty. Clone the last node of nodeset. - cloneNodeset = nodeset; - cloneNodesetSize = nodesetSize; - cloneIndex = nodesetSize - 1; } else { - // Clone all the nodes in the origin node-set. - cloneNodeset = originNodeset; - cloneNodesetSize = originNodesetSize; - cloneIndex = 0; - } - // Context Info: 'inserted-nodes' - nsCOMPtr contextInfo = - new nsXFormsContextInfo(mElement); - NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); - contextInfo->SetNodesetValue("inserted-nodes", cloneNodeset); - mContextInfo.AppendObject(contextInfo); - - cloneNodeset->SnapshotItem(cloneIndex, getter_AddRefs(prototypeNode)); - NS_ENSURE_STATE(prototypeNode); - - // The prototypeNode (node to be cloned) and the locationNode (node to - // which the clone will be inserted) may belong to different instances. - nsCOMPtr originDoc, locationDoc; - prototypeNode->GetOwnerDocument(getter_AddRefs(originDoc)); - NS_ENSURE_STATE(originDoc); - locationNode->GetOwnerDocument(getter_AddRefs(locationDoc)); - NS_ENSURE_STATE(locationDoc); - - while ((cloneIndex < cloneNodesetSize) && prototypeNode) { - if (!SameCOMIdentity(originDoc, locationDoc)) { - locationDoc->ImportNode(prototypeNode, PR_TRUE, getter_AddRefs(newNode)); - } else { - prototypeNode->CloneNode(PR_TRUE, getter_AddRefs(newNode)); - } - NS_ENSURE_STATE(newNode); - cloneNodes.AppendObject(newNode); - - // Get the next node in the node-set. - ++cloneIndex; - cloneNodeset->SnapshotItem(cloneIndex, getter_AddRefs(prototypeNode)); - } - } - - // - // Step 6 and 7 (Insert): Determine the target location (Steps 6a-d) and - // insert all of the nodes that were cloned in Step 5. - // - // Step 4 (Delete): Delete the nodes. - // - - nsCOMPtr locationDoc; - nsCOMPtr locationDocElement; - nsCOMPtr parentNode, newNode, resNode, instNode; - if (mIsInsert) { - // The cloned node or nodes are inserted in the order they were cloned at - // their target location depending on their node type. - nsCOMPtr newNode; - - for (PRInt32 i = 0; i < cloneNodes.Count(); ++i) { - // Node to be inserted. - newNode = cloneNodes[i]; - - // Get the node type of the insert node and location node. - PRUint16 newNodeType, locationNodeType; - newNode->GetNodeType(&newNodeType); - locationNode->GetNodeType(&locationNodeType); - - // Step 6a - If the Node Set Binding node-set is not specified or empty - // OR Step 6b - If the Node Set Binding node-set is specified and not - // empty and the type of the cloned node is different from the type of - // the insert location node, the target location depends on the node - // type of the cloned node. - // - // If the cloned node is an attribute, then the target location is before - // the first attribute of the insert location node. If the cloned node is - // not an attribute, then the target location is before the first child - // of the insert location node. - if ((!nodeset || nodesetSize < 1) || - (nodeset && nodesetSize > 0 && newNodeType != locationNodeType)) { - Location location = eLocation_Before; - if (newNodeType != nsIDOMNode::ATTRIBUTE_NODE) { - // Target location is before the first child of location node. If the - // location node is empty (has no children), it remains the location - // node and the new node will become the first child of the location - // node. - nsCOMPtr targetNode; - locationNode->GetFirstChild(getter_AddRefs(targetNode)); - if (targetNode) { - locationNode.swap(targetNode); - } else { - // New node will become first child of locationNode. - location = eLocation_FirstChild; - } - } - InsertNode(locationNode, newNode, location, getter_AddRefs(resNode)); - } else { - // Step 6c - If insert location node is the root element of an - // instance, then that instance root element location is the target - // location and the cloned node replaces the instance element. If - // there is more than one cloned node to insert, only the first node - // that does not cause a conflict is considered. - // - locationNode->GetOwnerDocument(getter_AddRefs(locationDoc)); - NS_ENSURE_STATE(locationDoc); - locationDoc->GetDocumentElement(getter_AddRefs(locationDocElement)); - - if (SameCOMIdentity(locationNode, locationDocElement)) { - // Step 7 - Replace the instance element with the first element - // node of the cloned node(s). - nsCOMPtr insertNode; - GetFirstNodeOfType(&cloneNodes, nsIDOMNode::ELEMENT_NODE, - getter_AddRefs(insertNode)); - if (insertNode) { - nsCOMPtr child; - locationDoc->RemoveChild(locationNode, getter_AddRefs(child)); - locationDoc->AppendChild(insertNode, getter_AddRefs(resNode)); - // Done...because we only consider the first node that does - // not cause a conflict. - break; - } - } else { - // Step 6d - the target location is immediately before or after the - // insert location node, based on the position attribute setting or - // its default. - PRBool insertAfter = PR_TRUE; - nsAutoString position; - mElement->GetAttribute(NS_LITERAL_STRING("position"), position); - if (!position.IsEmpty()) { - if (position.EqualsLiteral("before")) { - insertAfter = PR_FALSE; - } else if (!position.EqualsLiteral("after")) { - // This is not a valid document... - return NS_ERROR_FAILURE; - } - } - // Context Info: 'position'. - nsCOMPtr contextInfo = - new nsXFormsContextInfo(mElement); - NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); - contextInfo->SetStringValue("position", position); - mContextInfo.AppendObject(contextInfo); - - InsertNode(locationNode, newNode, - insertAfter ? eLocation_After: eLocation_Before, - getter_AddRefs(resNode)); - } - } - } - rv = nsXFormsUtils::GetInstanceNodeForData(resNode, getter_AddRefs(instNode)); + PRBool usesModelBinding; + rv = nsXFormsUtils::EvaluateNodeBinding(element, + nsXFormsUtils::ELEMENT_WITH_MODEL_ATTR, + EmptyString(), + EmptyString(), + nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, + getter_AddRefs(model), + getter_AddRefs(nodeset), + &usesModelBinding); NS_ENSURE_SUCCESS(rv, rv); - - // Step 8: Set indexes for repeats - rv = RefreshRepeats(&cloneNodes); - NS_ENSURE_SUCCESS(rv, rv); - - } else { - // Delete - // If there is no delete location, each node in the Node Set Binding - // node-set is deleted, unless the node is the root document element of an - // instance. - // - // If there is a delete location, the node at the delete location in the - // Node Set Binding node-set is deleted, unless the node is the root - // document element of an instance. - PRBool didDelete = PR_FALSE; - - PRUint32 deleteIndex, deleteCount; - - if (!locationNode) { - // Delete all the nodes in the node-set. - deleteIndex = 0; - deleteCount = nodesetSize; - } else { - // Delete the node at the delete location. - deleteIndex = atInt - 1; - deleteCount = atInt; + + if (!model) + return NS_OK; } - // Context Info: 'deleted-nodes' - nsCOMPtr contextInfo = - new nsXFormsContextInfo(mElement); - NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); - contextInfo->SetNodesetValue("deleted-nodes", nodeset); - mContextInfo.AppendObject(contextInfo); - - nodeset->SnapshotItem(deleteIndex, getter_AddRefs(locationNode)); - NS_ENSURE_STATE(locationNode); - - locationNode->GetOwnerDocument(getter_AddRefs(locationDoc)); - NS_ENSURE_STATE(locationDoc); - - rv = nsXFormsUtils::GetInstanceNodeForData(locationNode, getter_AddRefs(instNode)); - NS_ENSURE_SUCCESS(rv, rv); - - locationDoc->GetDocumentElement(getter_AddRefs(locationDocElement)); - while ((deleteIndex < deleteCount) && locationNode) { - // Delete the node(s) unless the delete location is the root document - // element of an instance. - PRUint16 locationNodeType; - locationNode->GetNodeType(&locationNodeType); - if (locationNodeType == nsIDOMNode::ATTRIBUTE_NODE) { - nsCOMPtr ownerElement; - nsCOMPtr attrNode(do_QueryInterface(locationNode)); - attrNode->GetOwnerElement(getter_AddRefs(ownerElement)); - NS_ENSURE_STATE(ownerElement); - - nsCOMPtr resAttr; - ownerElement->RemoveAttributeNode(attrNode, getter_AddRefs(resAttr)); - resNode = locationNode; - - // Deleted at least one node so delete will not terminate. - didDelete = PR_TRUE; - } else { - if (!SameCOMIdentity(locationNode, locationDocElement)) { - locationNode->GetParentNode(getter_AddRefs(parentNode)); - NS_ENSURE_STATE(parentNode); - - rv = parentNode->RemoveChild(locationNode, getter_AddRefs(resNode)); + + if (nodeset) { + rv = nodeset->GetSnapshotLength(&nodesetSize); + NS_ENSURE_SUCCESS(rv, rv); + } + + // The insert action is terminated with no effect if the context attribute + // is not given and the Node Set Binding node-set is the empty node-set. + // + // The delete action is terminated with no effect if the Node Set Binding + // node-set is the empty node-set. + if (!nodeset || nodesetSize < 1) { + if (!mIsInsert || (mIsInsert && contextExpr.IsEmpty())) + return NS_OK; + } + + // + // Step 3 (Insert): Determine the origin node-set. + // + nsCOMPtr originNodeset; + nsCOMPtr originNode; + PRUint32 originNodesetSize = 0; + + if (mIsInsert) { + // If the origin attribute is not given and the Node Set Binding node-set + // is empty, then the origin node-set is the empty node-set. Otherwise, + // if the origin attribute is not given, then the origin node-set consists + // of the last node of the Node Set Binding node-set (which we will obtain + // just before performing the insert). + // + // If the origin attribute is given, the origin node-set is the result of + // the evaluation of the origin attribute in the insert context. + nsAutoString origin; + element->GetAttribute(NS_LITERAL_STRING("origin"), origin); + + if (!origin.IsEmpty()) { + rv = nsXFormsUtils::EvaluateXPath(origin, contextNode, element, + nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE, + getter_AddRefs(originNodeset)); + NS_ENSURE_SUCCESS(rv, rv); + + // The insert action is terminated with no effect if the origin node-set + // is the empty node-set. + if (!originNodeset) + return NS_OK; + + rv = originNodeset->GetSnapshotLength(&originNodesetSize); + NS_ENSURE_SUCCESS(rv, rv); + + // The insert action is terminated with no effect if the origin node-set + // is the empty node-set. + if (originNodesetSize < 1) + return NS_OK; + + // Context Info: 'origin-nodes' + nsCOMPtr contextInfo = + new nsXFormsContextInfo(element); + NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); + contextInfo->SetNodesetValue("origin-nodes", originNodeset); + mContextInfo.AppendObject(contextInfo); + } + } + + // + // Step 4 (Insert), Step 3 (Delete): + // Determine the insert/delete location node. + // + // Insert: If the Node Set Binding node-set is not specified or empty, the + // insert location node is the insert context node. Otherwise, if the at + // attribute is not given, then the insert location node is the last node + // of the Node Set Binding node-set. Otherwise, an insert location node is + // determined from the at attribute. + // + // Delete: If the at attribute is not specified, there is no delete location. + // Otherwise, the delete location is determined by evaluating the XPath + // expression specified by the at attribute. + // + + nsCOMPtr locationNode; + PRUint32 atInt = 0; + double atDoub = 0; + + nsAutoString atExpr; + element->GetAttribute(NS_LITERAL_STRING("at"), atExpr); + + if (mIsInsert) { + if (!nodeset || nodesetSize < 1) { + // The insert location node is the insert context node. + locationNode = contextNode; + } else if (atExpr.IsEmpty()) { + // The insert location node is the last node of the Node Set Binding + // node-set. + nodeset->SnapshotItem(nodesetSize - 1, getter_AddRefs(locationNode)); + NS_ENSURE_STATE(locationNode); + } + } + + if (!locationNode) { + // For insert, we have a nodeset and got past the special cases of an empty + // nodeset or no @at expression so the insert location node is determined by + // @at. + // + // For delete, the delete location is determined by the @at expression if + // present; otherwise there is no delete location and each node in the + // Node Set Binding node-set is deleted, unless the node is the root + // document element of an instance. + if (!atExpr.IsEmpty()) { + // The evaluation context node is the first node in document order of + // the Node Set Binding node-set. + nsCOMPtr evalContextNode; + nodeset->SnapshotItem(0, getter_AddRefs(evalContextNode)); + + // The context size is the size of the Node Set Binding node-set and + // the context position is 1. + nsCOMPtr xpRes; + rv = nsXFormsUtils::EvaluateXPath(atExpr, evalContextNode, element, + nsIDOMXPathResult::NUMBER_TYPE, + getter_AddRefs(xpRes), 1, nodesetSize); + + if (xpRes) { + rv = xpRes->GetNumberValue(&atDoub); NS_ENSURE_SUCCESS(rv, rv); - + } + + // Determine the insert/delete location. + if (atDoub < 1) { + atInt = 1; + } else { + // If the location is greater than the nodeset size or NaN, + // the location is the end of the nodeset. + // XXX: Need to check for NaN but isnan() is not portable. + atInt = (PRInt32) floor(atDoub+0.5); + if (atInt > nodesetSize) + atInt = nodesetSize; + } + + // The location node is the node in the Node Set Binding node-set at + // the position given by the location. + nodeset->SnapshotItem(atInt - 1, getter_AddRefs(locationNode)); + NS_ENSURE_STATE(locationNode); + } + } + + // Context Info: 'insert-location-node' or 'delete-location' + nsCOMPtr contextInfo; + if (mIsInsert) { + contextInfo = new nsXFormsContextInfo(element); + NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); + contextInfo->SetNodeValue("insert-location-node", locationNode); + mContextInfo.AppendObject(contextInfo); + } else { + contextInfo = new nsXFormsContextInfo(element); + NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); + contextInfo->SetNumberValue("delete-location", atInt); + mContextInfo.AppendObject(contextInfo); + } + + // + // Step 5 (Insert): Each node in the origin node-set is cloned in the + // order it appears in the origin node-set. If the origin node-set is empty + // (Step 3), the origin node-set consists of the last node of the Node Set + // Binding node-set. + // + // The clones are deep copies of the original nodes except the contents of + // nodes of type xsd:ID are modified to remain as unique values in the + // instance data after the clones are inserted. + // + // XXX: Need to modify the contents of nodes of type xsd:ID to remain + // unique. + + nsCOMArray cloneNodes; + nsCOMPtr cloneNodeset; + PRUint32 cloneNodesetSize = 0; + + if (mIsInsert) { + nsCOMPtr prototypeNode, newNode; + PRUint32 cloneIndex; + + // Get prototype node(s) and clone. + if (originNodesetSize < 1) { + // Origin nodeset is empty. Clone the last node of nodeset. + cloneNodeset = nodeset; + cloneNodesetSize = nodesetSize; + cloneIndex = nodesetSize - 1; + } else { + // Clone all the nodes in the origin node-set. + cloneNodeset = originNodeset; + cloneNodesetSize = originNodesetSize; + cloneIndex = 0; + } + // Context Info: 'inserted-nodes' + nsCOMPtr contextInfo = + new nsXFormsContextInfo(element); + NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); + contextInfo->SetNodesetValue("inserted-nodes", cloneNodeset); + mContextInfo.AppendObject(contextInfo); + + cloneNodeset->SnapshotItem(cloneIndex, getter_AddRefs(prototypeNode)); + NS_ENSURE_STATE(prototypeNode); + + // The prototypeNode (node to be cloned) and the locationNode (node to + // which the clone will be inserted) may belong to different instances. + nsCOMPtr originDoc, locationDoc; + prototypeNode->GetOwnerDocument(getter_AddRefs(originDoc)); + NS_ENSURE_STATE(originDoc); + locationNode->GetOwnerDocument(getter_AddRefs(locationDoc)); + NS_ENSURE_STATE(locationDoc); + + while ((cloneIndex < cloneNodesetSize) && prototypeNode) { + if (!SameCOMIdentity(originDoc, locationDoc)) { + locationDoc->ImportNode(prototypeNode, PR_TRUE, getter_AddRefs(newNode)); + } else { + prototypeNode->CloneNode(PR_TRUE, getter_AddRefs(newNode)); + } + NS_ENSURE_STATE(newNode); + cloneNodes.AppendObject(newNode); + + // Get the next node in the node-set. + ++cloneIndex; + cloneNodeset->SnapshotItem(cloneIndex, getter_AddRefs(prototypeNode)); + } + } + + // + // Step 6 and 7 (Insert): Determine the target location (Steps 6a-d) and + // insert all of the nodes that were cloned in Step 5. + // + // Step 4 (Delete): Delete the nodes. + // + + nsCOMPtr locationDoc; + nsCOMPtr locationDocElement; + nsCOMPtr parentNode, newNode, resNode, instNode; + if (mIsInsert) { + // The cloned node or nodes are inserted in the order they were cloned at + // their target location depending on their node type. + nsCOMPtr newNode; + + for (PRInt32 i = 0; i < cloneNodes.Count(); ++i) { + // Node to be inserted. + newNode = cloneNodes[i]; + + // Get the node type of the insert node and location node. + PRUint16 newNodeType, locationNodeType; + newNode->GetNodeType(&newNodeType); + locationNode->GetNodeType(&locationNodeType); + + // Step 6a - If the Node Set Binding node-set is not specified or empty + // OR Step 6b - If the Node Set Binding node-set is specified and not + // empty and the type of the cloned node is different from the type of + // the insert location node, the target location depends on the node + // type of the cloned node. + // + // If the cloned node is an attribute, then the target location is before + // the first attribute of the insert location node. If the cloned node is + // not an attribute, then the target location is before the first child + // of the insert location node. + if ((!nodeset || nodesetSize < 1) || + (nodeset && nodesetSize > 0 && newNodeType != locationNodeType)) { + Location location = eLocation_Before; + if (newNodeType != nsIDOMNode::ATTRIBUTE_NODE) { + // Target location is before the first child of location node. If the + // location node is empty (has no children), it remains the location + // node and the new node will become the first child of the location + // node. + nsCOMPtr targetNode; + locationNode->GetFirstChild(getter_AddRefs(targetNode)); + if (targetNode) { + locationNode.swap(targetNode); + } else { + // New node will become first child of locationNode. + location = eLocation_FirstChild; + } + } + InsertNode(locationNode, newNode, location, getter_AddRefs(resNode)); + } else { + // Step 6c - If insert location node is the root element of an + // instance, then that instance root element location is the target + // location and the cloned node replaces the instance element. If + // there is more than one cloned node to insert, only the first node + // that does not cause a conflict is considered. + // + locationNode->GetOwnerDocument(getter_AddRefs(locationDoc)); + NS_ENSURE_STATE(locationDoc); + locationDoc->GetDocumentElement(getter_AddRefs(locationDocElement)); + + if (SameCOMIdentity(locationNode, locationDocElement)) { + // Step 7 - Replace the instance element with the first element + // node of the cloned node(s). + nsCOMPtr insertNode; + GetFirstNodeOfType(&cloneNodes, nsIDOMNode::ELEMENT_NODE, + getter_AddRefs(insertNode)); + if (insertNode) { + nsCOMPtr child; + locationDoc->RemoveChild(locationNode, getter_AddRefs(child)); + locationDoc->AppendChild(insertNode, getter_AddRefs(resNode)); + // Done...because we only consider the first node that does + // not cause a conflict. + break; + } + } else { + // Step 6d - the target location is immediately before or after the + // insert location node, based on the position attribute setting or + // its default. + PRBool insertAfter = PR_TRUE; + nsAutoString position; + element->GetAttribute(NS_LITERAL_STRING("position"), position); + if (!position.IsEmpty()) { + if (position.EqualsLiteral("before")) { + insertAfter = PR_FALSE; + } else if (!position.EqualsLiteral("after")) { + // This is not a valid document... + return NS_ERROR_FAILURE; + } + } + // Context Info: 'position'. + nsCOMPtr contextInfo = + new nsXFormsContextInfo(element); + NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); + contextInfo->SetStringValue("position", position); + mContextInfo.AppendObject(contextInfo); + + InsertNode(locationNode, newNode, + insertAfter ? eLocation_After: eLocation_Before, + getter_AddRefs(resNode)); + } + } + } + rv = nsXFormsUtils::GetInstanceNodeForData(resNode, getter_AddRefs(instNode)); + NS_ENSURE_SUCCESS(rv, rv); + + // Step 8: Set indexes for repeats + rv = RefreshRepeats(&cloneNodes); + NS_ENSURE_SUCCESS(rv, rv); + + } else { + // Delete + // If there is no delete location, each node in the Node Set Binding + // node-set is deleted, unless the node is the root document element of an + // instance. + // + // If there is a delete location, the node at the delete location in the + // Node Set Binding node-set is deleted, unless the node is the root + // document element of an instance. + PRBool didDelete = PR_FALSE; + + PRUint32 deleteIndex, deleteCount; + + if (!locationNode) { + // Delete all the nodes in the node-set. + deleteIndex = 0; + deleteCount = nodesetSize; + } else { + // Delete the node at the delete location. + deleteIndex = atInt - 1; + deleteCount = atInt; + } + // Context Info: 'deleted-nodes' + nsCOMPtr contextInfo = + new nsXFormsContextInfo(element); + NS_ENSURE_TRUE(contextInfo, NS_ERROR_OUT_OF_MEMORY); + contextInfo->SetNodesetValue("deleted-nodes", nodeset); + mContextInfo.AppendObject(contextInfo); + + nodeset->SnapshotItem(deleteIndex, getter_AddRefs(locationNode)); + NS_ENSURE_STATE(locationNode); + + locationNode->GetOwnerDocument(getter_AddRefs(locationDoc)); + NS_ENSURE_STATE(locationDoc); + + rv = nsXFormsUtils::GetInstanceNodeForData(locationNode, getter_AddRefs(instNode)); + NS_ENSURE_SUCCESS(rv, rv); + + locationDoc->GetDocumentElement(getter_AddRefs(locationDocElement)); + while ((deleteIndex < deleteCount) && locationNode) { + // Delete the node(s) unless the delete location is the root document + // element of an instance. + PRUint16 locationNodeType; + locationNode->GetNodeType(&locationNodeType); + if (locationNodeType == nsIDOMNode::ATTRIBUTE_NODE) { + nsCOMPtr ownerElement; + nsCOMPtr attrNode(do_QueryInterface(locationNode)); + attrNode->GetOwnerElement(getter_AddRefs(ownerElement)); + NS_ENSURE_STATE(ownerElement); + + nsCOMPtr resAttr; + ownerElement->RemoveAttributeNode(attrNode, getter_AddRefs(resAttr)); + resNode = locationNode; + // Deleted at least one node so delete will not terminate. didDelete = PR_TRUE; + } else { + if (!SameCOMIdentity(locationNode, locationDocElement)) { + locationNode->GetParentNode(getter_AddRefs(parentNode)); + NS_ENSURE_STATE(parentNode); + + rv = parentNode->RemoveChild(locationNode, getter_AddRefs(resNode)); + NS_ENSURE_SUCCESS(rv, rv); + + // Deleted at least one node so delete will not terminate. + didDelete = PR_TRUE; + } } + // Get the next node in the node-set. + ++deleteIndex; + nodeset->SnapshotItem(deleteIndex, getter_AddRefs(locationNode)); } - // Get the next node in the node-set. - ++deleteIndex; - nodeset->SnapshotItem(deleteIndex, getter_AddRefs(locationNode)); + + // The delete action is terminated with no effect if no node is deleted. + if (!didDelete) + return NS_OK; + } + NS_ENSURE_STATE(resNode); + + // Dispatch xforms-insert/delete event to the instance node we have modified + // data for + rv = nsXFormsUtils::DispatchEvent(instNode, + mIsInsert ? eEvent_Insert : eEvent_Delete, + nsnull, nsnull, &mContextInfo); + NS_ENSURE_SUCCESS(rv, rv); + + // Dispatch refreshing events to the model + if (aParentAction) { + aParentAction->SetRebuild(model, PR_TRUE); + aParentAction->SetRecalculate(model, PR_TRUE); + aParentAction->SetRevalidate(model, PR_TRUE); + aParentAction->SetRefresh(model, PR_TRUE); + } else { + rv = model->RequestRebuild(); + NS_ENSURE_SUCCESS(rv, rv); + rv = model->RequestRecalculate(); + NS_ENSURE_SUCCESS(rv, rv); + rv = model->RequestRevalidate(); + NS_ENSURE_SUCCESS(rv, rv); + rv = model->RequestRefresh(); + NS_ENSURE_SUCCESS(rv, rv); } - // The delete action is terminated with no effect if no node is deleted. - if (!didDelete) + // Repeat this action if it can iterate and if it uses the `while` + // attribute (the expression of which must have evaluated to true to + // arrive here). + if (!CanIterate() || !usesWhile) { return NS_OK; - } - NS_ENSURE_STATE(resNode); + } - // Dispatch xforms-insert/delete event to the instance node we have modified - // data for - rv = nsXFormsUtils::DispatchEvent(instNode, - mIsInsert ? eEvent_Insert : eEvent_Delete, - nsnull, nsnull, &mContextInfo); - NS_ENSURE_SUCCESS(rv, rv); + // See if we've exceeded our time limit, and if so, prompt the user to + // determine if she wants to cancel the loop. + LL_SUB(runTime, PR_Now(), start); + if (microseconds <= 0 || runTime < microseconds) { + continue; + } - // Dispatch refreshing events to the model - if (aParentAction) { - aParentAction->SetRebuild(model, PR_TRUE); - aParentAction->SetRecalculate(model, PR_TRUE); - aParentAction->SetRevalidate(model, PR_TRUE); - aParentAction->SetRefresh(model, PR_TRUE); - } else { - rv = model->RequestRebuild(); - NS_ENSURE_SUCCESS(rv, rv); - rv = model->RequestRecalculate(); - NS_ENSURE_SUCCESS(rv, rv); - rv = model->RequestRevalidate(); - NS_ENSURE_SUCCESS(rv, rv); - rv = model->RequestRefresh(); - NS_ENSURE_SUCCESS(rv, rv); - } + // The remaining part of the loop prompts the user about cancelling the + // loop, and is only executed if we've gone over the time limit. + PRBool stopWaiting = nsXFormsUtils::AskStopWaiting(element); - // Repeat this action if it uses the `while` attribute (which must have - // evaluated to true to arrive here). - if (usesWhile) { - return HandleAction(aEvent, aParentAction); + if (stopWaiting) { + // Stop the loop + return NS_OK; + } else { + start = PR_Now(); + } } return NS_OK; diff --git a/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp b/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp index 398c09fc554..6f636967b37 100644 --- a/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsInstanceElement.cpp @@ -62,7 +62,7 @@ NS_IMPL_ISUPPORTS_INHERITED6(nsXFormsInstanceElement, nsIChannelEventSink) nsXFormsInstanceElement::nsXFormsInstanceElement() - : nsXFormsStubElement() + : mElement(nsnull) , mInitialized(PR_FALSE) , mLazy(PR_FALSE) { diff --git a/mozilla/extensions/xforms/nsXFormsInstanceElement.h b/mozilla/extensions/xforms/nsXFormsInstanceElement.h index 1e1916a2837..2f5a92bec3e 100644 --- a/mozilla/extensions/xforms/nsXFormsInstanceElement.h +++ b/mozilla/extensions/xforms/nsXFormsInstanceElement.h @@ -103,6 +103,7 @@ private: nsCOMPtr mDocument; nsCOMPtr mOriginalDocument; + nsIDOMElement *mElement; nsCOMPtr mListener; PRBool mInitialized; PRBool mLazy; diff --git a/mozilla/extensions/xforms/nsXFormsLoadElement.cpp b/mozilla/extensions/xforms/nsXFormsLoadElement.cpp index f8dd48c383a..c6adf2a8032 100644 --- a/mozilla/extensions/xforms/nsXFormsLoadElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsLoadElement.cpp @@ -49,13 +49,11 @@ class nsXFormsLoadElement : public nsXFormsActionModuleBase { public: nsXFormsLoadElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsLoadElement::nsXFormsLoadElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsLoadElement::nsXFormsLoadElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsMessageElement.cpp b/mozilla/extensions/xforms/nsXFormsMessageElement.cpp index 0d09efb0dd0..de1a17cae83 100644 --- a/mozilla/extensions/xforms/nsXFormsMessageElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsMessageElement.cpp @@ -104,10 +104,12 @@ class nsXFormsEventListener; * @see http://www.w3.org/TR/xforms/slice10.html#action-info */ class nsXFormsMessageElement : public nsXFormsDelegateStub, + public nsIDOMEventListener, + public nsIXFormsActionModuleElement, public nsIStreamListener, public nsIInterfaceRequestor, public nsIChannelEventSink, - public nsXFormsActionModuleBase + public nsXFormsActionModuleHelper { public: NS_DECL_ISUPPORTS_INHERITED @@ -118,7 +120,6 @@ public: // nsIXTFElement overrides NS_IMETHOD OnCreated(nsIXTFElementWrapper *aWrapper); NS_IMETHOD WillChangeDocument(nsIDOMDocument *aNewDocument); - NS_IMETHOD DocumentChanged(nsIDOMDocument *aNewDocument); NS_IMETHOD OnDestroyed(); NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent); NS_IMETHOD WillChangeParent(nsIDOMElement *aNewParent); @@ -131,7 +132,11 @@ public: NS_DECL_NSISTREAMLISTENER NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIDOMEVENTLISTENER + NS_DECL_NSIXFORMSACTIONMODULEELEMENT + virtual nsIDOMElement* GetElement() { return mElement; } + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); // Start the timer, which is used to set the message visible void StartEphemeral(); // Set the message visible and start timer to hide it later. @@ -159,13 +164,9 @@ public: nsXFormsMessageElement(MessageType aType) : - nsXFormsDelegateStub(), nsXFormsActionModuleBase(PR_TRUE), mType(aType), mPosX(-1), mPosY(-1), mDocument(nsnull), mStopType(eStopType_None), mSrcAttrText(""), mDoneAddingChildren(PR_FALSE) {} -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); private: nsresult HandleEphemeralMessage(nsIDOMDocument* aDoc, nsIDOMEvent* aEvent); nsresult HandleModalAndModelessMessage(nsIDOMDocument* aDoc, nsAString& aLevel); @@ -275,20 +276,6 @@ nsXFormsMessageElement::WillChangeDocument(nsIDOMDocument *aNewDocument) return nsXFormsDelegateStub::WillChangeDocument(aNewDocument); } -/** - * The `nsXFormsMessageElement` class inherits from both - * `nsXFormsActionModuleBase` and `nsXFormsControlStub`, which both - * implement a `DocumentChanged` method. The method defined by - * `nsXFormsControlStub` completely subsumes that of - * `nsXFormsActionModuleBase`, so we delegate to the former method as the - * implementation of this method. - */ -NS_IMETHODIMP -nsXFormsMessageElement::DocumentChanged(nsIDOMDocument *aNewDocument) -{ - return nsXFormsControlStub::DocumentChanged(aNewDocument); -} - NS_IMETHODIMP nsXFormsMessageElement::OnDestroyed() { @@ -467,6 +454,13 @@ nsXFormsMessageElement::DoneAddingChildren() return NS_OK; } +NS_IMETHODIMP +nsXFormsMessageElement::HandleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction) +{ + return nsXFormsActionModuleBase::DoHandleAction(this, aEvent, aParentAction); +} + nsresult nsXFormsMessageElement::HandleSingleAction(nsIDOMEvent *aEvent, nsIXFormsActionElement *aParentAction) @@ -1299,6 +1293,13 @@ nsXFormsMessageElement::SetContextInfo(const char *aName, const nsAString &aValu return NS_OK; } +NS_IMETHODIMP +nsXFormsMessageElement::GetCurrentEvent(nsIDOMEvent **aEvent) +{ + NS_IF_ADDREF(*aEvent = mCurrentEvent); + return NS_OK; +} + NS_HIDDEN_(nsresult) NS_NewXFormsMessageElement(nsIXTFElement **aResult) { diff --git a/mozilla/extensions/xforms/nsXFormsModelElement.cpp b/mozilla/extensions/xforms/nsXFormsModelElement.cpp index 27c839dd10f..c2c80a014f7 100644 --- a/mozilla/extensions/xforms/nsXFormsModelElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsModelElement.cpp @@ -642,7 +642,7 @@ nsXFormsModelElement::CancelPostRefresh(nsIXFormsControl* aControl) } nsXFormsModelElement::nsXFormsModelElement() - : nsXFormsStubElement(), + : mElement(nsnull), mFormControls(nsnull, &mControlListHash), mSchemaCount(0), mSchemaTotal(0), diff --git a/mozilla/extensions/xforms/nsXFormsModelElement.h b/mozilla/extensions/xforms/nsXFormsModelElement.h index b4c4c7e6d31..2ce6de6759a 100644 --- a/mozilla/extensions/xforms/nsXFormsModelElement.h +++ b/mozilla/extensions/xforms/nsXFormsModelElement.h @@ -469,6 +469,7 @@ private: */ nsresult SetContextInfo(const char *aName, const nsAString &aValue); + nsIDOMElement *mElement; nsCOMPtr mSchemas; nsStringArray mPendingInlineSchemas; nsXFormsControlListItem mFormControls; diff --git a/mozilla/extensions/xforms/nsXFormsRebuildElement.cpp b/mozilla/extensions/xforms/nsXFormsRebuildElement.cpp index 637b0d56360..3ec1810e965 100644 --- a/mozilla/extensions/xforms/nsXFormsRebuildElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsRebuildElement.cpp @@ -43,13 +43,11 @@ class nsXFormsRebuildElement : public nsXFormsActionModuleBase { public: nsXFormsRebuildElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsRebuildElement::nsXFormsRebuildElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsRebuildElement::nsXFormsRebuildElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsRecalculateElement.cpp b/mozilla/extensions/xforms/nsXFormsRecalculateElement.cpp index cac91121297..33e6e9b34ac 100644 --- a/mozilla/extensions/xforms/nsXFormsRecalculateElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsRecalculateElement.cpp @@ -43,13 +43,11 @@ class nsXFormsRecalculateElement : public nsXFormsActionModuleBase { public: nsXFormsRecalculateElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsRecalculateElement::nsXFormsRecalculateElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsRecalculateElement::nsXFormsRecalculateElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsRefreshElement.cpp b/mozilla/extensions/xforms/nsXFormsRefreshElement.cpp index 6263c52e18f..0ee3cab6051 100644 --- a/mozilla/extensions/xforms/nsXFormsRefreshElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsRefreshElement.cpp @@ -43,13 +43,11 @@ class nsXFormsRefreshElement : public nsXFormsActionModuleBase { public: nsXFormsRefreshElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsRefreshElement::nsXFormsRefreshElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsRefreshElement::nsXFormsRefreshElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsResetElement.cpp b/mozilla/extensions/xforms/nsXFormsResetElement.cpp index 920759201e0..dc7851f96a6 100644 --- a/mozilla/extensions/xforms/nsXFormsResetElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsResetElement.cpp @@ -43,13 +43,11 @@ class nsXFormsResetElement : public nsXFormsActionModuleBase { public: nsXFormsResetElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsResetElement::nsXFormsResetElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsResetElement::nsXFormsResetElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsRevalidateElement.cpp b/mozilla/extensions/xforms/nsXFormsRevalidateElement.cpp index 83b0e5ae078..416e0b42764 100644 --- a/mozilla/extensions/xforms/nsXFormsRevalidateElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsRevalidateElement.cpp @@ -43,13 +43,11 @@ class nsXFormsRevalidateElement : public nsXFormsActionModuleBase { public: nsXFormsRevalidateElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsRevalidateElement::nsXFormsRevalidateElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsRevalidateElement::nsXFormsRevalidateElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsSendElement.cpp b/mozilla/extensions/xforms/nsXFormsSendElement.cpp index 2a066bfcd16..03942e68b8f 100644 --- a/mozilla/extensions/xforms/nsXFormsSendElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsSendElement.cpp @@ -45,13 +45,11 @@ class nsXFormsSendElement : public nsXFormsActionModuleBase { public: nsXFormsSendElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsSendElement::nsXFormsSendElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsSendElement::nsXFormsSendElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsSetFocusElement.cpp b/mozilla/extensions/xforms/nsXFormsSetFocusElement.cpp index d0bc8621e08..cd800305730 100644 --- a/mozilla/extensions/xforms/nsXFormsSetFocusElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsSetFocusElement.cpp @@ -46,13 +46,11 @@ class nsXFormsSetFocusElement : public nsXFormsActionModuleBase { public: nsXFormsSetFocusElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsSetFocusElement::nsXFormsSetFocusElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsSetFocusElement::nsXFormsSetFocusElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp b/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp index 4f0fd1a14af..f896b4a7f7e 100644 --- a/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsSetIndexElement.cpp @@ -61,13 +61,11 @@ class nsXFormsSetIndexElement : public nsXFormsActionModuleBase { public: nsXFormsSetIndexElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsSetIndexElement::nsXFormsSetIndexElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsSetIndexElement::nsXFormsSetIndexElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp b/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp index 61097a81598..b0c44951e5c 100644 --- a/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsSetValueElement.cpp @@ -51,13 +51,11 @@ class nsXFormsSetValueElement : public nsXFormsActionModuleBase { public: nsXFormsSetValueElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsSetValueElement::nsXFormsSetValueElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsSetValueElement::nsXFormsSetValueElement() { } diff --git a/mozilla/extensions/xforms/nsXFormsStubElement.h b/mozilla/extensions/xforms/nsXFormsStubElement.h index 247e9661c6b..cab2831c9ed 100644 --- a/mozilla/extensions/xforms/nsXFormsStubElement.h +++ b/mozilla/extensions/xforms/nsXFormsStubElement.h @@ -73,8 +73,6 @@ enum nsRepeatState { class nsXFormsStubElement : public nsIXTFElement { protected: - nsIDOMElement* mElement; - // We need a virtual destructor so that when a subclass does // NS_IMPL_ISUPPORTS_INHERITED, our Release() implementation calls the // derived class destructor. @@ -112,7 +110,6 @@ public: /** Constructor */ nsXFormsStubElement() : - mElement(nsnull), mRepeatState(eType_Unknown), mHasParent(PR_FALSE), mHasDoc(PR_FALSE) diff --git a/mozilla/extensions/xforms/nsXFormsSubmissionElement.h b/mozilla/extensions/xforms/nsXFormsSubmissionElement.h index eab26a3bbea..9a0ba67fc6d 100644 --- a/mozilla/extensions/xforms/nsXFormsSubmissionElement.h +++ b/mozilla/extensions/xforms/nsXFormsSubmissionElement.h @@ -86,7 +86,7 @@ public: NS_DECL_NSIHTTPHEADERVISITOR nsXFormsSubmissionElement() - : nsXFormsStubElement(), + : mElement(nsnull), mSubmissionActive(PR_FALSE), mIsReplaceInstance(PR_FALSE), mIsSOAPRequest(PR_FALSE), @@ -151,6 +151,7 @@ public: const nsCString &contentType); private: + nsIDOMElement* mElement; PRPackedBool mSubmissionActive; // Valid when mSubmissionActive == PR_TRUE PRPackedBool mIsReplaceInstance; diff --git a/mozilla/extensions/xforms/nsXFormsToggleElement.cpp b/mozilla/extensions/xforms/nsXFormsToggleElement.cpp index 0eeb5c7d0cd..07052417ef5 100644 --- a/mozilla/extensions/xforms/nsXFormsToggleElement.cpp +++ b/mozilla/extensions/xforms/nsXFormsToggleElement.cpp @@ -52,13 +52,11 @@ class nsXFormsToggleElement : public nsXFormsActionModuleBase { public: nsXFormsToggleElement(); -protected: - nsresult HandleSingleAction(nsIDOMEvent* aEvent, - nsIXFormsActionElement *aParentAction); + virtual nsresult HandleSingleAction(nsIDOMEvent* aEvent, + nsIXFormsActionElement *aParentAction); }; -nsXFormsToggleElement::nsXFormsToggleElement() : - nsXFormsActionModuleBase(PR_TRUE) +nsXFormsToggleElement::nsXFormsToggleElement() { }