XForms bug 294441 - fix model-construct-done processing. Patch by aaronr, r=smaug/me a=mkaply

git-svn-id: svn://10.0.0.236/trunk@175315 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
doronr%us.ibm.com 2005-06-29 18:14:43 +00:00
parent 403260a8fd
commit 25a72b45f8
14 changed files with 528 additions and 112 deletions

View File

@ -71,6 +71,7 @@ REQUIRES = \
schemavalidation \
intl \
pref \
htmlparser \
$(NULL)
XPIDLSRCS = \
@ -145,6 +146,7 @@ CPPSRCS = \
nsXFormsControlStub.cpp \
nsXFormsUtilityService.cpp \
nsXFormsDelegateStub.cpp \
nsXFormsLazyInstanceElement.cpp \
$(NULL)
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS)

View File

@ -1,13 +0,0 @@
<?xml version="1.0"?>
<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:chrome="http://www.mozilla.org/rdf/chrome#">
<!-- list all the packages being supplied by this jar -->
<RDF:Seq about="urn:mozilla:package:root">
<RDF:li resource="urn:mozilla:package:xforms"/>
</RDF:Seq>
<!-- package information -->
<RDF:Description about="urn:mozilla:package:xforms"
chrome:name="xforms"/>
</RDF:RDF>

View File

@ -39,6 +39,7 @@
#include "nsISupports.idl"
interface nsIDOMDocument;
interface nsIDOMElement;
/**
* Private interface implemented by the instance element.
@ -50,6 +51,7 @@ interface nsIInstanceElementPrivate : nsISupports
* The document which holds the live instance data.
*/
attribute nsIDOMDocument document;
readonly attribute nsIDOMElement element;
void backupOriginalDocument();
void restoreOriginalDocument();
};

View File

@ -42,6 +42,11 @@ interface nsIXFormsControl;
interface nsISchemaType;
interface nsIInstanceElementPrivate;
interface nsIDOMNode;
%{C++
#include "nsCOMArray.h"
%}
[ptr] native nsCOMArrayPtr(nsCOMArray<nsIInstanceElementPrivate>);
/**
* Private interface implemented by the model element for other
@ -119,4 +124,21 @@ interface nsIModelElementPrivate : nsIXFormsModelElement
* @param aBoundNode The node the control is bound to
*/
void setStates(in nsIXFormsControl aControl, in nsIDOMNode aBoundNode);
/**
* The list of instance elements held by this model. Includes lazy-authored
* instance elements
*/
readonly attribute nsCOMArrayPtr instanceList;
/**
* Add an instance element to the model's instance list
* @param aInstanceElement The instance element to add to the list
*/
void addInstanceElement(in nsIInstanceElementPrivate aInstanceElement);
/**
* This attribute is set when the model's instance was lazy authored
*/
readonly attribute boolean lazyAuthored;
};

View File

