PR_LOG(gLog, PR_LOG_DEBUG, ("xultemplate[%p] synchronize-all [%s] begin", this, uri));
PR_LOG(gXULTemplateLog, PR_LOG_DEBUG, ("xultemplate[%p]   %d <= %s", this, var, str.get()));
nsXULTemplateBuilder::SynchronizeAll(nsIRDFResource* aSource,                                     nsIRDFResource* aProperty,                                     nsIRDFNode* aOldTarget,                                     nsIRDFNode* aNewTarget){    // Update each match that contains <aSource, aProperty, aOldTarget>.    nsresult rv;    // Forbid re-entrant updates while we synchronize    AutoSentry guard(&mIsBuilding);    // Get all the matches whose assignments are currently supported    // by aSource and aProperty: we'll need to recompute them.    const MatchSet* matches;    mConflictSet.GetMatchesWithBindingDependency(aSource, &matches);    if (! matches || matches->Empty())        return NS_OK;    // Since we'll actually be manipulating the match set as we    // iterate through it, we need to copy it into our own private    // area before performing the iteration.    static const size_t kBucketSizes[] = { MatchSet::kEntrySize, MatchSet::kIndexSize };    static const PRInt32 kNumBuckets = sizeof(kBucketSizes) / sizeof(size_t);    // Per news://news.mozilla.org/39BEC105.5090206%40netscape.com    static const PRInt32 kPoolSize = 256;    nsFixedSizeAllocator pool;    pool.Init("nsXULTemplateBuilder::SynchronizeAll", kBucketSizes, kNumBuckets, kPoolSize);    MatchSet copy;    matches->CopyInto(copy, pool);    for (MatchSet::Iterator match = copy.First(); match != copy.Last(); ++match) {        const Rule* rule = match->mRule;        // Recompute the assignments. This will replace aOldTarget with        // aNewTarget, which will disrupt the match set.        VariableSet modified;        rule->RecomputeBindings(mConflictSet, match.operator->(),                                aSource, aProperty, aOldTarget, aNewTarget,                                modified);        // If nothing changed, then continue on to the next match.        if (0 == modified.GetCount())            continue;        Value memberValue;        match->mAssignments.GetAssignmentFor(rule->GetMemberVariable(), &memberValue);        nsIRDFResource* resource = VALUE_TO_IRDFRESOURCE(memberValue);        NS_ASSERTION(resource != nsnull, "no content");        if (! resource)            continue;#ifdef PR_LOGGING        if (PR_LOG_TEST(gLog, PR_LOG_DEBUG)) {            const char* uri;            resource->GetValueConst(&uri);            PR_LOG(gLog, PR_LOG_DEBUG,                   ("xultemplate[%p] synchronize-all [%s] begin", this, uri));        }#endif        Value parentValue;        match->mAssignments.GetAssignmentFor(mContentVar, &parentValue);        nsIContent* parent = VALUE_TO_ICONTENT(parentValue);        // Now that we've got the resource of the member variable, we        // should be able to update its kids appropriately        nsCOMPtr<nsISupportsArray> elements;        rv = NS_NewISupportsArray(getter_AddRefs(elements));        NS_ASSERTION(NS_SUCCEEDED(rv), "unable to create new ISupportsArray");        if (NS_FAILED(rv)) return rv;        rv = GetElementsForResource(resource, elements);        NS_ASSERTION(NS_SUCCEEDED(rv), "unable to retrieve elements from resource");        if (NS_FAILED(rv)) return rv;        PRUint32 cnt;        rv = elements->Count(&cnt);        if (NS_FAILED(rv)) return rv;#ifdef PR_LOGGING        if (PR_LOG_TEST(gLog, PR_LOG_DEBUG) && cnt == 0) {            const char* uri;            resource->GetValueConst(&uri);            PR_LOG(gLog, PR_LOG_DEBUG,                   ("xultemplate[%p] synchronize-all [%s] is not in element map", this, uri));        }#endif        for (PRInt32 i = PRInt32(cnt) - 1; i >= 0; --i) {            nsISupports* isupports = elements->ElementAt(i);            nsCOMPtr<nsIContent> element( do_QueryInterface(isupports) );            NS_IF_RELEASE(isupports);            // If the element is contained by the parent of the rule            // that we've just matched, then it's the wrong element.            if (! IsElementContainedBy(element, parent))                continue;            nsAutoString templateID;            rv = element->GetAttribute(kNameSpaceID_None,                                       nsXULAtoms::Template,                                       templateID);            if (NS_FAILED(rv)) return rv;            if (rv != NS_CONTENT_ATTR_HAS_VALUE)                continue;            nsCOMPtr<nsIDOMXULDocument>    xulDoc;            xulDoc = do_QueryInterface(mDocument);            if (! xulDoc)                return NS_ERROR_UNEXPECTED;            nsCOMPtr<nsIDOMElement>    domElement;            rv = xulDoc->GetElementById(templateID, getter_AddRefs(domElement));            NS_ASSERTION(NS_SUCCEEDED(rv), "unable to find template node");            if (NS_FAILED(rv)) return rv;            nsCOMPtr<nsIContent> templateNode = do_QueryInterface(domElement);            if (! templateNode)                return NS_ERROR_UNEXPECTED;            // this node was created by a XUL template, so update it accordingly            rv = SynchronizeUsingTemplate(templateNode, element, *match, modified);            if (NS_FAILED(rv)) return rv;        }        #ifdef PR_LOGGING        if (PR_LOG_TEST(gLog, PR_LOG_DEBUG)) {            const char* uri;            resource->GetValueConst(&uri);            PR_LOG(gLog, PR_LOG_DEBUG,                   ("xultemplate[%p] synchronize-all [%s] end", this, uri));        }#endif    }    return NS_OK;}