зеркало из https://github.com/mozilla/pjs.git
[XForms] Setting a type on instance data makes rebuild() throw exception. Bug 310138, r=aaronr+smaug
This commit is contained in:
Родитель
acbab68e7c
Коммит
e58de7c058
|
@ -148,4 +148,14 @@ interface nsIModelElementPrivate : nsIXFormsModelElement
|
|||
* This attribute is set when the model handled xforms-ready event
|
||||
*/
|
||||
readonly attribute boolean isReady;
|
||||
|
||||
/**
|
||||
* Retrieves the type for an instance data node
|
||||
*
|
||||
* @param aInstanceData The instance data node
|
||||
* @param aType The type of the node
|
||||
* @param aNSURI The namespace of the type
|
||||
*/
|
||||
void GetTypeFromNode(in nsIDOMNode aInstanceData, out AString aType,
|
||||
out AString aNSUri);
|
||||
};
|
||||
|
|
|
@ -604,6 +604,10 @@ nsXFormsModelElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
|
|||
mInstanceDocuments = new nsXFormsModelInstanceDocuments();
|
||||
NS_ASSERTION(mInstanceDocuments, "could not create mInstanceDocuments?!");
|
||||
|
||||
// Initialize hash tables
|
||||
NS_ENSURE_TRUE(mNodeToType.Init(), NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(mNodeToP3PType.Init(), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -640,6 +644,12 @@ nsXFormsModelElement::Rebuild()
|
|||
rv = mMDG.Clear();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Clear any type information
|
||||
NS_ENSURE_TRUE(mNodeToType.IsInitialized() && mNodeToP3PType.IsInitialized(),
|
||||
NS_ERROR_FAILURE);
|
||||
mNodeToType.Clear();
|
||||
mNodeToP3PType.Clear();
|
||||
|
||||
// 2. Re-attach all elements
|
||||
if (mDocumentLoaded) { // if it's not during initializing phase
|
||||
// Copy the form control list as it stands right now.
|
||||
|
@ -1004,9 +1014,9 @@ nsXFormsModelElement::GetTypeForControl(nsIXFormsControl *aControl,
|
|||
nsXFormsModelElement::GetTypeAndNSFromNode(nsIDOMNode *aInstanceData,
|
||||
nsAString &aType, nsAString &aNSUri)
|
||||
{
|
||||
nsresult rv = nsXFormsUtils::ParseTypeFromNode(aInstanceData, aType, aNSUri);
|
||||
nsresult rv = GetTypeFromNode(aInstanceData, aType, aNSUri);
|
||||
|
||||
if(rv == NS_ERROR_NOT_AVAILABLE) {
|
||||
if (rv == NS_ERROR_NOT_AVAILABLE) {
|
||||
// if there is no type assigned, then assume that the type is 'string'
|
||||
aNSUri.Assign(NS_LITERAL_STRING(NS_NAMESPACE_XML_SCHEMA));
|
||||
aType.Assign(NS_LITERAL_STRING("string"));
|
||||
|
@ -1185,6 +1195,79 @@ nsXFormsModelElement::GetIsReady(PRBool *aIsReady)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::GetTypeFromNode(nsIDOMNode *aInstanceData,
|
||||
nsAString &aType,
|
||||
nsAString &aNSUri)
|
||||
{
|
||||
// aInstanceData could be an instance data node or it could be an attribute
|
||||
// on an instance data node (basically the node that a control is bound to).
|
||||
|
||||
nsString *typeVal = nsnull;
|
||||
|
||||
// Get type stored directly on instance node
|
||||
nsAutoString typeAttribute;
|
||||
nsCOMPtr<nsIDOMElement> nodeElem(do_QueryInterface(aInstanceData));
|
||||
if (nodeElem) {
|
||||
nodeElem->GetAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_XML_SCHEMA_INSTANCE),
|
||||
NS_LITERAL_STRING("type"), typeAttribute);
|
||||
if (!typeAttribute.IsEmpty()) {
|
||||
typeVal = &typeAttribute;
|
||||
}
|
||||
}
|
||||
|
||||
// If there was no type information on the node itself, check for a type
|
||||
// bound to the node via \<xforms:bind\>
|
||||
if (!typeVal && !mNodeToType.Get(aInstanceData, &typeVal)) {
|
||||
// No type information found
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// split type (ns:type) into namespace and type.
|
||||
nsAutoString prefix;
|
||||
PRInt32 separator = typeVal->FindChar(':');
|
||||
if ((PRUint32) separator == (typeVal->Length() - 1)) {
|
||||
const PRUnichar *strings[] = { typeVal->get() };
|
||||
nsXFormsUtils::ReportError(NS_LITERAL_STRING("missingTypeName"), strings, 1,
|
||||
mElement, nsnull);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (separator == kNotFound) {
|
||||
// no namespace prefix, which is valid;
|
||||
prefix = EmptyString();
|
||||
aType.Assign(*typeVal);
|
||||
} else {
|
||||
prefix.Assign(Substring(*typeVal, 0, separator));
|
||||
aType.Assign(Substring(*typeVal, ++separator, typeVal->Length()));
|
||||
}
|
||||
|
||||
if (prefix.IsEmpty()) {
|
||||
aNSUri = EmptyString();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// get the namespace url from the prefix using instance data node
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOM3Node> domNode3 = do_QueryInterface(aInstanceData, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = domNode3->LookupNamespaceURI(prefix, aNSUri);
|
||||
|
||||
if (DOMStringIsNull(aNSUri)) {
|
||||
// if not found using instance data node, use <xf:instance> node
|
||||
nsCOMPtr<nsIDOMNode> instanceNode;
|
||||
rv = nsXFormsUtils::GetInstanceNodeForData(aInstanceData,
|
||||
getter_AddRefs(instanceNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
domNode3 = do_QueryInterface(instanceNode, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = domNode3->LookupNamespaceURI(prefix, aNSUri);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// nsIXFormsContextControl
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1487,15 +1570,6 @@ nsXFormsModelElement::MaybeNotifyCompletion()
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DeleteAutoString(void *aObject,
|
||||
nsIAtom *aPropertyName,
|
||||
void *aPropertyValue,
|
||||
void *aData)
|
||||
{
|
||||
delete NS_STATIC_CAST(nsAutoString*, aPropertyValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
|
||||
nsIDOMNode *aContextNode,
|
||||
|
@ -1582,33 +1656,24 @@ nsXFormsModelElement::ProcessBind(nsIXFormsXPathEvaluator *aEvaluator,
|
|||
|
||||
// type and p3ptype are stored as properties on the instance node
|
||||
if (j == eModel_type || j == eModel_p3ptype) {
|
||||
nsAutoPtr<nsAutoString> prop (new nsAutoString(propStrings[j]));
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(node);
|
||||
if (content) {
|
||||
rv = content->SetProperty(sModelPropsList[j],
|
||||
prop,
|
||||
DeleteAutoString);
|
||||
} else {
|
||||
nsCOMPtr<nsIAttribute> attribute = do_QueryInterface(node);
|
||||
if (attribute) {
|
||||
rv = attribute->SetProperty(sModelPropsList[j],
|
||||
prop,
|
||||
DeleteAutoString);
|
||||
} else {
|
||||
NS_WARNING("node is neither nsIContent or nsIAttribute");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
prop.forget();
|
||||
} else {
|
||||
return rv;
|
||||
}
|
||||
if (rv == NS_PROPTABLE_PROP_OVERWRITTEN) {
|
||||
nsClassHashtable<nsISupportsHashKey, nsString> *table;
|
||||
table = j == eModel_type ? &mNodeToType : &mNodeToP3PType;
|
||||
NS_ENSURE_TRUE(table->IsInitialized(), NS_ERROR_FAILURE);
|
||||
|
||||
// Check for existing value
|
||||
if (table->Get(node, nsnull)) {
|
||||
multiMIP = PR_TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Insert value
|
||||
nsAutoPtr<nsString> newString(new nsString(propStrings[j]));
|
||||
NS_ENSURE_TRUE(newString, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ENSURE_TRUE(table->Put(node, newString), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
// string is succesfully stored in the table, we should not dealloc it
|
||||
newString.forget();
|
||||
|
||||
if (j == eModel_type) {
|
||||
// Inform MDG that it needs to check type. The only arguments
|
||||
// actually used are |eModel_constraint| and |node|.
|
||||
|
|
|
@ -288,6 +288,21 @@ private:
|
|||
|
||||
// Indicates whether the model's instance was built by lazy authoring
|
||||
PRBool mLazyModel;
|
||||
|
||||
/**
|
||||
* Type information for nodes, with their type set through \<xforms:bind\>.
|
||||
*
|
||||
* @see http://www.w3.org/TR/xforms/slice6.html#model-prop-type
|
||||
*/
|
||||
nsClassHashtable<nsISupportsHashKey, nsString> mNodeToType;
|
||||
|
||||
/**
|
||||
* P3P type information for nodes, with their type set through
|
||||
* \<xforms:bind\>.
|
||||
|
||||
* @see http://www.w3.org/TR/xforms/slice6.html#model-prop-p3ptype
|
||||
*/
|
||||
nsClassHashtable<nsISupportsHashKey, nsString> mNodeToP3PType;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1279,7 +1279,7 @@ nsXFormsSubmissionElement::CopyChildren(nsIDOMNode *source, nsIDOMNode *dest,
|
|||
|
||||
PRUint32 encType;
|
||||
if (attachments &&
|
||||
NS_SUCCEEDED(GetElementEncodingType(currentNode, &encType)) &&
|
||||
NS_SUCCEEDED(GetElementEncodingType(currentNode, &encType, model)) &&
|
||||
encType == ELEMENT_ENCTYPE_URI)
|
||||
{
|
||||
// ok, looks like we have a local file to upload
|
||||
|
@ -1744,7 +1744,9 @@ nsXFormsSubmissionElement::AppendPostDataChunk(nsCString &postDataChunk,
|
|||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsSubmissionElement::GetElementEncodingType(nsIDOMNode *node, PRUint32 *encType)
|
||||
nsXFormsSubmissionElement::GetElementEncodingType(nsIDOMNode *node,
|
||||
PRUint32 *encType,
|
||||
nsIModelElementPrivate *aModel)
|
||||
{
|
||||
*encType = ELEMENT_ENCTYPE_STRING; // default
|
||||
|
||||
|
@ -1753,7 +1755,12 @@ nsXFormsSubmissionElement::GetElementEncodingType(nsIDOMNode *node, PRUint32 *en
|
|||
|
||||
// check for 'xsd:base64Binary', 'xsd:hexBinary', or 'xsd:anyURI'
|
||||
nsAutoString type, nsuri;
|
||||
nsresult rv = nsXFormsUtils::ParseTypeFromNode(node, type, nsuri);
|
||||
nsresult rv;
|
||||
if (aModel) {
|
||||
rv = aModel->GetTypeFromNode(node, type, nsuri);
|
||||
} else {
|
||||
rv = nsXFormsUtils::ParseTypeFromNode(node, type, nsuri);
|
||||
}
|
||||
if (NS_SUCCEEDED(rv) &&
|
||||
nsuri.EqualsLiteral(NS_NAMESPACE_XML_SCHEMA) &&
|
||||
!type.IsEmpty())
|
||||
|
|
|
@ -112,7 +112,7 @@ public:
|
|||
NS_HIDDEN_(nsresult) SerializeDataMultipartFormData(nsIDOMNode *data, nsIInputStream **, nsCString &contentType);
|
||||
NS_HIDDEN_(nsresult) AppendMultipartFormData(nsIDOMNode *data, const nsCString &boundary, nsCString &buf, nsIMultiplexInputStream *);
|
||||
NS_HIDDEN_(nsresult) AppendPostDataChunk(nsCString &postDataChunk, nsIMultiplexInputStream *multiStream);
|
||||
NS_HIDDEN_(nsresult) GetElementEncodingType(nsIDOMNode *data, PRUint32 *encType);
|
||||
NS_HIDDEN_(nsresult) GetElementEncodingType(nsIDOMNode *data, PRUint32 *encType, nsIModelElementPrivate* aModel = nsnull);
|
||||
NS_HIDDEN_(nsresult) CreateFileStream(const nsString &absURI, nsIFile **file, nsIInputStream **stream);
|
||||
NS_HIDDEN_(nsresult) SendData(const nsCString &uri, nsIInputStream *stream, const nsCString &contentType);
|
||||
|
||||
|
|
|
@ -146,10 +146,12 @@ nsBoundType
|
|||
nsXFormsUploadElement::GetBoundType()
|
||||
{
|
||||
nsBoundType result = TYPE_DEFAULT;
|
||||
if (!mModel)
|
||||
return result;
|
||||
|
||||
// get type bound to node
|
||||
nsAutoString type, nsuri;
|
||||
nsresult rv = nsXFormsUtils::ParseTypeFromNode(mBoundNode, type, nsuri);
|
||||
nsresult rv = mModel->GetTypeFromNode(mBoundNode, type, nsuri);
|
||||
if (NS_SUCCEEDED(rv) && nsuri.EqualsLiteral(NS_NAMESPACE_XML_SCHEMA)) {
|
||||
if (type.EqualsLiteral("anyURI")) {
|
||||
result = TYPE_ANYURI;
|
||||
|
|
|
@ -1260,89 +1260,26 @@ nsXFormsUtils::GetInstanceNodeForData(nsIDOMNode *aInstanceDataNode,
|
|||
}
|
||||
|
||||
/* static */ nsresult
|
||||
nsXFormsUtils::ParseTypeFromNode(nsIDOMNode *aInstanceData,
|
||||
nsAString &aType, nsAString &aNSUri)
|
||||
nsXFormsUtils::ParseTypeFromNode(nsIDOMNode *aInstanceData,
|
||||
nsAString &aType,
|
||||
nsAString &aNSUri)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsresult rv;
|
||||
|
||||
// aInstanceData could be an instance data node or it could be an attribute
|
||||
// on an instance data node (basically the node that a control is bound to).
|
||||
// Find the model for the instance data node
|
||||
nsCOMPtr<nsIDOMNode> instanceNode;
|
||||
rv = nsXFormsUtils::GetInstanceNodeForData(aInstanceData,
|
||||
getter_AddRefs(instanceNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString *typeVal = nsnull;
|
||||
nsCOMPtr<nsIDOMNode> modelNode;
|
||||
rv = instanceNode->GetParentNode(getter_AddRefs(modelNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Get type stored directly on instance node
|
||||
nsAutoString typeAttribute;
|
||||
nsCOMPtr<nsIDOMElement> nodeElem(do_QueryInterface(aInstanceData));
|
||||
if (nodeElem) {
|
||||
nodeElem->GetAttributeNS(NS_LITERAL_STRING(NS_NAMESPACE_XML_SCHEMA_INSTANCE),
|
||||
NS_LITERAL_STRING("type"), typeAttribute);
|
||||
if (!typeAttribute.IsEmpty()) {
|
||||
typeVal = &typeAttribute;
|
||||
}
|
||||
}
|
||||
nsCOMPtr<nsIModelElementPrivate> model(do_QueryInterface(modelNode));
|
||||
NS_ENSURE_STATE(model);
|
||||
|
||||
if (!typeVal) {
|
||||
// Get MIP type bound to node
|
||||
nsCOMPtr<nsIContent> nodeContent(do_QueryInterface(aInstanceData));
|
||||
if (nodeContent) {
|
||||
typeVal =
|
||||
NS_STATIC_CAST(nsAutoString*,
|
||||
nodeContent->GetProperty(nsXFormsAtoms::type, &rv));
|
||||
} else {
|
||||
nsCOMPtr<nsIAttribute> nodeAttribute(do_QueryInterface(aInstanceData));
|
||||
if (!nodeAttribute)
|
||||
// node is neither content or attribute!
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
typeVal =
|
||||
NS_STATIC_CAST(nsAutoString*,
|
||||
nodeAttribute->GetProperty(nsXFormsAtoms::type, &rv));
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv) || !typeVal) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// split type (ns:type) into namespace and type.
|
||||
nsAutoString prefix;
|
||||
PRInt32 separator = typeVal->FindChar(':');
|
||||
if ((PRUint32) separator == (typeVal->Length() - 1)) {
|
||||
const PRUnichar *strings[] = { typeVal->get() };
|
||||
// XXX: get an element from the document this came from
|
||||
ReportError(NS_LITERAL_STRING("missingTypeName"), strings, 1, nsnull, nsnull);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
} else if (separator == kNotFound) {
|
||||
// no namespace prefix, which is valid;
|
||||
prefix.AssignLiteral("");
|
||||
aType.Assign(*typeVal);
|
||||
} else {
|
||||
prefix.Assign(Substring(*typeVal, 0, separator));
|
||||
aType.Assign(Substring(*typeVal, ++separator, typeVal->Length()));
|
||||
}
|
||||
|
||||
if (prefix.IsEmpty()) {
|
||||
aNSUri.AssignLiteral("");
|
||||
} else {
|
||||
// get the namespace url from the prefix using instance data node
|
||||
nsCOMPtr<nsIDOM3Node> domNode3 = do_QueryInterface(aInstanceData, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = domNode3->LookupNamespaceURI(prefix, aNSUri);
|
||||
|
||||
if (DOMStringIsNull(aNSUri)) {
|
||||
// if not found using instance data node, use <xf:instance> node
|
||||
nsCOMPtr<nsIDOMNode> instanceNode;
|
||||
rv = nsXFormsUtils::GetInstanceNodeForData(aInstanceData,
|
||||
getter_AddRefs(instanceNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
domNode3 = do_QueryInterface(instanceNode, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = domNode3->LookupNamespaceURI(prefix, aNSUri);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
return model->GetTypeFromNode(aInstanceData, aType, aNSUri);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
|
|
Загрузка…
Ссылка в новой задаче