@ -159,6 +159,19 @@ nsXFormsControlStubBase::ResetBoundNode(const nsString &aBindAttribute,
if (mBoundNode && mModel) {
mModel->SetStates(this, mBoundNode);
} else if (mModel) {
// we should have been successful. Must be pointing to a node that
// doesn't exist in the instance document. Disable the control
// per 4.2.2 in the spec
// Set pseudo class
///
/// @bug Set via attributes right now. Bug 271720. (XXX)
mElement->SetAttribute(NS_LITERAL_STRING("disabled"),
NS_LITERAL_STRING("1"));
mElement->RemoveAttribute(NS_LITERAL_STRING("enabled"));
// Dispatch event
nsXFormsUtils::DispatchEvent(mElement, eEvent_Disabled);
}
if (aResult) {

View File

@ -140,9 +140,9 @@ nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
{
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED |
nsIXTFElement::NOTIFY_PARENT_CHANGED |
nsIXTFElement::NOTIFY_BEGIN_ADDING_CHILDREN |
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
// XXX observe nsIXTFElement::NOTIFY_PARENT_CHANGED ??
nsCOMPtr<nsIDOMElement> node;
aWrapper->GetElementNode(getter_AddRefs(node));
@ -157,6 +157,23 @@ nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
return NS_OK;
}
NS_IMETHODIMP
nsXFormsInstanceElement::ParentChanged(nsIDOMElement *aNewParent)
{
if (!aNewParent)
return NS_OK;
// Once we are set up in the DOM, can find the model and make sure that this
// instance is on the list of instance elements that model keeps
nsCOMPtr<nsIModelElementPrivate> model = GetModel();
NS_ENSURE_TRUE(model, NS_ERROR_FAILURE);
nsCOMPtr<nsIInstanceElementPrivate> instance =
NS_STATIC_CAST(nsIInstanceElementPrivate*, this);
model->AddInstanceElement(this);
return NS_OK;
}
// nsIInterfaceRequestor
NS_IMETHODIMP
@ -298,10 +315,11 @@ nsXFormsInstanceElement::RestoreOriginalDocument()
{
nsresult rv = NS_OK;
// This is called when xforms-ready is received by the model. By now we know
// that the instance document, whether external or inline, is loaded into
// mDocument. Get the root node, clone it, and insert it into our copy of
// the document. This is the magic behind getting xforms-reset to work.
// This is called when xforms-reset is received by the model. We assume
// that the backup of the instance document has been populated and is
// loaded into mOriginalDocument. Get the backup's root node, clone it, and
// insert it into the live copy of the instance document. This is the magic
// behind getting xforms-reset to work.
if(mDocument && mOriginalDocument) {
nsCOMPtr<nsIDOMNode> newNode, instanceRootNode, nodeReturn;
nsCOMPtr<nsIDOMElement> instanceRoot;
@ -332,6 +350,12 @@ nsXFormsInstanceElement::RestoreOriginalDocument()
return rv;
}
NS_IMETHODIMP
nsXFormsInstanceElement::GetElement(nsIDOMElement **aElement)
{
NS_IF_ADDREF(*aElement = mElement);
return NS_OK;
}
// private methods
@ -446,7 +470,7 @@ nsXFormsInstanceElement::CreateInstanceDocument()
NS_ENSURE_SUCCESS(rv, rv);
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mDocument));
getter_AddRefs(mDocument));
NS_ENSURE_SUCCESS(rv, rv);
// I don't know if not being able to create a backup document is worth

View File

@ -78,6 +78,7 @@ public:
NS_IMETHOD BeginAddingChildren();
NS_IMETHOD DoneAddingChildren();
NS_IMETHOD OnCreated(nsIXTFGenericElementWrapper *aWrapper);
NS_IMETHOD ParentChanged(nsIDOMElement *aNewParent);
nsXFormsInstanceElement() NS_HIDDEN;

View File

