}
nsXULTemplateBuilder::OnChange(nsIRDFResource* aSource,                               nsIRDFResource* aProperty,                               nsIRDFNode* aOldTarget,                               nsIRDFNode* aNewTarget){    // Just silently fail, because this can happen "normally" as part    // of tear-down code. (Bug 9098)    if (! mDocument)        return NS_OK;    // Ignore re-entrant updates while we're building content.    if (mIsBuilding)        return NS_OK;	if (mCache)	{		if (aOldTarget)		{			// XXX fix this: in-memory DS doesn't like a null oldTarget			mCache->Change(aSource, aProperty, aOldTarget, aNewTarget);		}		else		{			// XXX should get tv via observer interface			mCache->Assert(aSource, aProperty, aNewTarget, PR_TRUE);		}	}    nsresult rv;    LOG("onchange", aSource, aProperty, aNewTarget);    if (aOldTarget) {        // Pull any old rules that were relying on aOldTarget        rv = Retract(aSource, aProperty, aOldTarget);        if (NS_FAILED(rv)) return rv;    }    if (aNewTarget) {        // Fire any new rules that are activated by aNewTarget        ClusterKeySet newkeys;        rv = Propogate(aSource, aProperty, aNewTarget, newkeys);        if (NS_FAILED(rv)) return rv;        rv = FireNewlyMatchedRules(newkeys);        if (NS_FAILED(rv)) return rv;    }    // Synchronize any of the content model that may have changed.    rv = SynchronizeAll(aSource, aProperty, aOldTarget, aNewTarget);    if (NS_FAILED(rv)) return rv;    return NS_OK;}