@ -0,0 +1,191 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXFormsLazyInstanceElement.h"
#include "nsIDOMElement.h"
#include "nsIDocument.h"
#include "nsIDOMDOMImplementation.h"
NS_IMPL_ISUPPORTS_INHERITED2(nsXFormsLazyInstanceElement,
nsXFormsStubElement,
nsIInstanceElementPrivate,
nsIInterfaceRequestor)
nsXFormsLazyInstanceElement::nsXFormsLazyInstanceElement()
{
}
// nsIInstanceElementPrivate
NS_IMETHODIMP
nsXFormsLazyInstanceElement::GetDocument(nsIDOMDocument **aDocument)
{
NS_IF_ADDREF(*aDocument = mDocument);
return NS_OK;
}
NS_IMETHODIMP
nsXFormsLazyInstanceElement::SetDocument(nsIDOMDocument *aDocument)
{
mDocument = aDocument;
return NS_OK;
}
NS_IMETHODIMP
nsXFormsLazyInstanceElement::BackupOriginalDocument()
{
nsresult rv = NS_OK;
// This is called when xforms-ready is received by the model. By now we know
// that the lazy instance document has been populated and is loaded into
// mDocument. Get the root node, clone it, and insert it into our copy of
// the document. This is the magic behind getting xforms-reset to work.
if(mDocument && mOriginalDocument) {
nsCOMPtr<nsIDOMNode> newNode;
nsCOMPtr<nsIDOMElement> instanceRoot;
rv = mDocument->GetDocumentElement(getter_AddRefs(instanceRoot));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(instanceRoot, NS_ERROR_FAILURE);
nsCOMPtr<nsIDOMNode> nodeReturn;
rv = instanceRoot->CloneNode(PR_TRUE, getter_AddRefs(newNode));
if(NS_SUCCEEDED(rv)) {
rv = mOriginalDocument->AppendChild(newNode, getter_AddRefs(nodeReturn));
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"failed to set up original instance document");
}
}
return rv;
}
NS_IMETHODIMP
nsXFormsLazyInstanceElement::RestoreOriginalDocument()
{
nsresult rv = NS_OK;
// This is called when xforms-reset is received by the model. We assume
// that the backup of the lazy instance document has been populated and is
// loaded into mOriginalDocument. Get the backup's root node, clone it, and
// insert it into the live copy of the instance document. This is the magic
// behind getting xforms-reset to work.
if(mDocument && mOriginalDocument) {
nsCOMPtr<nsIDOMNode> newNode, instanceRootNode, nodeReturn;
nsCOMPtr<nsIDOMElement> instanceRoot;
// first remove all the old stuff
rv = mDocument->GetDocumentElement(getter_AddRefs(instanceRoot));
if(NS_SUCCEEDED(rv)) {
if(instanceRoot) {
rv = mDocument->RemoveChild(instanceRoot, getter_AddRefs(nodeReturn));
NS_ENSURE_SUCCESS(rv, rv);
}
}
// now all of the garbage is out o' there! Put the original data back
// into mDocument
rv = mOriginalDocument->GetDocumentElement(getter_AddRefs(instanceRoot));
NS_ENSURE_SUCCESS(rv, rv);
NS_ENSURE_TRUE(instanceRoot, NS_ERROR_FAILURE);
instanceRootNode = do_QueryInterface(instanceRoot);
rv = instanceRootNode->CloneNode(PR_TRUE, getter_AddRefs(newNode));
if(NS_SUCCEEDED(rv)) {
rv = mDocument->AppendChild(newNode, getter_AddRefs(nodeReturn));
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
"failed to restore original instance document");
}
}
return rv;
}
NS_IMETHODIMP
nsXFormsLazyInstanceElement::GetElement(nsIDOMElement **aElement)
{
*aElement = nsnull;
return NS_OK;
}
// nsIInterfaceRequestor
NS_IMETHODIMP
nsXFormsLazyInstanceElement::GetInterface(const nsIID & aIID, void **aResult)
{
*aResult = nsnull;
return QueryInterface(aIID, aResult);
}
nsresult
nsXFormsLazyInstanceElement::CreateLazyInstanceDocument(nsIDOMDocument *aXFormsDocument)
{
NS_ENSURE_ARG(aXFormsDocument);
// Do not try to load an instance document if the current document is not
// associated with a DOM window. This could happen, for example, if some
// XForms document loaded itself as instance data (which is what the Forms
// 1.0 testsuite does).
nsCOMPtr<nsIDocument> d = do_QueryInterface(aXFormsDocument);
if (d && !d->GetScriptGlobalObject())
return NS_ERROR_FAILURE;
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
nsresult rv = aXFormsDocument->GetImplementation(getter_AddRefs(domImpl));
NS_ENSURE_SUCCESS(rv, rv);
rv = domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mDocument));
NS_ENSURE_SUCCESS(rv, rv);
// Lazy authored instance documents have a root named "instanceData"
nsCOMPtr<nsIDOMElement> instanceDataElement;
nsCOMPtr<nsIDOMNode> childReturn;
rv = mDocument->CreateElementNS(EmptyString(),
NS_LITERAL_STRING("instanceData"),
getter_AddRefs(instanceDataElement));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDocument->AppendChild(instanceDataElement, getter_AddRefs(childReturn));
NS_ENSURE_SUCCESS(rv, rv);
// I don't know if not being able to create a backup document is worth
// failing this function. Since it probably won't be used often, we'll
// let it slide. But it probably does mean that things are going south
// with the browser.
domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
getter_AddRefs(mOriginalDocument));
return rv;
}

View File

@ -0,0 +1,76 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla XForms support.
*
* The Initial Developer of the Original Code is
* IBM Corporation.
* Portions created by the Initial Developer are Copyright (C) 2005
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Aaron Reed <aaronr@us.ibm.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsXFormsLazyInstanceElement_h_
#define nsXFormsLazyInstanceElement_h_
#include "nsXFormsStubElement.h"
#include "nsIDOMDocument.h"
#include "nsCOMPtr.h"
#include "nsIModelElementPrivate.h"
#include "nsIInstanceElementPrivate.h"
#include "nsIInterfaceRequestor.h"
class nsIDOMElement;
/**
* Implementation of the XForms \<instance\> element created through lazy
* authoring. It creates an instance document by cloning the contained
* instance data.
*/
class nsXFormsLazyInstanceElement : public nsXFormsStubElement,
public nsIInstanceElementPrivate,
public nsIInterfaceRequestor
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIINSTANCEELEMENTPRIVATE
NS_DECL_NSIINTERFACEREQUESTOR
NS_HIDDEN_(nsresult) CreateLazyInstanceDocument(nsIDOMDocument *aXFormsDocument);
nsXFormsLazyInstanceElement() NS_HIDDEN;
private:
nsCOMPtr<nsIDOMDocument> mDocument;
nsCOMPtr<nsIDOMDocument> mOriginalDocument;
};
#endif

View File

@ -76,6 +76,7 @@
#include "nsISchema.h"
#include "nsAutoPtr.h"
#include "nsArray.h"
#include "nsXFormsLazyInstanceElement.h"
#ifdef DEBUG
//#define DEBUG_MODEL
@ -248,7 +249,9 @@ nsXFormsModelElement::nsXFormsModelElement()
mSchemaTotal(0),
mPendingInstanceCount(0),
mDocumentLoaded(PR_FALSE),
mNeedsRefresh(PR_FALSE)
mNeedsRefresh(PR_FALSE),
mInstanceList(16),
mLazyModel(PR_FALSE)
{
}
@ -268,6 +271,8 @@ nsXFormsModelElement::OnDestroyed()
mElement = nsnull;
mSchemas = nsnull;
mInstanceList.Clear();
return NS_OK;
}
@ -398,6 +403,22 @@ nsXFormsModelElement::DoneAddingChildren()
}
}
// If all of the children are added and there aren't any instance elements,
// yet, then we need to make sure that one is ready in case the form author
// is using lazy authoring.
PRUint32 instCount = mInstanceList.Count();
if (!instCount) {
nsCOMPtr<nsIDOMDocument> domDoc;
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
if (domDoc) {
nsXFormsLazyInstanceElement *lazyInstance =
new nsXFormsLazyInstanceElement();
lazyInstance->CreateLazyInstanceDocument(domDoc);
AddInstanceElement(lazyInstance);
mLazyModel = PR_TRUE;
}
}
// 2. construct an XPath data model from inline or external initial instance
// data. This is done by our child instance elements as they are inserted
// into the document, and all of the instances will be processed by this
@ -990,32 +1011,34 @@ nsXFormsModelElement::FindInstanceElement(const nsAString &aID,
{
*aElement = nsnull;
nsCOMPtr<nsIDOMNodeList> children;
mElement->GetChildNodes(getter_AddRefs(children));
PRUint32 instCount = mInstanceList.Count();
if (instCount) {
nsCOMPtr<nsIDOMElement> element;
nsAutoString id;
for (int i = 0; i < instCount; ++i) {
nsIInstanceElementPrivate* instEle = mInstanceList.ObjectAt(i);
instEle->GetElement(getter_AddRefs(element));
if (!children)
return NS_OK;
PRUint32 childCount = 0;
children->GetLength(&childCount);
nsCOMPtr<nsIDOMNode> node;
nsCOMPtr<nsIDOMElement> element;
nsAutoString id;
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(node));
NS_ASSERTION(node, "incorrect NodeList length?");
element = do_QueryInterface(node);
if (!element)
continue;
element->GetAttribute(NS_LITERAL_STRING("id"), id);
if (aID.IsEmpty() || aID.Equals(id)) {
CallQueryInterface(element, aElement);
if (*aElement)
if (aID.IsEmpty()) {
NS_ADDREF(instEle);
*aElement = instEle;
break;
} else if (!element) {
// this should only happen if the instance on the list is lazy authored
// and as far as I can tell, a lazy authored instance should be the
// first (and only) instance in the model and unable to have an ID.
// But that isn't clear to me reading the spec, so for now
// we'll play it safe in case the WG more clearly defines lazy authoring
// in the future.
continue;
}
element->GetAttribute(NS_LITERAL_STRING("id"), id);
if (aID.Equals(id)) {
NS_ADDREF(instEle);
*aElement = instEle;
break;
}
}
}
@ -1155,6 +1178,12 @@ nsXFormsModelElement::GetContext(nsAString &aModelID,
return NS_OK;
}
NS_IMETHODIMP
nsXFormsModelElement::GetLazyAuthored(PRBool *aLazyInstance)
{
*aLazyInstance = mLazyModel;
return NS_OK;
}
// internal methods
@ -1244,40 +1273,23 @@ nsXFormsModelElement::Ready()
void
nsXFormsModelElement::BackupOrRestoreInstanceData(PRBool restore)
{
// I imagine that this can be done more elegantly. But in the end, the
// bulk of the work is walking the model's children looking for instance
// elements. After one is found, just need to ask the instance element to
// backup or restore.
nsCOMPtr<nsIDOMNodeList> children;
mElement->GetChildNodes(getter_AddRefs(children));
PRUint32 instCount = mInstanceList.Count();
if (instCount) {
for (int i = 0; i < instCount; ++i) {
nsIInstanceElementPrivate *instance = mInstanceList.ObjectAt(i);
if (!children)
return;
PRUint32 childCount = 0;
children->GetLength(&childCount);
nsCOMPtr<nsIDOMNode> node;
nsCOMPtr<nsIInstanceElementPrivate> instance;
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(node));
NS_ASSERTION(node, "incorrect NodeList length?");
instance = do_QueryInterface(node);
if (!instance)
continue;
// Don't know what to do with error if we get one.
// Restore/BackupOriginalDocument will already output warnings.
if(restore) {
instance->RestoreOriginalDocument();
}
else {
instance->BackupOriginalDocument();
// Don't know what to do with error if we get one.
// Restore/BackupOriginalDocument will already output warnings.
if(restore) {
instance->RestoreOriginalDocument();
}
else {
instance->BackupOriginalDocument();
}
}
}
}
@ -1614,6 +1626,26 @@ nsXFormsModelElement::SetStates(nsIXFormsControl *aControl, nsIDOMNode *aBoundNo
return SetStatesInternal(aControl, aBoundNode, PR_TRUE);
}
NS_IMETHODIMP
nsXFormsModelElement::GetInstanceList(nsCOMArray<nsIInstanceElementPrivate> **aInstanceList)
{
if (aInstanceList) {
*aInstanceList = &mInstanceList;
}
return NS_OK;
}
nsresult
nsXFormsModelElement::AddInstanceElement(nsIInstanceElementPrivate *aInstEle)
{
// always append to the end of the list. We need to keep the elements in
// document order since the first instance element is the default instance
// document for the model.
mInstanceList.AppendObject(aInstEle);
return NS_OK;
}
/* static */ void
nsXFormsModelElement::Startup()
{

View File

@ -209,6 +209,15 @@ private:
// This flag indicates whether a xforms-rebuild has been called, but no
// xforms-revalidate yet
PRBool mNeedsRefresh;
/**
* List of instance elements contained by this model, including lazy-authored
* instance elements.
*/
nsCOMArray<nsIInstanceElementPrivate> mInstanceList;
/** Indicates whether the model's instance was built by lazy authoring */
PRBool mLazyModel;
};
/**

View File

@ -775,11 +775,20 @@ nsXFormsSubmissionElement::SerializeDataXML(nsIDOMNode *data,
// add namespaces from the main document to the submission document, but only
// if the instance data is local, not remote.
PRBool hasSrc = PR_FALSE;
PRBool serialize = PR_FALSE;
nsCOMPtr<nsIDOMElement> instanceElement(do_QueryInterface(instanceNode));
instanceElement->HasAttribute(NS_LITERAL_STRING("src"), &hasSrc);
if (!hasSrc) {
// make sure that this is a DOMElement. It won't be if it was lazy
// authored. Lazy authored instance documents don't inherit namespaces
// from parent nodes or the original document (in formsPlayer and Novell,
// at least).
if (instanceElement) {
PRBool hasSrc = PR_FALSE;
instanceElement->HasAttribute(NS_LITERAL_STRING("src"), &hasSrc);
serialize = !hasSrc;
}
if (serialize) {
rv = AddNameSpaces(newDocElm, node);
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -116,12 +116,10 @@ nsXFormsUtilityService::IsNodeAssocWithModel( nsIDOMNode *aNode,
if (modelNode && (modelNode == aModel)) {
*aModelAssocWithNode = PR_TRUE;
}
else {
} else {
*aModelAssocWithNode = PR_FALSE;
}
}
else {
} else {
// We are assuming that if the node coming in isn't a proper XForms element,
// then it is an instance element in an instance doc. Now we just have
// to determine if the given model contains this instance document.
@ -137,26 +135,16 @@ nsXFormsUtilityService::IsNodeAssocWithModel( nsIDOMNode *aNode,
// document. If it is equal to the document that contains aNode,
// then aNode is associated with this aModel element and we can return
// true.
nsCOMPtr<nsIDOMNodeList> children;
aModel->GetChildNodes(getter_AddRefs(children));
if (!children)
return NS_OK;
PRUint32 childCount = 0;
children->GetLength(&childCount);
nsCOMPtr<nsIDOMNode> node;
nsCOMPtr<nsIModelElementPrivate>model = do_QueryInterface(modelEle);
nsCOMPtr<nsIInstanceElementPrivate> instElement;
nsCOMPtr<nsIDOMDocument> instDocument;
for (PRUint32 i = 0; i < childCount; ++i) {
children->Item(i, getter_AddRefs(node));
NS_ASSERTION(node, "incorrect NodeList length?");
instElement = do_QueryInterface(node);
if (!instElement)
continue;
nsCOMArray<nsIInstanceElementPrivate> *instList = nsnull;
model->GetInstanceList(&instList);
NS_ENSURE_TRUE(instList, NS_ERROR_FAILURE);
for (int i = 0; i < instList->Count(); ++i) {
instElement = instList->ObjectAt(i);
instElement->GetDocument(getter_AddRefs(instDocument));
if (instDocument) {

View File

@ -87,6 +87,7 @@
#include "nsIURI.h"
#include "nsIPrivateDOMEvent.h"
#include "nsIDOMNamedNodeMap.h"
#include "nsIParserService.h"
#define CANCELABLE 0x01
#define BUBBLES 0x02
@ -536,6 +537,73 @@ nsXFormsUtils::EvaluateNodeBinding(nsIDOMElement *aElement,
aDeps,
aIndexesUsed);
// If the evaluation failed because the node wasn't there and we should be
// lazy authoring, then create it (if the situation qualifies, of course).
// Novell only allows lazy authoring of single bound nodes.
if (aResultType == nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE) {
if (res) {
nsCOMPtr<nsIDOMNode> node;
rv = res->GetSingleNodeValue(getter_AddRefs(node));
if (NS_SUCCEEDED(rv) && !node) {
PRBool lazy = PR_FALSE;
if (*aModel)
(*aModel)->GetLazyAuthored(&lazy);
if (lazy) {
// according to sec 4.2.2 in the spec, "An instance data element node
// will be created using the binding expression from the user
// interface control as the name. If the name is not a valid QName,
// processing halts with an exception (xforms-binding-exception)"
nsCOMPtr<nsIParserService> parserService =
do_GetService(NS_PARSERSERVICE_CONTRACTID);
if (NS_SUCCEEDED(rv) && parserService) {
const PRUnichar* colon;
rv = parserService->CheckQName(expr, PR_TRUE, &colon);
if (NS_SUCCEEDED(rv)) {
nsAutoString namespaceURI(EmptyString());
// if we detect a namespace, we'll add it to the node, otherwise
// we'll use the empty namespace. If we should have gotten a
// namespace and didn't, then we might as well give up.
if (colon) {
nsCOMPtr<nsIDOM3Node> dom3node = do_QueryInterface(aElement);
rv = dom3node->LookupNamespaceURI(Substring(expr.get(), colon),
namespaceURI);
NS_ENSURE_SUCCESS(rv, rv);
}
if (NS_SUCCEEDED(rv)) {
nsCOMArray<nsIInstanceElementPrivate> *instList = nsnull;
(*aModel)->GetInstanceList(&instList);
nsCOMPtr<nsIInstanceElementPrivate> instance =
instList->ObjectAt(0);
nsCOMPtr<nsIDOMDocument> domdoc;
instance->GetDocument(getter_AddRefs(domdoc));
nsCOMPtr<nsIDOMElement> instanceDataEle;
nsCOMPtr<nsIDOMNode> childReturn;
rv = domdoc->CreateElementNS(namespaceURI, expr,
getter_AddRefs(instanceDataEle));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMElement> instanceRoot;
rv = domdoc->GetDocumentElement(getter_AddRefs(instanceRoot));
rv = instanceRoot->AppendChild(instanceDataEle,
getter_AddRefs(childReturn));
NS_ENSURE_SUCCESS(rv, rv);
}
// now that we inserted the lazy authored node, try to bind
// again
res = EvaluateXPath(expr, contextNode, aElement, aResultType,
contextPosition, contextSize, aDeps,
aIndexesUsed);
} else {
nsXFormsUtils::DispatchEvent(aElement, eEvent_BindingException);
}
}
}
}
}
}
res.swap(*aResult); // exchanges ref
return NS_OK;
@ -1116,22 +1184,14 @@ nsXFormsUtils::GetInstanceNodeForData(nsIDOMNode *aInstanceDataNode,
instanceDoc = do_QueryInterface(aInstanceDataNode);
NS_ENSURE_TRUE(instanceDoc, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIDOMElement> modelElem = do_QueryInterface(aModel);
NS_ENSURE_STATE(modelElem);
nsCOMPtr<nsIDOMNodeList> nodeList;
nsresult rv = modelElem->GetElementsByTagNameNS(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS),
NS_LITERAL_STRING("instance"),
getter_AddRefs(nodeList));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMArray<nsIInstanceElementPrivate> *instList = nsnull;
aModel->GetInstanceList(&instList);
NS_ENSURE_TRUE(instList, NS_ERROR_FAILURE);
PRUint32 childCount = 0;
nodeList->GetLength(&childCount);
PRUint32 i;
PRUint32 childCount = instList->Count();
for (i = 0; i < childCount; ++i) {
nodeList->Item(i, aInstanceNode);
nsCOMPtr<nsIInstanceElementPrivate> instPriv = do_QueryInterface(*aInstanceNode);
if (!instPriv)
continue;
nsCOMPtr<nsIInstanceElementPrivate> instPriv = instList->ObjectAt(i);
nsCOMPtr<nsIDOMDocument> tmpDoc;
instPriv->GetDocument(getter_AddRefs(tmpDoc));