зеркало из https://github.com/mozilla/pjs.git
Fix for bugs 20485 and 24600. We no longer flush immediately in the content sink when we hit a script element. Instead the sink is a document observer and listens for BeginUpdate/EndUpdate notifications when evaluating a script and flushes only if necessary. Added BeginUpdate/EndUpdate notifications to nsIDocument and layout content (note that it's still necessary for XUL content). r=nisheeth,pollmann
This commit is contained in:
Родитель
92dc6a32b9
Коммит
fa580e6551
|
@ -240,6 +240,8 @@ public:
|
|||
|
||||
// Observation hooks used by content nodes to propagate
|
||||
// notifications to document observers.
|
||||
NS_IMETHOD BeginUpdate() = 0;
|
||||
NS_IMETHOD EndUpdate() = 0;
|
||||
NS_IMETHOD BeginLoad() = 0;
|
||||
NS_IMETHOD EndLoad() = 0;
|
||||
NS_IMETHOD ContentChanged(nsIContent* aContent,
|
||||
|
|
|
@ -1463,6 +1463,42 @@ PRBool nsDocument::RemoveObserver(nsIDocumentObserver* aObserver)
|
|||
return (mObservers.IndexOf(aObserver) != -1);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::BeginUpdate()
|
||||
{
|
||||
PRInt32 i;
|
||||
// Get new value of count for every iteration in case
|
||||
// observers remove themselves during the loop.
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
// Make sure that the observer didn't remove itself during the
|
||||
// notification. If it did, update our index and count.
|
||||
if (observer != (nsIDocumentObserver*)mObservers[i]) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::EndUpdate()
|
||||
{
|
||||
PRInt32 i;
|
||||
// Get new value of count for every iteration in case
|
||||
// observers remove themselves during the loop.
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->EndUpdate(this);
|
||||
// Make sure that the observer didn't remove itself during the
|
||||
// notification. If it did, update our index and count.
|
||||
if (observer != (nsIDocumentObserver*)mObservers[i]) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::BeginLoad()
|
||||
{
|
||||
|
@ -1651,12 +1687,16 @@ nsDocument::StyleRuleChanged(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRul
|
|||
// observers remove themselves during the loop.
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
observer->StyleRuleChanged(this, aStyleSheet, aStyleRule, aHint);
|
||||
// Make sure that the observer didn't remove itself during the
|
||||
// notification. If it did, update our index and count.
|
||||
if (observer != (nsIDocumentObserver*)mObservers[i]) {
|
||||
i--;
|
||||
}
|
||||
else {
|
||||
observer->EndUpdate(this);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1669,12 +1709,16 @@ nsDocument::StyleRuleAdded(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule)
|
|||
// observers remove themselves during the loop.
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
observer->StyleRuleAdded(this, aStyleSheet, aStyleRule);
|
||||
// Make sure that the observer didn't remove itself during the
|
||||
// notification. If it did, update our index and count.
|
||||
if (observer != (nsIDocumentObserver*)mObservers[i]) {
|
||||
i--;
|
||||
}
|
||||
else {
|
||||
observer->EndUpdate(this);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1687,12 +1731,16 @@ nsDocument::StyleRuleRemoved(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRul
|
|||
// observers remove themselves during the loop.
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
observer->StyleRuleRemoved(this, aStyleSheet, aStyleRule);
|
||||
// Make sure that the observer didn't remove itself during the
|
||||
// notification. If it did, update our index and count.
|
||||
if (observer != (nsIDocumentObserver*)mObservers[i]) {
|
||||
i--;
|
||||
}
|
||||
else {
|
||||
observer->EndUpdate(this);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1004,11 +1004,15 @@ nsGenericDOMDataNode::SetText(const PRUnichar* aBuffer, PRInt32 aLength,
|
|||
if (nsnull == aBuffer) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->BeginUpdate();
|
||||
}
|
||||
mText.SetTo(aBuffer, aLength);
|
||||
|
||||
// Trigger a reflow
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->ContentChanged(mContent, nsnull);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1025,11 +1029,15 @@ nsGenericDOMDataNode::SetText(const char* aBuffer,
|
|||
if (nsnull == aBuffer) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->BeginUpdate();
|
||||
}
|
||||
mText.SetTo(aBuffer, aLength);
|
||||
|
||||
// Trigger a reflow
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->ContentChanged(mContent, nsnull);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1868,6 +1868,11 @@ nsGenericContainerElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
if (nsnull == mAttributes) {
|
||||
mAttributes = new nsVoidArray();
|
||||
}
|
||||
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->BeginUpdate();
|
||||
}
|
||||
|
||||
if (nsnull != mAttributes) {
|
||||
nsGenericAttribute* attr;
|
||||
PRInt32 index;
|
||||
|
@ -1890,8 +1895,11 @@ nsGenericContainerElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && aNotify && (nsnull != mDocument)) {
|
||||
mDocument->AttributeChanged(mContent, aNameSpaceID, aName, NS_STYLE_HINT_UNKNOWN);
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mDocument->AttributeChanged(mContent, aNameSpaceID, aName, NS_STYLE_HINT_UNKNOWN);
|
||||
}
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -1957,6 +1965,9 @@ nsGenericContainerElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
nsGenericAttribute* attr = (nsGenericAttribute*)mAttributes->ElementAt(index);
|
||||
if (((kNameSpaceID_Unknown == aNameSpaceID) || (attr->mNameSpaceID == aNameSpaceID)) &&
|
||||
(attr->mName == aName)) {
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->BeginUpdate();
|
||||
}
|
||||
mAttributes->RemoveElementAt(index);
|
||||
delete attr;
|
||||
found = PR_TRUE;
|
||||
|
@ -1966,6 +1977,7 @@ nsGenericContainerElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
|
||||
if (NS_SUCCEEDED(rv) && found && aNotify && (nsnull != mDocument)) {
|
||||
mDocument->AttributeChanged(mContent, aNameSpaceID, aName, NS_STYLE_HINT_UNKNOWN);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2117,12 +2129,15 @@ nsGenericContainerElement::InsertChildAt(nsIContent* aKid,
|
|||
PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aKid, "null ptr");
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
nsRange::OwnerChildInserted(mContent, aIndex);
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -2130,6 +2145,9 @@ nsGenericContainerElement::InsertChildAt(nsIContent* aKid,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2139,13 +2157,16 @@ nsGenericContainerElement::ReplaceChildAt(nsIContent* aKid,
|
|||
PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aKid, "null ptr");
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
|
||||
nsRange::OwnerChildReplaced(mContent, aIndex, oldKid);
|
||||
PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex);
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -2156,6 +2177,9 @@ nsGenericContainerElement::ReplaceChildAt(nsIContent* aKid,
|
|||
oldKid->SetParent(nsnull);
|
||||
NS_RELEASE(oldKid);
|
||||
}
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2163,12 +2187,15 @@ nsresult
|
|||
nsGenericContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION((nsnull != aKid) && (aKid != mContent), "null ptr");
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
PRBool rv = mChildren.AppendElement(aKid);
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
// ranges don't need adjustment since new child is at end of list
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -2176,6 +2203,9 @@ nsGenericContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2185,6 +2215,9 @@ nsGenericContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
|||
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
|
||||
if (nsnull != oldKid ) {
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
nsRange::OwnerChildRemoved(mContent, aIndex, oldKid);
|
||||
mChildren.RemoveElementAt(aIndex);
|
||||
if (aNotify) {
|
||||
|
@ -2195,6 +2228,9 @@ nsGenericContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
|||
oldKid->SetDocument(nsnull, PR_TRUE);
|
||||
oldKid->SetParent(nsnull);
|
||||
NS_RELEASE(oldKid);
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -2085,6 +2085,7 @@ nsEventStateManager::SetContentState(nsIContent *aContent, PRInt32 aState)
|
|||
nsIDocument *document; // this presumes content can't get/lose state if not connected to doc
|
||||
notifyContent[0]->GetDocument(document);
|
||||
if (document) {
|
||||
document->BeginUpdate();
|
||||
document->ContentStatesChanged(notifyContent[0], notifyContent[1]);
|
||||
if (notifyContent[2]) { // more that two notifications are needed (should be rare)
|
||||
// XXX a further optimization here would be to group the notification pairs
|
||||
|
@ -2095,6 +2096,7 @@ nsEventStateManager::SetContentState(nsIContent *aContent, PRInt32 aState)
|
|||
document->ContentStatesChanged(notifyContent[4], nsnull);
|
||||
}
|
||||
}
|
||||
document->EndUpdate();
|
||||
NS_RELEASE(document);
|
||||
}
|
||||
|
||||
|
|
|
@ -217,11 +217,15 @@ nsDOMCSSAttributeDeclaration::ParseDeclaration(const nsString& aDecl)
|
|||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
PRInt32 hint;
|
||||
if (doc) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, &hint);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
if (doc) {
|
||||
if (doc) {
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
doc->AttributeChanged(mContent, kNameSpaceID_None, nsHTMLAtoms::style, hint);
|
||||
}
|
||||
doc->EndUpdate();
|
||||
}
|
||||
if (cssLoader) {
|
||||
cssLoader->RecycleParser(cssParser);
|
||||
|
@ -700,6 +704,10 @@ nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
|
|||
NS_RELEASE(htmlContent);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->BeginUpdate();
|
||||
}
|
||||
// set as string value to avoid another string copy
|
||||
PRBool impact = NS_STYLE_HINT_NONE;
|
||||
htmlContent->GetMappedAttributeImpact(aAttribute, impact);
|
||||
|
@ -729,6 +737,7 @@ nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
|
|||
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->AttributeChanged(mContent, aNameSpaceID, aAttribute, NS_STYLE_HINT_UNKNOWN);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -771,15 +780,18 @@ nsGenericHTMLElement::SetHTMLAttribute(nsIAtom* aAttribute,
|
|||
PRBool impact = NS_STYLE_HINT_NONE;
|
||||
htmlContent->GetMappedAttributeImpact(aAttribute, impact);
|
||||
if (nsnull != mDocument) { // set attr via style sheet
|
||||
if (aNotify && (nsHTMLAtoms::style == aAttribute)) {
|
||||
nsHTMLValue oldValue;
|
||||
PRInt32 oldImpact = NS_STYLE_HINT_NONE;
|
||||
if (NS_CONTENT_ATTR_NOT_THERE != GetHTMLAttribute(aAttribute, oldValue)) {
|
||||
oldImpact = GetStyleImpactFrom(oldValue);
|
||||
}
|
||||
impact = GetStyleImpactFrom(aValue);
|
||||
if (impact < oldImpact) {
|
||||
impact = oldImpact;
|
||||
if (aNotify) {
|
||||
mDocument->BeginUpdate();
|
||||
if (nsHTMLAtoms::style == aAttribute) {
|
||||
nsHTMLValue oldValue;
|
||||
PRInt32 oldImpact = NS_STYLE_HINT_NONE;
|
||||
if (NS_CONTENT_ATTR_NOT_THERE != GetHTMLAttribute(aAttribute, oldValue)) {
|
||||
oldImpact = GetStyleImpactFrom(oldValue);
|
||||
}
|
||||
impact = GetStyleImpactFrom(aValue);
|
||||
if (impact < oldImpact) {
|
||||
impact = oldImpact;
|
||||
}
|
||||
}
|
||||
}
|
||||
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
|
||||
|
@ -791,6 +803,7 @@ nsGenericHTMLElement::SetHTMLAttribute(nsIAtom* aAttribute,
|
|||
}
|
||||
if (aNotify) {
|
||||
mDocument->AttributeChanged(mContent, kNameSpaceID_None, aAttribute, impact);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
}
|
||||
else { // manage this ourselves and re-sync when we connect to doc
|
||||
|
@ -833,13 +846,16 @@ nsGenericHTMLElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
|||
}
|
||||
if (nsnull != mDocument) { // set attr via style sheet
|
||||
PRInt32 impact = NS_STYLE_HINT_UNKNOWN;
|
||||
if (aNotify && (nsHTMLAtoms::style == aAttribute)) {
|
||||
nsHTMLValue oldValue;
|
||||
if (NS_CONTENT_ATTR_NOT_THERE != GetHTMLAttribute(aAttribute, oldValue)) {
|
||||
impact = GetStyleImpactFrom(oldValue);
|
||||
}
|
||||
else {
|
||||
impact = NS_STYLE_HINT_NONE;
|
||||
if (aNotify) {
|
||||
mDocument->BeginUpdate();
|
||||
if (nsHTMLAtoms::style == aAttribute) {
|
||||
nsHTMLValue oldValue;
|
||||
if (NS_CONTENT_ATTR_NOT_THERE != GetHTMLAttribute(aAttribute, oldValue)) {
|
||||
impact = GetStyleImpactFrom(oldValue);
|
||||
}
|
||||
else {
|
||||
impact = NS_STYLE_HINT_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
|
||||
|
@ -849,6 +865,7 @@ nsGenericHTMLElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
|||
}
|
||||
if (aNotify) {
|
||||
mDocument->AttributeChanged(mContent, aNameSpaceID, aAttribute, impact);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
}
|
||||
else { // manage this ourselves and re-sync when we connect to doc
|
||||
|
@ -1585,16 +1602,19 @@ nsGenericHTMLElement::ColorToString(const nsHTMLValue& aValue,
|
|||
// XXX This creates a dependency between content and frames
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetPrimaryFrame(nsIHTMLContent* aContent,
|
||||
nsIFormControlFrame *&aFormControlFrame)
|
||||
nsIFormControlFrame *&aFormControlFrame,
|
||||
PRBool aFlushNotifications)
|
||||
{
|
||||
nsIDocument* doc = nsnull;
|
||||
nsresult res = NS_NOINTERFACE;
|
||||
// Get the document
|
||||
if (NS_OK == aContent->GetDocument(doc)) {
|
||||
if (nsnull != doc) {
|
||||
// Cause a flushing of notifications, so we get
|
||||
// up-to-date presentation information
|
||||
doc->FlushPendingNotifications();
|
||||
if (aFlushNotifications) {
|
||||
// Cause a flushing of notifications, so we get
|
||||
// up-to-date presentation information
|
||||
doc->FlushPendingNotifications();
|
||||
}
|
||||
|
||||
// Get presentation shell 0
|
||||
nsIPresShell* presShell = doc->GetShellAt(0);
|
||||
|
@ -1618,24 +1638,32 @@ nsGenericHTMLElement::GetPrimaryPresState(nsIHTMLContent* aContent,
|
|||
nsIStatefulFrame::StateType aStateType,
|
||||
nsIPresState** aPresState)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
// Get the document
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
aContent->GetDocument(*getter_AddRefs(doc));
|
||||
result = aContent->GetDocument(*getter_AddRefs(doc));
|
||||
if (doc) {
|
||||
// Get presentation shell 0
|
||||
nsCOMPtr<nsIPresShell> presShell = getter_AddRefs(doc->GetShellAt(0));
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsILayoutHistoryState> history;
|
||||
presShell->GetHistoryState(getter_AddRefs(history));
|
||||
result = presShell->GetHistoryState(getter_AddRefs(history));
|
||||
if (history) {
|
||||
PRUint32 ID;
|
||||
aContent->GetContentID(&ID);
|
||||
history->GetState(ID, aPresState, aStateType);
|
||||
result = history->GetState(ID, aPresState, aStateType);
|
||||
if (!*aPresState) {
|
||||
result = NS_NewPresState(aPresState);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = history->AddState(ID, *aPresState, aStateType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
// XXX This creates a dependency between content and frames
|
||||
|
@ -2941,12 +2969,15 @@ nsGenericHTMLContainerElement::InsertChildAt(nsIContent* aKid,
|
|||
PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aKid, "null ptr");
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
nsRange::OwnerChildInserted(mContent, aIndex);
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -2954,6 +2985,9 @@ nsGenericHTMLContainerElement::InsertChildAt(nsIContent* aKid,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2964,12 +2998,15 @@ nsGenericHTMLContainerElement::ReplaceChildAt(nsIContent* aKid,
|
|||
{
|
||||
NS_PRECONDITION(nsnull != aKid, "null ptr");
|
||||
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
nsRange::OwnerChildReplaced(mContent, aIndex, oldKid);
|
||||
PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex);
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -2980,6 +3017,9 @@ nsGenericHTMLContainerElement::ReplaceChildAt(nsIContent* aKid,
|
|||
oldKid->SetParent(nsnull);
|
||||
NS_RELEASE(oldKid);
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2987,12 +3027,15 @@ nsresult
|
|||
nsGenericHTMLContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION((nsnull != aKid) && (aKid != mContent), "null ptr");
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
PRBool rv = mChildren.AppendElement(aKid);
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
// ranges don't need adjustment since new child is at end of list
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -3000,15 +3043,21 @@ nsGenericHTMLContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
||||
{
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
|
||||
if (nsnull != oldKid ) {
|
||||
nsIDocument* doc = mDocument;
|
||||
nsRange::OwnerChildRemoved(mContent, aIndex, oldKid);
|
||||
mChildren.RemoveElementAt(aIndex);
|
||||
if (aNotify) {
|
||||
|
@ -3020,6 +3069,9 @@ nsGenericHTMLContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
|||
oldKid->SetParent(nsnull);
|
||||
NS_RELEASE(oldKid);
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -286,7 +286,8 @@ public:
|
|||
|
||||
//XXX These three create a dependency between content and frames
|
||||
static nsresult GetPrimaryFrame(nsIHTMLContent* aContent,
|
||||
nsIFormControlFrame *&aFormControlFrame);
|
||||
nsIFormControlFrame *&aFormControlFrame,
|
||||
PRBool aFlushNotifications=PR_TRUE);
|
||||
static nsresult GetPrimaryPresState(nsIHTMLContent* aContent,
|
||||
nsIStatefulFrame::StateType aStateType,
|
||||
nsIPresState** aPresState);
|
||||
|
|
|
@ -720,7 +720,7 @@ nsHTMLSelectElement::DoneAddingContent(PRBool aIsDone)
|
|||
{
|
||||
mIsDoneAddingContent = aIsDone;
|
||||
nsIFormControlFrame* fcFrame = nsnull;
|
||||
nsresult result = nsGenericHTMLElement::GetPrimaryFrame(this, fcFrame);
|
||||
nsresult result = nsGenericHTMLElement::GetPrimaryFrame(this, fcFrame,PR_FALSE);
|
||||
if (NS_SUCCEEDED(result) && (nsnull != fcFrame)) {
|
||||
nsISelectControlFrame* selectFrame = nsnull;
|
||||
result = fcFrame->QueryInterface(nsISelectControlFrame::GetIID(),(void **) &selectFrame);
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
|
||||
#include "nsIWebShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
@ -144,7 +145,8 @@ class SinkContext;
|
|||
class HTMLContentSink : public nsIHTMLContentSink,
|
||||
public nsIUnicharStreamLoaderObserver,
|
||||
public nsITimerCallback,
|
||||
public nsICSSLoaderObserver
|
||||
public nsICSSLoaderObserver,
|
||||
public nsIDocumentObserver
|
||||
{
|
||||
public:
|
||||
HTMLContentSink();
|
||||
|
@ -200,6 +202,62 @@ public:
|
|||
// nsICSSLoaderObserver
|
||||
NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify);
|
||||
|
||||
// nsIDocumentObserver
|
||||
NS_IMETHOD BeginUpdate(nsIDocument *aDocument);
|
||||
NS_IMETHOD EndUpdate(nsIDocument *aDocument);
|
||||
NS_IMETHOD BeginLoad(nsIDocument *aDocument) { return NS_OK; }
|
||||
NS_IMETHOD EndLoad(nsIDocument *aDocument) { return NS_OK; }
|
||||
NS_IMETHOD BeginReflow(nsIDocument *aDocument,
|
||||
nsIPresShell* aShell) { return NS_OK; }
|
||||
NS_IMETHOD EndReflow(nsIDocument *aDocument,
|
||||
nsIPresShell* aShell) { return NS_OK; }
|
||||
NS_IMETHOD ContentChanged(nsIDocument *aDocument,
|
||||
nsIContent* aContent,
|
||||
nsISupports* aSubContent) { return NS_OK; }
|
||||
NS_IMETHOD ContentStatesChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent1,
|
||||
nsIContent* aContent2) { return NS_OK; }
|
||||
NS_IMETHOD AttributeChanged(nsIDocument *aDocument,
|
||||
nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aHint) { return NS_OK; }
|
||||
NS_IMETHOD ContentAppended(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer)
|
||||
{ return NS_OK; }
|
||||
NS_IMETHOD ContentInserted(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer) { return NS_OK; }
|
||||
NS_IMETHOD ContentReplaced(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aOldChild,
|
||||
nsIContent* aNewChild,
|
||||
PRInt32 aIndexInContainer) { return NS_OK; }
|
||||
NS_IMETHOD ContentRemoved(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer) { return NS_OK; }
|
||||
NS_IMETHOD StyleSheetAdded(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet) { return NS_OK; }
|
||||
NS_IMETHOD StyleSheetRemoved(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet) { return NS_OK; }
|
||||
NS_IMETHOD StyleSheetDisabledStateChanged(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
PRBool aDisabled) { return NS_OK; }
|
||||
NS_IMETHOD StyleRuleChanged(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule,
|
||||
PRInt32 aHint) { return NS_OK; }
|
||||
NS_IMETHOD StyleRuleAdded(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule) { return NS_OK; }
|
||||
NS_IMETHOD StyleRuleRemoved(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule) { return NS_OK; }
|
||||
NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument) { return NS_OK; }
|
||||
|
||||
PRBool IsTimeToNotify();
|
||||
PRBool IsInScript();
|
||||
void ReduceEntities(nsString& aString);
|
||||
|
@ -243,6 +301,7 @@ public:
|
|||
|
||||
PRBool mLayoutStarted;
|
||||
PRInt32 mInScript;
|
||||
PRInt32 mInNotification;
|
||||
nsIDOMHTMLFormElement* mCurrentForm;
|
||||
nsIHTMLContent* mCurrentMap;
|
||||
|
||||
|
@ -344,7 +403,7 @@ public:
|
|||
{
|
||||
return FlushText(aDidFlush, PR_TRUE);
|
||||
}
|
||||
nsresult FlushTags();
|
||||
nsresult FlushTags(PRBool aNotify = PR_TRUE);
|
||||
|
||||
PRBool IsCurrentContainer(nsHTMLTag mType);
|
||||
PRBool IsAncestorContainer(nsHTMLTag mType);
|
||||
|
@ -1152,7 +1211,7 @@ SinkContext::DidAddContent(nsIContent* aContent, PRBool aDidNotify)
|
|||
else if (!aDidNotify && mSink->IsTimeToNotify()) {
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("SinkContext::DidAddContent: Notification as a result of the interval expiring; backoff count: %d", mSink->mBackoffCount));
|
||||
FlushTags();
|
||||
FlushTags(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1210,10 +1269,10 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
|
|||
if (mStack[mStackPos-1].mInsertionPoint != -1) {
|
||||
parent->InsertChildAt(content,
|
||||
mStack[mStackPos-1].mInsertionPoint++,
|
||||
mSink->IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
parent->AppendChildTo(content, mSink->IsInScript());
|
||||
parent->AppendChildTo(content, PR_FALSE);
|
||||
}
|
||||
mStack[mStackPos].mFlags |= APPENDED;
|
||||
}
|
||||
|
@ -1287,10 +1346,10 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
if (mStack[mStackPos-1].mInsertionPoint != -1) {
|
||||
result = parent->InsertChildAt(content,
|
||||
mStack[mStackPos-1].mInsertionPoint++,
|
||||
mSink->IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
result = parent->AppendChildTo(content, mSink->IsInScript());
|
||||
result = parent->AppendChildTo(content, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1324,7 +1383,7 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
mNotifyLevel = mStackPos-1;
|
||||
}
|
||||
|
||||
DidAddContent(content, mSink->IsInScript());
|
||||
DidAddContent(content, PR_FALSE);
|
||||
|
||||
|
||||
// Special handling for certain tags
|
||||
|
@ -1434,7 +1493,7 @@ SinkContext::DemoteContainer(const nsIParserNode& aNode)
|
|||
// with later.
|
||||
parent->ChildCount(parentCount);
|
||||
if (mStack[stackPos-1].mNumFlushed == parentCount) {
|
||||
FlushTags();
|
||||
FlushTags(PR_TRUE);
|
||||
sync = PR_TRUE;
|
||||
}
|
||||
// Otherwise just append the container to the parent without
|
||||
|
@ -1601,13 +1660,13 @@ SinkContext::AddLeaf(nsIHTMLContent* aContent)
|
|||
if (mStack[mStackPos-1].mInsertionPoint != -1) {
|
||||
parent->InsertChildAt(aContent,
|
||||
mStack[mStackPos-1].mInsertionPoint++,
|
||||
mSink->IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
parent->AppendChildTo(aContent, mSink->IsInScript());
|
||||
parent->AppendChildTo(aContent, PR_FALSE);
|
||||
}
|
||||
|
||||
DidAddContent(aContent, mSink->IsInScript());
|
||||
DidAddContent(aContent, PR_FALSE);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mPreAppend &&
|
||||
|
@ -1653,13 +1712,13 @@ SinkContext::AddComment(const nsIParserNode& aNode)
|
|||
if (mStack[mStackPos-1].mInsertionPoint != -1) {
|
||||
parent->InsertChildAt(comment,
|
||||
mStack[mStackPos-1].mInsertionPoint++,
|
||||
mSink->IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
parent->AppendChildTo(comment, mSink->IsInScript());
|
||||
parent->AppendChildTo(comment, PR_FALSE);
|
||||
}
|
||||
|
||||
DidAddContent(comment, mSink->IsInScript());
|
||||
DidAddContent(comment, PR_FALSE);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mPreAppend &&
|
||||
|
@ -1764,7 +1823,7 @@ SinkContext::AddText(const nsString& aText)
|
|||
* has been newly added so that the frame tree is complete.
|
||||
*/
|
||||
nsresult
|
||||
SinkContext::FlushTags()
|
||||
SinkContext::FlushTags(PRBool aNotify)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
|
@ -1796,47 +1855,49 @@ SinkContext::FlushTags()
|
|||
stackPos--;
|
||||
}
|
||||
|
||||
// Start from the base of the stack (growing upward) and do
|
||||
// a notification from the node that is closest to the root of
|
||||
// tree for any content that has been added.
|
||||
stackPos = 1;
|
||||
PRBool flushed = PR_FALSE;
|
||||
while (stackPos < mStackPos) {
|
||||
content = mStack[stackPos].mContent;
|
||||
content->ChildCount(childCount);
|
||||
if (aNotify) {
|
||||
// Start from the base of the stack (growing upward) and do
|
||||
// a notification from the node that is closest to the root of
|
||||
// tree for any content that has been added.
|
||||
stackPos = 1;
|
||||
PRBool flushed = PR_FALSE;
|
||||
while (stackPos < mStackPos) {
|
||||
content = mStack[stackPos].mContent;
|
||||
content->ChildCount(childCount);
|
||||
|
||||
if (!flushed && (mStack[stackPos].mNumFlushed < childCount)) {
|
||||
if (!flushed && (mStack[stackPos].mNumFlushed < childCount)) {
|
||||
#ifdef NS_DEBUG
|
||||
// Tracing code
|
||||
char cbuf[40];
|
||||
const char* cp;
|
||||
nsAutoString str;
|
||||
nsCOMPtr<nsIDTD> dtd;
|
||||
mSink->mParser->GetDTD(getter_AddRefs(dtd));
|
||||
dtd->IntTagToStringTag(nsHTMLTag(mStack[stackPos].mType), str);
|
||||
cp = str.ToCString(cbuf, sizeof(cbuf));
|
||||
// Tracing code
|
||||
char cbuf[40];
|
||||
const char* cp;
|
||||
nsAutoString str;
|
||||
nsCOMPtr<nsIDTD> dtd;
|
||||
mSink->mParser->GetDTD(getter_AddRefs(dtd));
|
||||
dtd->IntTagToStringTag(nsHTMLTag(mStack[stackPos].mType), str);
|
||||
cp = str.ToCString(cbuf, sizeof(cbuf));
|
||||
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("SinkContext::FlushTags: tag=%s from newindex=%d at stackPos=%d",
|
||||
cp, mStack[stackPos].mNumFlushed, stackPos));
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("SinkContext::FlushTags: tag=%s from newindex=%d at stackPos=%d",
|
||||
cp, mStack[stackPos].mNumFlushed, stackPos));
|
||||
#endif
|
||||
if ((mStack[stackPos].mInsertionPoint != -1) &&
|
||||
(mStackPos > (stackPos+1))) {
|
||||
nsIContent* child = mStack[stackPos+1].mContent;
|
||||
mSink->NotifyInsert(content,
|
||||
child,
|
||||
mStack[stackPos].mInsertionPoint);
|
||||
if ((mStack[stackPos].mInsertionPoint != -1) &&
|
||||
(mStackPos > (stackPos+1))) {
|
||||
nsIContent* child = mStack[stackPos+1].mContent;
|
||||
mSink->NotifyInsert(content,
|
||||
child,
|
||||
mStack[stackPos].mInsertionPoint);
|
||||
}
|
||||
else {
|
||||
mSink->NotifyAppend(content, mStack[stackPos].mNumFlushed);
|
||||
}
|
||||
flushed = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
mSink->NotifyAppend(content, mStack[stackPos].mNumFlushed);
|
||||
}
|
||||
flushed = PR_TRUE;
|
||||
}
|
||||
|
||||
mStack[stackPos].mNumFlushed = childCount;
|
||||
stackPos++;
|
||||
mStack[stackPos].mNumFlushed = childCount;
|
||||
stackPos++;
|
||||
}
|
||||
mNotifyLevel = mStackPos-1;
|
||||
}
|
||||
mNotifyLevel = mStackPos-1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1907,10 +1968,10 @@ SinkContext::FlushText(PRBool* aDidFlush, PRBool aReleaseLast)
|
|||
if (mStack[mStackPos-1].mInsertionPoint != -1) {
|
||||
parent->InsertChildAt(content,
|
||||
mStack[mStackPos-1].mInsertionPoint++,
|
||||
mSink->IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
parent->AppendChildTo(content, mSink->IsInScript());
|
||||
parent->AppendChildTo(content, PR_FALSE);
|
||||
}
|
||||
|
||||
mLastTextNode = content;
|
||||
|
@ -1918,7 +1979,7 @@ SinkContext::FlushText(PRBool* aDidFlush, PRBool aReleaseLast)
|
|||
mTextLength = 0;
|
||||
didFlush = PR_TRUE;
|
||||
|
||||
DidAddContent(content, mSink->IsInScript());
|
||||
DidAddContent(content, PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1972,6 +2033,7 @@ HTMLContentSink::HTMLContentSink() {
|
|||
mNotAtRef = PR_TRUE;
|
||||
mContentIDCounter = NS_CONTENT_ID_COUNTER_BASE;
|
||||
mInScript = 0;
|
||||
mInNotification = 0;
|
||||
mInsideNoXXXTag = 0;
|
||||
}
|
||||
|
||||
|
@ -1982,7 +2044,10 @@ HTMLContentSink::~HTMLContentSink()
|
|||
NS_IF_RELEASE(mFrameset);
|
||||
NS_IF_RELEASE(mRoot);
|
||||
|
||||
NS_IF_RELEASE(mDocument);
|
||||
if (mDocument) {
|
||||
mDocument->RemoveObserver(this);
|
||||
NS_RELEASE(mDocument);
|
||||
}
|
||||
NS_IF_RELEASE(mHTMLDocument);
|
||||
NS_IF_RELEASE(mDocumentURI);
|
||||
NS_IF_RELEASE(mDocumentBaseURL);
|
||||
|
@ -2033,12 +2098,13 @@ HTMLContentSink::~HTMLContentSink()
|
|||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS5(HTMLContentSink,
|
||||
NS_IMPL_ISUPPORTS6(HTMLContentSink,
|
||||
nsIHTMLContentSink,
|
||||
nsIContentSink,
|
||||
nsIUnicharStreamLoaderObserver,
|
||||
nsITimerCallback,
|
||||
nsICSSLoaderObserver)
|
||||
nsICSSLoaderObserver,
|
||||
nsIDocumentObserver)
|
||||
|
||||
nsresult
|
||||
HTMLContentSink::Init(nsIDocument* aDoc,
|
||||
|
@ -2060,6 +2126,7 @@ HTMLContentSink::Init(nsIDocument* aDoc,
|
|||
|
||||
mDocument = aDoc;
|
||||
NS_ADDREF(aDoc);
|
||||
aDoc->AddObserver(this);
|
||||
aDoc->QueryInterface(kIHTMLDocumentIID, (void**)&mHTMLDocument);
|
||||
mDocumentURI = aURL;
|
||||
NS_ADDREF(aURL);
|
||||
|
@ -2187,7 +2254,7 @@ HTMLContentSink::DidBuildModel(PRInt32 aQualityLevel)
|
|||
if (nsnull != mBody) {
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("HTMLContentSink::DidBuildModel: layout final content"));
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
ScrollToRef();
|
||||
|
||||
|
@ -2220,7 +2287,7 @@ HTMLContentSink::Notify(nsITimer *timer)
|
|||
("HTMLContentSink::Notify: reflow on a timer: %d milliseconds late, backoff count: %d", delay, mBackoffCount));
|
||||
#endif
|
||||
if (mCurrentContext) {
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
mNotificationTimer = 0;
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::Notify()\n"));
|
||||
|
@ -2251,7 +2318,7 @@ HTMLContentSink::WillInterrupt()
|
|||
mBackoffCount--;
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("HTMLContentSink::WillInterrupt: flushing tags since we've run out time; backoff count: %d", mBackoffCount));
|
||||
result = mCurrentContext->FlushTags();
|
||||
result = mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
else {
|
||||
// If the time since the last notification is less than
|
||||
|
@ -2289,7 +2356,7 @@ HTMLContentSink::WillInterrupt()
|
|||
else {
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("HTMLContentSink::WillInterrupt: flushing tags unconditionally"));
|
||||
result = mCurrentContext->FlushTags();
|
||||
result = mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -2343,7 +2410,7 @@ HTMLContentSink::BeginContext(PRInt32 aPosition)
|
|||
}
|
||||
// Flush everything in the current context so that we don't have
|
||||
// to worry about insertions resulting in inconsistent frame creation.
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_TRUE);
|
||||
|
||||
PRInt32 insertionPoint = -1;
|
||||
nsHTMLTag nodeType = mCurrentContext->mStack[aPosition].mType;
|
||||
|
@ -2477,8 +2544,8 @@ HTMLContentSink::CloseHTML(const nsIParserNode& aNode)
|
|||
if(mCurrentContext==mHeadContext) {
|
||||
PRInt32 numContexts = mContextStack.Count();
|
||||
// Pop off the second html context if it's not done earlier
|
||||
mContextStack.RemoveElementAt(--numContexts);
|
||||
mCurrentContext = nsnull;
|
||||
mCurrentContext = (SinkContext*)mContextStack.ElementAt(--numContexts);
|
||||
mContextStack.RemoveElementAt(numContexts);
|
||||
}
|
||||
mHeadContext->End();
|
||||
delete mHeadContext;
|
||||
|
@ -2596,7 +2663,7 @@ HTMLContentSink::CloseBody(const nsIParserNode& aNode)
|
|||
// Flush out anything that's left
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("HTMLContentSink::CloseBody: layout final body content"));
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_TRUE);
|
||||
mCurrentContext->CloseContainer(aNode);
|
||||
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::CloseBody()\n"));
|
||||
|
@ -3770,7 +3837,7 @@ IsJavaScriptLanguage(const nsString& aName, const char* *aVersion)
|
|||
void
|
||||
HTMLContentSink::ForceReflow()
|
||||
{
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3778,6 +3845,7 @@ HTMLContentSink::ForceReflow()
|
|||
void
|
||||
HTMLContentSink::NotifyAppend(nsIContent* aContainer, PRInt32 aStartIndex)
|
||||
{
|
||||
mInNotification++;
|
||||
MOZ_TIMER_DEBUGLOG(("Save and stop: nsHTMLContentSink::NotifyAppend()\n"));
|
||||
MOZ_TIMER_SAVE(mWatch)
|
||||
MOZ_TIMER_STOP(mWatch);
|
||||
|
@ -3785,6 +3853,7 @@ HTMLContentSink::NotifyAppend(nsIContent* aContainer, PRInt32 aStartIndex)
|
|||
mLastNotificationTime = PR_Now();
|
||||
MOZ_TIMER_DEBUGLOG(("Restore: nsHTMLContentSink::NotifyAppend()\n"));
|
||||
MOZ_TIMER_RESTORE(mWatch);
|
||||
mInNotification--;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3792,6 +3861,7 @@ HTMLContentSink::NotifyInsert(nsIContent* aContent,
|
|||
nsIContent* aChildContent,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
mInNotification++;
|
||||
MOZ_TIMER_DEBUGLOG(("Save and stop: nsHTMLContentSink::NotifyInsert()\n"));
|
||||
MOZ_TIMER_SAVE(mWatch)
|
||||
MOZ_TIMER_STOP(mWatch);
|
||||
|
@ -3799,6 +3869,7 @@ HTMLContentSink::NotifyInsert(nsIContent* aContent,
|
|||
mLastNotificationTime = PR_Now();
|
||||
MOZ_TIMER_DEBUGLOG(("Restore: nsHTMLContentSink::NotifyInsert()\n"));
|
||||
MOZ_TIMER_RESTORE(mWatch);
|
||||
mInNotification--;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -3835,6 +3906,37 @@ HTMLContentSink::UpdateAllContexts()
|
|||
mCurrentContext->UpdateChildCounts();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLContentSink::BeginUpdate(nsIDocument *aDocument)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
// If we're in a script and we didn't do the notification,
|
||||
// something else in the script processing caused the
|
||||
// notification to occur. Since this could result in frame
|
||||
// creation, make sure we've flushed everything before we
|
||||
// continue
|
||||
if (mInScript && !mInNotification && mCurrentContext) {
|
||||
result = mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLContentSink::EndUpdate(nsIDocument *aDocument)
|
||||
{
|
||||
|
||||
// If we're in a script and we didn't do the notification,
|
||||
// something else in the script processing caused the
|
||||
// notification to occur. Update our notion of how much
|
||||
// has been flushed to include any new content.
|
||||
if (mInScript && !mInNotification) {
|
||||
UpdateAllContexts();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLContentSink::ResumeParsing()
|
||||
{
|
||||
|
@ -3853,10 +3955,12 @@ HTMLContentSink::PreEvaluateScript()
|
|||
// to the body (so that they can be seen by scripts) and force reflow.
|
||||
SINK_TRACE(SINK_TRACE_CALLS,
|
||||
("HTMLContentSink::PreEvaluateScript: flushing tags before evaluating script"));
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_FALSE);
|
||||
mCurrentContext->SetPreAppend(PR_TRUE);
|
||||
|
||||
mInScript++;
|
||||
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -3864,8 +3968,7 @@ void
|
|||
HTMLContentSink::PostEvaluateScript(PRBool aBodyPresent)
|
||||
{
|
||||
mInScript--;
|
||||
|
||||
mCurrentContext->UpdateChildCounts();
|
||||
mCurrentContext->SetPreAppend(PR_FALSE);
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -4019,10 +4122,10 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
|
|||
if (mCurrentContext->mStack[mCurrentContext->mStackPos-1].mInsertionPoint != -1) {
|
||||
parent->InsertChildAt(element,
|
||||
mCurrentContext->mStack[mCurrentContext->mStackPos-1].mInsertionPoint++,
|
||||
IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
parent->AppendChildTo(element, IsInScript());
|
||||
parent->AppendChildTo(element, PR_FALSE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -4044,7 +4147,7 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
|
|||
tc->SetData(script);
|
||||
NS_RELEASE(tc);
|
||||
}
|
||||
element->AppendChildTo(text, IsInScript());
|
||||
element->AppendChildTo(text, PR_FALSE);
|
||||
text->SetDocument(mDocument, PR_FALSE);
|
||||
NS_RELEASE(text);
|
||||
}
|
||||
|
@ -4201,7 +4304,7 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode)
|
|||
tc->SetData(content);
|
||||
NS_RELEASE(tc);
|
||||
}
|
||||
element->AppendChildTo(text, IsInScript());
|
||||
element->AppendChildTo(text, PR_FALSE);
|
||||
text->SetDocument(mDocument, PR_FALSE);
|
||||
NS_RELEASE(text);
|
||||
}
|
||||
|
@ -4262,13 +4365,15 @@ HTMLContentSink::NotifyError(const nsParserError* aError)
|
|||
NS_IMETHODIMP
|
||||
HTMLContentSink::FlushPendingNotifications()
|
||||
{
|
||||
/* XXX This is temporarily commented out so that this change can be tested locally.
|
||||
nsresult result = NS_OK;
|
||||
if (mCurrentContext) {
|
||||
// Only flush tags if we're not doing the notification ourselves
|
||||
// (since we aren't reentrant) and if we're in a script (since
|
||||
// we only care to flush if this is done via script).
|
||||
if (mCurrentContext && !mInNotification && mInScript) {
|
||||
result = mCurrentContext->FlushTags();
|
||||
}
|
||||
*/
|
||||
return NS_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -1294,6 +1294,34 @@ nsXULDocument::RemoveObserver(nsIDocumentObserver* aObserver)
|
|||
return mObservers.RemoveElement(aObserver);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::BeginUpdate()
|
||||
{
|
||||
// XXX Never called. Does this matter?
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::EndUpdate()
|
||||
{
|
||||
// XXX Never called. Does this matter?
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->EndUpdate(this);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::BeginLoad()
|
||||
{
|
||||
|
|
|
@ -191,6 +191,10 @@ public:
|
|||
|
||||
virtual PRBool RemoveObserver(nsIDocumentObserver* aObserver);
|
||||
|
||||
NS_IMETHOD BeginUpdate();
|
||||
|
||||
NS_IMETHOD EndUpdate();
|
||||
|
||||
NS_IMETHOD BeginLoad();
|
||||
|
||||
NS_IMETHOD EndLoad();
|
||||
|
|
|
@ -240,6 +240,8 @@ public:
|
|||
|
||||
// Observation hooks used by content nodes to propagate
|
||||
// notifications to document observers.
|
||||
NS_IMETHOD BeginUpdate() = 0;
|
||||
NS_IMETHOD EndUpdate() = 0;
|
||||
NS_IMETHOD BeginLoad() = 0;
|
||||
NS_IMETHOD EndLoad() = 0;
|
||||
NS_IMETHOD ContentChanged(nsIContent* aContent,
|
||||
|
|
|
@ -1463,6 +1463,42 @@ PRBool nsDocument::RemoveObserver(nsIDocumentObserver* aObserver)
|
|||
return (mObservers.IndexOf(aObserver) != -1);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::BeginUpdate()
|
||||
{
|
||||
PRInt32 i;
|
||||
// Get new value of count for every iteration in case
|
||||
// observers remove themselves during the loop.
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
// Make sure that the observer didn't remove itself during the
|
||||
// notification. If it did, update our index and count.
|
||||
if (observer != (nsIDocumentObserver*)mObservers[i]) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::EndUpdate()
|
||||
{
|
||||
PRInt32 i;
|
||||
// Get new value of count for every iteration in case
|
||||
// observers remove themselves during the loop.
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->EndUpdate(this);
|
||||
// Make sure that the observer didn't remove itself during the
|
||||
// notification. If it did, update our index and count.
|
||||
if (observer != (nsIDocumentObserver*)mObservers[i]) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocument::BeginLoad()
|
||||
{
|
||||
|
@ -1651,12 +1687,16 @@ nsDocument::StyleRuleChanged(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRul
|
|||
// observers remove themselves during the loop.
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
observer->StyleRuleChanged(this, aStyleSheet, aStyleRule, aHint);
|
||||
// Make sure that the observer didn't remove itself during the
|
||||
// notification. If it did, update our index and count.
|
||||
if (observer != (nsIDocumentObserver*)mObservers[i]) {
|
||||
i--;
|
||||
}
|
||||
else {
|
||||
observer->EndUpdate(this);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1669,12 +1709,16 @@ nsDocument::StyleRuleAdded(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule)
|
|||
// observers remove themselves during the loop.
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
observer->StyleRuleAdded(this, aStyleSheet, aStyleRule);
|
||||
// Make sure that the observer didn't remove itself during the
|
||||
// notification. If it did, update our index and count.
|
||||
if (observer != (nsIDocumentObserver*)mObservers[i]) {
|
||||
i--;
|
||||
}
|
||||
else {
|
||||
observer->EndUpdate(this);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1687,12 +1731,16 @@ nsDocument::StyleRuleRemoved(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRul
|
|||
// observers remove themselves during the loop.
|
||||
for (i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*)mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
observer->StyleRuleRemoved(this, aStyleSheet, aStyleRule);
|
||||
// Make sure that the observer didn't remove itself during the
|
||||
// notification. If it did, update our index and count.
|
||||
if (observer != (nsIDocumentObserver*)mObservers[i]) {
|
||||
i--;
|
||||
}
|
||||
else {
|
||||
observer->EndUpdate(this);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1004,11 +1004,15 @@ nsGenericDOMDataNode::SetText(const PRUnichar* aBuffer, PRInt32 aLength,
|
|||
if (nsnull == aBuffer) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->BeginUpdate();
|
||||
}
|
||||
mText.SetTo(aBuffer, aLength);
|
||||
|
||||
// Trigger a reflow
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->ContentChanged(mContent, nsnull);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1025,11 +1029,15 @@ nsGenericDOMDataNode::SetText(const char* aBuffer,
|
|||
if (nsnull == aBuffer) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->BeginUpdate();
|
||||
}
|
||||
mText.SetTo(aBuffer, aLength);
|
||||
|
||||
// Trigger a reflow
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->ContentChanged(mContent, nsnull);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -1868,6 +1868,11 @@ nsGenericContainerElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
if (nsnull == mAttributes) {
|
||||
mAttributes = new nsVoidArray();
|
||||
}
|
||||
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->BeginUpdate();
|
||||
}
|
||||
|
||||
if (nsnull != mAttributes) {
|
||||
nsGenericAttribute* attr;
|
||||
PRInt32 index;
|
||||
|
@ -1890,8 +1895,11 @@ nsGenericContainerElement::SetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
}
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && aNotify && (nsnull != mDocument)) {
|
||||
mDocument->AttributeChanged(mContent, aNameSpaceID, aName, NS_STYLE_HINT_UNKNOWN);
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mDocument->AttributeChanged(mContent, aNameSpaceID, aName, NS_STYLE_HINT_UNKNOWN);
|
||||
}
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
@ -1957,6 +1965,9 @@ nsGenericContainerElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
nsGenericAttribute* attr = (nsGenericAttribute*)mAttributes->ElementAt(index);
|
||||
if (((kNameSpaceID_Unknown == aNameSpaceID) || (attr->mNameSpaceID == aNameSpaceID)) &&
|
||||
(attr->mName == aName)) {
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->BeginUpdate();
|
||||
}
|
||||
mAttributes->RemoveElementAt(index);
|
||||
delete attr;
|
||||
found = PR_TRUE;
|
||||
|
@ -1966,6 +1977,7 @@ nsGenericContainerElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||
|
||||
if (NS_SUCCEEDED(rv) && found && aNotify && (nsnull != mDocument)) {
|
||||
mDocument->AttributeChanged(mContent, aNameSpaceID, aName, NS_STYLE_HINT_UNKNOWN);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2117,12 +2129,15 @@ nsGenericContainerElement::InsertChildAt(nsIContent* aKid,
|
|||
PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aKid, "null ptr");
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
nsRange::OwnerChildInserted(mContent, aIndex);
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -2130,6 +2145,9 @@ nsGenericContainerElement::InsertChildAt(nsIContent* aKid,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2139,13 +2157,16 @@ nsGenericContainerElement::ReplaceChildAt(nsIContent* aKid,
|
|||
PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aKid, "null ptr");
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
|
||||
nsRange::OwnerChildReplaced(mContent, aIndex, oldKid);
|
||||
PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex);
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -2156,6 +2177,9 @@ nsGenericContainerElement::ReplaceChildAt(nsIContent* aKid,
|
|||
oldKid->SetParent(nsnull);
|
||||
NS_RELEASE(oldKid);
|
||||
}
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2163,12 +2187,15 @@ nsresult
|
|||
nsGenericContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION((nsnull != aKid) && (aKid != mContent), "null ptr");
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
PRBool rv = mChildren.AppendElement(aKid);
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
// ranges don't need adjustment since new child is at end of list
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -2176,6 +2203,9 @@ nsGenericContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2185,6 +2215,9 @@ nsGenericContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
|||
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
|
||||
if (nsnull != oldKid ) {
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
nsRange::OwnerChildRemoved(mContent, aIndex, oldKid);
|
||||
mChildren.RemoveElementAt(aIndex);
|
||||
if (aNotify) {
|
||||
|
@ -2195,6 +2228,9 @@ nsGenericContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
|||
oldKid->SetDocument(nsnull, PR_TRUE);
|
||||
oldKid->SetParent(nsnull);
|
||||
NS_RELEASE(oldKid);
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
|
|
@ -2085,6 +2085,7 @@ nsEventStateManager::SetContentState(nsIContent *aContent, PRInt32 aState)
|
|||
nsIDocument *document; // this presumes content can't get/lose state if not connected to doc
|
||||
notifyContent[0]->GetDocument(document);
|
||||
if (document) {
|
||||
document->BeginUpdate();
|
||||
document->ContentStatesChanged(notifyContent[0], notifyContent[1]);
|
||||
if (notifyContent[2]) { // more that two notifications are needed (should be rare)
|
||||
// XXX a further optimization here would be to group the notification pairs
|
||||
|
@ -2095,6 +2096,7 @@ nsEventStateManager::SetContentState(nsIContent *aContent, PRInt32 aState)
|
|||
document->ContentStatesChanged(notifyContent[4], nsnull);
|
||||
}
|
||||
}
|
||||
document->EndUpdate();
|
||||
NS_RELEASE(document);
|
||||
}
|
||||
|
||||
|
|
|
@ -217,11 +217,15 @@ nsDOMCSSAttributeDeclaration::ParseDeclaration(const nsString& aDecl)
|
|||
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
PRInt32 hint;
|
||||
if (doc) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, &hint);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
if (doc) {
|
||||
if (doc) {
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
doc->AttributeChanged(mContent, kNameSpaceID_None, nsHTMLAtoms::style, hint);
|
||||
}
|
||||
doc->EndUpdate();
|
||||
}
|
||||
if (cssLoader) {
|
||||
cssLoader->RecycleParser(cssParser);
|
||||
|
@ -700,6 +704,10 @@ nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
|
|||
NS_RELEASE(htmlContent);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->BeginUpdate();
|
||||
}
|
||||
// set as string value to avoid another string copy
|
||||
PRBool impact = NS_STYLE_HINT_NONE;
|
||||
htmlContent->GetMappedAttributeImpact(aAttribute, impact);
|
||||
|
@ -729,6 +737,7 @@ nsGenericHTMLElement::SetAttribute(PRInt32 aNameSpaceID,
|
|||
|
||||
if (aNotify && (nsnull != mDocument)) {
|
||||
mDocument->AttributeChanged(mContent, aNameSpaceID, aAttribute, NS_STYLE_HINT_UNKNOWN);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -771,15 +780,18 @@ nsGenericHTMLElement::SetHTMLAttribute(nsIAtom* aAttribute,
|
|||
PRBool impact = NS_STYLE_HINT_NONE;
|
||||
htmlContent->GetMappedAttributeImpact(aAttribute, impact);
|
||||
if (nsnull != mDocument) { // set attr via style sheet
|
||||
if (aNotify && (nsHTMLAtoms::style == aAttribute)) {
|
||||
nsHTMLValue oldValue;
|
||||
PRInt32 oldImpact = NS_STYLE_HINT_NONE;
|
||||
if (NS_CONTENT_ATTR_NOT_THERE != GetHTMLAttribute(aAttribute, oldValue)) {
|
||||
oldImpact = GetStyleImpactFrom(oldValue);
|
||||
}
|
||||
impact = GetStyleImpactFrom(aValue);
|
||||
if (impact < oldImpact) {
|
||||
impact = oldImpact;
|
||||
if (aNotify) {
|
||||
mDocument->BeginUpdate();
|
||||
if (nsHTMLAtoms::style == aAttribute) {
|
||||
nsHTMLValue oldValue;
|
||||
PRInt32 oldImpact = NS_STYLE_HINT_NONE;
|
||||
if (NS_CONTENT_ATTR_NOT_THERE != GetHTMLAttribute(aAttribute, oldValue)) {
|
||||
oldImpact = GetStyleImpactFrom(oldValue);
|
||||
}
|
||||
impact = GetStyleImpactFrom(aValue);
|
||||
if (impact < oldImpact) {
|
||||
impact = oldImpact;
|
||||
}
|
||||
}
|
||||
}
|
||||
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
|
||||
|
@ -791,6 +803,7 @@ nsGenericHTMLElement::SetHTMLAttribute(nsIAtom* aAttribute,
|
|||
}
|
||||
if (aNotify) {
|
||||
mDocument->AttributeChanged(mContent, kNameSpaceID_None, aAttribute, impact);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
}
|
||||
else { // manage this ourselves and re-sync when we connect to doc
|
||||
|
@ -833,13 +846,16 @@ nsGenericHTMLElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
|||
}
|
||||
if (nsnull != mDocument) { // set attr via style sheet
|
||||
PRInt32 impact = NS_STYLE_HINT_UNKNOWN;
|
||||
if (aNotify && (nsHTMLAtoms::style == aAttribute)) {
|
||||
nsHTMLValue oldValue;
|
||||
if (NS_CONTENT_ATTR_NOT_THERE != GetHTMLAttribute(aAttribute, oldValue)) {
|
||||
impact = GetStyleImpactFrom(oldValue);
|
||||
}
|
||||
else {
|
||||
impact = NS_STYLE_HINT_NONE;
|
||||
if (aNotify) {
|
||||
mDocument->BeginUpdate();
|
||||
if (nsHTMLAtoms::style == aAttribute) {
|
||||
nsHTMLValue oldValue;
|
||||
if (NS_CONTENT_ATTR_NOT_THERE != GetHTMLAttribute(aAttribute, oldValue)) {
|
||||
impact = GetStyleImpactFrom(oldValue);
|
||||
}
|
||||
else {
|
||||
impact = NS_STYLE_HINT_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
nsIHTMLStyleSheet* sheet = GetAttrStyleSheet(mDocument);
|
||||
|
@ -849,6 +865,7 @@ nsGenericHTMLElement::UnsetAttribute(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
|
|||
}
|
||||
if (aNotify) {
|
||||
mDocument->AttributeChanged(mContent, aNameSpaceID, aAttribute, impact);
|
||||
mDocument->EndUpdate();
|
||||
}
|
||||
}
|
||||
else { // manage this ourselves and re-sync when we connect to doc
|
||||
|
@ -1585,16 +1602,19 @@ nsGenericHTMLElement::ColorToString(const nsHTMLValue& aValue,
|
|||
// XXX This creates a dependency between content and frames
|
||||
nsresult
|
||||
nsGenericHTMLElement::GetPrimaryFrame(nsIHTMLContent* aContent,
|
||||
nsIFormControlFrame *&aFormControlFrame)
|
||||
nsIFormControlFrame *&aFormControlFrame,
|
||||
PRBool aFlushNotifications)
|
||||
{
|
||||
nsIDocument* doc = nsnull;
|
||||
nsresult res = NS_NOINTERFACE;
|
||||
// Get the document
|
||||
if (NS_OK == aContent->GetDocument(doc)) {
|
||||
if (nsnull != doc) {
|
||||
// Cause a flushing of notifications, so we get
|
||||
// up-to-date presentation information
|
||||
doc->FlushPendingNotifications();
|
||||
if (aFlushNotifications) {
|
||||
// Cause a flushing of notifications, so we get
|
||||
// up-to-date presentation information
|
||||
doc->FlushPendingNotifications();
|
||||
}
|
||||
|
||||
// Get presentation shell 0
|
||||
nsIPresShell* presShell = doc->GetShellAt(0);
|
||||
|
@ -1618,24 +1638,32 @@ nsGenericHTMLElement::GetPrimaryPresState(nsIHTMLContent* aContent,
|
|||
nsIStatefulFrame::StateType aStateType,
|
||||
nsIPresState** aPresState)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
// Get the document
|
||||
nsCOMPtr<nsIDocument> doc;
|
||||
aContent->GetDocument(*getter_AddRefs(doc));
|
||||
result = aContent->GetDocument(*getter_AddRefs(doc));
|
||||
if (doc) {
|
||||
// Get presentation shell 0
|
||||
nsCOMPtr<nsIPresShell> presShell = getter_AddRefs(doc->GetShellAt(0));
|
||||
if (presShell) {
|
||||
nsCOMPtr<nsILayoutHistoryState> history;
|
||||
presShell->GetHistoryState(getter_AddRefs(history));
|
||||
result = presShell->GetHistoryState(getter_AddRefs(history));
|
||||
if (history) {
|
||||
PRUint32 ID;
|
||||
aContent->GetContentID(&ID);
|
||||
history->GetState(ID, aPresState, aStateType);
|
||||
result = history->GetState(ID, aPresState, aStateType);
|
||||
if (!*aPresState) {
|
||||
result = NS_NewPresState(aPresState);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
result = history->AddState(ID, *aPresState, aStateType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
// XXX This creates a dependency between content and frames
|
||||
|
@ -2941,12 +2969,15 @@ nsGenericHTMLContainerElement::InsertChildAt(nsIContent* aKid,
|
|||
PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION(nsnull != aKid, "null ptr");
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
PRBool rv = mChildren.InsertElementAt(aKid, aIndex);/* XXX fix up void array api to use nsresult's*/
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
nsRange::OwnerChildInserted(mContent, aIndex);
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -2954,6 +2985,9 @@ nsGenericHTMLContainerElement::InsertChildAt(nsIContent* aKid,
|
|||
}
|
||||
}
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2964,12 +2998,15 @@ nsGenericHTMLContainerElement::ReplaceChildAt(nsIContent* aKid,
|
|||
{
|
||||
NS_PRECONDITION(nsnull != aKid, "null ptr");
|
||||
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
nsRange::OwnerChildReplaced(mContent, aIndex, oldKid);
|
||||
PRBool rv = mChildren.ReplaceElementAt(aKid, aIndex);
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -2980,6 +3017,9 @@ nsGenericHTMLContainerElement::ReplaceChildAt(nsIContent* aKid,
|
|||
oldKid->SetParent(nsnull);
|
||||
NS_RELEASE(oldKid);
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2987,12 +3027,15 @@ nsresult
|
|||
nsGenericHTMLContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
||||
{
|
||||
NS_PRECONDITION((nsnull != aKid) && (aKid != mContent), "null ptr");
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
PRBool rv = mChildren.AppendElement(aKid);
|
||||
if (rv) {
|
||||
NS_ADDREF(aKid);
|
||||
aKid->SetParent(mContent);
|
||||
// ranges don't need adjustment since new child is at end of list
|
||||
nsIDocument* doc = mDocument;
|
||||
if (nsnull != doc) {
|
||||
aKid->SetDocument(doc, PR_FALSE);
|
||||
if (aNotify) {
|
||||
|
@ -3000,15 +3043,21 @@ nsGenericHTMLContainerElement::AppendChildTo(nsIContent* aKid, PRBool aNotify)
|
|||
}
|
||||
}
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsGenericHTMLContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
||||
{
|
||||
nsIDocument* doc = mDocument;
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->BeginUpdate();
|
||||
}
|
||||
nsIContent* oldKid = (nsIContent *)mChildren.ElementAt(aIndex);
|
||||
if (nsnull != oldKid ) {
|
||||
nsIDocument* doc = mDocument;
|
||||
nsRange::OwnerChildRemoved(mContent, aIndex, oldKid);
|
||||
mChildren.RemoveElementAt(aIndex);
|
||||
if (aNotify) {
|
||||
|
@ -3020,6 +3069,9 @@ nsGenericHTMLContainerElement::RemoveChildAt(PRInt32 aIndex, PRBool aNotify)
|
|||
oldKid->SetParent(nsnull);
|
||||
NS_RELEASE(oldKid);
|
||||
}
|
||||
if (aNotify && (nsnull != doc)) {
|
||||
doc->EndUpdate();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -286,7 +286,8 @@ public:
|
|||
|
||||
//XXX These three create a dependency between content and frames
|
||||
static nsresult GetPrimaryFrame(nsIHTMLContent* aContent,
|
||||
nsIFormControlFrame *&aFormControlFrame);
|
||||
nsIFormControlFrame *&aFormControlFrame,
|
||||
PRBool aFlushNotifications=PR_TRUE);
|
||||
static nsresult GetPrimaryPresState(nsIHTMLContent* aContent,
|
||||
nsIStatefulFrame::StateType aStateType,
|
||||
nsIPresState** aPresState);
|
||||
|
|
|
@ -720,7 +720,7 @@ nsHTMLSelectElement::DoneAddingContent(PRBool aIsDone)
|
|||
{
|
||||
mIsDoneAddingContent = aIsDone;
|
||||
nsIFormControlFrame* fcFrame = nsnull;
|
||||
nsresult result = nsGenericHTMLElement::GetPrimaryFrame(this, fcFrame);
|
||||
nsresult result = nsGenericHTMLElement::GetPrimaryFrame(this, fcFrame,PR_FALSE);
|
||||
if (NS_SUCCEEDED(result) && (nsnull != fcFrame)) {
|
||||
nsISelectControlFrame* selectFrame = nsnull;
|
||||
result = fcFrame->QueryInterface(nsISelectControlFrame::GetIID(),(void **) &selectFrame);
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
|
||||
#include "nsIWebShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDocumentObserver.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
|
@ -144,7 +145,8 @@ class SinkContext;
|
|||
class HTMLContentSink : public nsIHTMLContentSink,
|
||||
public nsIUnicharStreamLoaderObserver,
|
||||
public nsITimerCallback,
|
||||
public nsICSSLoaderObserver
|
||||
public nsICSSLoaderObserver,
|
||||
public nsIDocumentObserver
|
||||
{
|
||||
public:
|
||||
HTMLContentSink();
|
||||
|
@ -200,6 +202,62 @@ public:
|
|||
// nsICSSLoaderObserver
|
||||
NS_IMETHOD StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify);
|
||||
|
||||
// nsIDocumentObserver
|
||||
NS_IMETHOD BeginUpdate(nsIDocument *aDocument);
|
||||
NS_IMETHOD EndUpdate(nsIDocument *aDocument);
|
||||
NS_IMETHOD BeginLoad(nsIDocument *aDocument) { return NS_OK; }
|
||||
NS_IMETHOD EndLoad(nsIDocument *aDocument) { return NS_OK; }
|
||||
NS_IMETHOD BeginReflow(nsIDocument *aDocument,
|
||||
nsIPresShell* aShell) { return NS_OK; }
|
||||
NS_IMETHOD EndReflow(nsIDocument *aDocument,
|
||||
nsIPresShell* aShell) { return NS_OK; }
|
||||
NS_IMETHOD ContentChanged(nsIDocument *aDocument,
|
||||
nsIContent* aContent,
|
||||
nsISupports* aSubContent) { return NS_OK; }
|
||||
NS_IMETHOD ContentStatesChanged(nsIDocument* aDocument,
|
||||
nsIContent* aContent1,
|
||||
nsIContent* aContent2) { return NS_OK; }
|
||||
NS_IMETHOD AttributeChanged(nsIDocument *aDocument,
|
||||
nsIContent* aContent,
|
||||
PRInt32 aNameSpaceID,
|
||||
nsIAtom* aAttribute,
|
||||
PRInt32 aHint) { return NS_OK; }
|
||||
NS_IMETHOD ContentAppended(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
PRInt32 aNewIndexInContainer)
|
||||
{ return NS_OK; }
|
||||
NS_IMETHOD ContentInserted(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer) { return NS_OK; }
|
||||
NS_IMETHOD ContentReplaced(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aOldChild,
|
||||
nsIContent* aNewChild,
|
||||
PRInt32 aIndexInContainer) { return NS_OK; }
|
||||
NS_IMETHOD ContentRemoved(nsIDocument *aDocument,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aChild,
|
||||
PRInt32 aIndexInContainer) { return NS_OK; }
|
||||
NS_IMETHOD StyleSheetAdded(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet) { return NS_OK; }
|
||||
NS_IMETHOD StyleSheetRemoved(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet) { return NS_OK; }
|
||||
NS_IMETHOD StyleSheetDisabledStateChanged(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
PRBool aDisabled) { return NS_OK; }
|
||||
NS_IMETHOD StyleRuleChanged(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule,
|
||||
PRInt32 aHint) { return NS_OK; }
|
||||
NS_IMETHOD StyleRuleAdded(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule) { return NS_OK; }
|
||||
NS_IMETHOD StyleRuleRemoved(nsIDocument *aDocument,
|
||||
nsIStyleSheet* aStyleSheet,
|
||||
nsIStyleRule* aStyleRule) { return NS_OK; }
|
||||
NS_IMETHOD DocumentWillBeDestroyed(nsIDocument *aDocument) { return NS_OK; }
|
||||
|
||||
PRBool IsTimeToNotify();
|
||||
PRBool IsInScript();
|
||||
void ReduceEntities(nsString& aString);
|
||||
|
@ -243,6 +301,7 @@ public:
|
|||
|
||||
PRBool mLayoutStarted;
|
||||
PRInt32 mInScript;
|
||||
PRInt32 mInNotification;
|
||||
nsIDOMHTMLFormElement* mCurrentForm;
|
||||
nsIHTMLContent* mCurrentMap;
|
||||
|
||||
|
@ -344,7 +403,7 @@ public:
|
|||
{
|
||||
return FlushText(aDidFlush, PR_TRUE);
|
||||
}
|
||||
nsresult FlushTags();
|
||||
nsresult FlushTags(PRBool aNotify = PR_TRUE);
|
||||
|
||||
PRBool IsCurrentContainer(nsHTMLTag mType);
|
||||
PRBool IsAncestorContainer(nsHTMLTag mType);
|
||||
|
@ -1152,7 +1211,7 @@ SinkContext::DidAddContent(nsIContent* aContent, PRBool aDidNotify)
|
|||
else if (!aDidNotify && mSink->IsTimeToNotify()) {
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("SinkContext::DidAddContent: Notification as a result of the interval expiring; backoff count: %d", mSink->mBackoffCount));
|
||||
FlushTags();
|
||||
FlushTags(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1210,10 +1269,10 @@ SinkContext::OpenContainer(const nsIParserNode& aNode)
|
|||
if (mStack[mStackPos-1].mInsertionPoint != -1) {
|
||||
parent->InsertChildAt(content,
|
||||
mStack[mStackPos-1].mInsertionPoint++,
|
||||
mSink->IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
parent->AppendChildTo(content, mSink->IsInScript());
|
||||
parent->AppendChildTo(content, PR_FALSE);
|
||||
}
|
||||
mStack[mStackPos].mFlags |= APPENDED;
|
||||
}
|
||||
|
@ -1287,10 +1346,10 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
if (mStack[mStackPos-1].mInsertionPoint != -1) {
|
||||
result = parent->InsertChildAt(content,
|
||||
mStack[mStackPos-1].mInsertionPoint++,
|
||||
mSink->IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
result = parent->AppendChildTo(content, mSink->IsInScript());
|
||||
result = parent->AppendChildTo(content, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1324,7 +1383,7 @@ SinkContext::CloseContainer(const nsIParserNode& aNode)
|
|||
mNotifyLevel = mStackPos-1;
|
||||
}
|
||||
|
||||
DidAddContent(content, mSink->IsInScript());
|
||||
DidAddContent(content, PR_FALSE);
|
||||
|
||||
|
||||
// Special handling for certain tags
|
||||
|
@ -1434,7 +1493,7 @@ SinkContext::DemoteContainer(const nsIParserNode& aNode)
|
|||
// with later.
|
||||
parent->ChildCount(parentCount);
|
||||
if (mStack[stackPos-1].mNumFlushed == parentCount) {
|
||||
FlushTags();
|
||||
FlushTags(PR_TRUE);
|
||||
sync = PR_TRUE;
|
||||
}
|
||||
// Otherwise just append the container to the parent without
|
||||
|
@ -1601,13 +1660,13 @@ SinkContext::AddLeaf(nsIHTMLContent* aContent)
|
|||
if (mStack[mStackPos-1].mInsertionPoint != -1) {
|
||||
parent->InsertChildAt(aContent,
|
||||
mStack[mStackPos-1].mInsertionPoint++,
|
||||
mSink->IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
parent->AppendChildTo(aContent, mSink->IsInScript());
|
||||
parent->AppendChildTo(aContent, PR_FALSE);
|
||||
}
|
||||
|
||||
DidAddContent(aContent, mSink->IsInScript());
|
||||
DidAddContent(aContent, PR_FALSE);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mPreAppend &&
|
||||
|
@ -1653,13 +1712,13 @@ SinkContext::AddComment(const nsIParserNode& aNode)
|
|||
if (mStack[mStackPos-1].mInsertionPoint != -1) {
|
||||
parent->InsertChildAt(comment,
|
||||
mStack[mStackPos-1].mInsertionPoint++,
|
||||
mSink->IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
parent->AppendChildTo(comment, mSink->IsInScript());
|
||||
parent->AppendChildTo(comment, PR_FALSE);
|
||||
}
|
||||
|
||||
DidAddContent(comment, mSink->IsInScript());
|
||||
DidAddContent(comment, PR_FALSE);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (mPreAppend &&
|
||||
|
@ -1764,7 +1823,7 @@ SinkContext::AddText(const nsString& aText)
|
|||
* has been newly added so that the frame tree is complete.
|
||||
*/
|
||||
nsresult
|
||||
SinkContext::FlushTags()
|
||||
SinkContext::FlushTags(PRBool aNotify)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
|
||||
|
@ -1796,47 +1855,49 @@ SinkContext::FlushTags()
|
|||
stackPos--;
|
||||
}
|
||||
|
||||
// Start from the base of the stack (growing upward) and do
|
||||
// a notification from the node that is closest to the root of
|
||||
// tree for any content that has been added.
|
||||
stackPos = 1;
|
||||
PRBool flushed = PR_FALSE;
|
||||
while (stackPos < mStackPos) {
|
||||
content = mStack[stackPos].mContent;
|
||||
content->ChildCount(childCount);
|
||||
if (aNotify) {
|
||||
// Start from the base of the stack (growing upward) and do
|
||||
// a notification from the node that is closest to the root of
|
||||
// tree for any content that has been added.
|
||||
stackPos = 1;
|
||||
PRBool flushed = PR_FALSE;
|
||||
while (stackPos < mStackPos) {
|
||||
content = mStack[stackPos].mContent;
|
||||
content->ChildCount(childCount);
|
||||
|
||||
if (!flushed && (mStack[stackPos].mNumFlushed < childCount)) {
|
||||
if (!flushed && (mStack[stackPos].mNumFlushed < childCount)) {
|
||||
#ifdef NS_DEBUG
|
||||
// Tracing code
|
||||
char cbuf[40];
|
||||
const char* cp;
|
||||
nsAutoString str;
|
||||
nsCOMPtr<nsIDTD> dtd;
|
||||
mSink->mParser->GetDTD(getter_AddRefs(dtd));
|
||||
dtd->IntTagToStringTag(nsHTMLTag(mStack[stackPos].mType), str);
|
||||
cp = str.ToCString(cbuf, sizeof(cbuf));
|
||||
// Tracing code
|
||||
char cbuf[40];
|
||||
const char* cp;
|
||||
nsAutoString str;
|
||||
nsCOMPtr<nsIDTD> dtd;
|
||||
mSink->mParser->GetDTD(getter_AddRefs(dtd));
|
||||
dtd->IntTagToStringTag(nsHTMLTag(mStack[stackPos].mType), str);
|
||||
cp = str.ToCString(cbuf, sizeof(cbuf));
|
||||
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("SinkContext::FlushTags: tag=%s from newindex=%d at stackPos=%d",
|
||||
cp, mStack[stackPos].mNumFlushed, stackPos));
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("SinkContext::FlushTags: tag=%s from newindex=%d at stackPos=%d",
|
||||
cp, mStack[stackPos].mNumFlushed, stackPos));
|
||||
#endif
|
||||
if ((mStack[stackPos].mInsertionPoint != -1) &&
|
||||
(mStackPos > (stackPos+1))) {
|
||||
nsIContent* child = mStack[stackPos+1].mContent;
|
||||
mSink->NotifyInsert(content,
|
||||
child,
|
||||
mStack[stackPos].mInsertionPoint);
|
||||
if ((mStack[stackPos].mInsertionPoint != -1) &&
|
||||
(mStackPos > (stackPos+1))) {
|
||||
nsIContent* child = mStack[stackPos+1].mContent;
|
||||
mSink->NotifyInsert(content,
|
||||
child,
|
||||
mStack[stackPos].mInsertionPoint);
|
||||
}
|
||||
else {
|
||||
mSink->NotifyAppend(content, mStack[stackPos].mNumFlushed);
|
||||
}
|
||||
flushed = PR_TRUE;
|
||||
}
|
||||
else {
|
||||
mSink->NotifyAppend(content, mStack[stackPos].mNumFlushed);
|
||||
}
|
||||
flushed = PR_TRUE;
|
||||
}
|
||||
|
||||
mStack[stackPos].mNumFlushed = childCount;
|
||||
stackPos++;
|
||||
mStack[stackPos].mNumFlushed = childCount;
|
||||
stackPos++;
|
||||
}
|
||||
mNotifyLevel = mStackPos-1;
|
||||
}
|
||||
mNotifyLevel = mStackPos-1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1907,10 +1968,10 @@ SinkContext::FlushText(PRBool* aDidFlush, PRBool aReleaseLast)
|
|||
if (mStack[mStackPos-1].mInsertionPoint != -1) {
|
||||
parent->InsertChildAt(content,
|
||||
mStack[mStackPos-1].mInsertionPoint++,
|
||||
mSink->IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
parent->AppendChildTo(content, mSink->IsInScript());
|
||||
parent->AppendChildTo(content, PR_FALSE);
|
||||
}
|
||||
|
||||
mLastTextNode = content;
|
||||
|
@ -1918,7 +1979,7 @@ SinkContext::FlushText(PRBool* aDidFlush, PRBool aReleaseLast)
|
|||
mTextLength = 0;
|
||||
didFlush = PR_TRUE;
|
||||
|
||||
DidAddContent(content, mSink->IsInScript());
|
||||
DidAddContent(content, PR_FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1972,6 +2033,7 @@ HTMLContentSink::HTMLContentSink() {
|
|||
mNotAtRef = PR_TRUE;
|
||||
mContentIDCounter = NS_CONTENT_ID_COUNTER_BASE;
|
||||
mInScript = 0;
|
||||
mInNotification = 0;
|
||||
mInsideNoXXXTag = 0;
|
||||
}
|
||||
|
||||
|
@ -1982,7 +2044,10 @@ HTMLContentSink::~HTMLContentSink()
|
|||
NS_IF_RELEASE(mFrameset);
|
||||
NS_IF_RELEASE(mRoot);
|
||||
|
||||
NS_IF_RELEASE(mDocument);
|
||||
if (mDocument) {
|
||||
mDocument->RemoveObserver(this);
|
||||
NS_RELEASE(mDocument);
|
||||
}
|
||||
NS_IF_RELEASE(mHTMLDocument);
|
||||
NS_IF_RELEASE(mDocumentURI);
|
||||
NS_IF_RELEASE(mDocumentBaseURL);
|
||||
|
@ -2033,12 +2098,13 @@ HTMLContentSink::~HTMLContentSink()
|
|||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS5(HTMLContentSink,
|
||||
NS_IMPL_ISUPPORTS6(HTMLContentSink,
|
||||
nsIHTMLContentSink,
|
||||
nsIContentSink,
|
||||
nsIUnicharStreamLoaderObserver,
|
||||
nsITimerCallback,
|
||||
nsICSSLoaderObserver)
|
||||
nsICSSLoaderObserver,
|
||||
nsIDocumentObserver)
|
||||
|
||||
nsresult
|
||||
HTMLContentSink::Init(nsIDocument* aDoc,
|
||||
|
@ -2060,6 +2126,7 @@ HTMLContentSink::Init(nsIDocument* aDoc,
|
|||
|
||||
mDocument = aDoc;
|
||||
NS_ADDREF(aDoc);
|
||||
aDoc->AddObserver(this);
|
||||
aDoc->QueryInterface(kIHTMLDocumentIID, (void**)&mHTMLDocument);
|
||||
mDocumentURI = aURL;
|
||||
NS_ADDREF(aURL);
|
||||
|
@ -2187,7 +2254,7 @@ HTMLContentSink::DidBuildModel(PRInt32 aQualityLevel)
|
|||
if (nsnull != mBody) {
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("HTMLContentSink::DidBuildModel: layout final content"));
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
ScrollToRef();
|
||||
|
||||
|
@ -2220,7 +2287,7 @@ HTMLContentSink::Notify(nsITimer *timer)
|
|||
("HTMLContentSink::Notify: reflow on a timer: %d milliseconds late, backoff count: %d", delay, mBackoffCount));
|
||||
#endif
|
||||
if (mCurrentContext) {
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
mNotificationTimer = 0;
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::Notify()\n"));
|
||||
|
@ -2251,7 +2318,7 @@ HTMLContentSink::WillInterrupt()
|
|||
mBackoffCount--;
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("HTMLContentSink::WillInterrupt: flushing tags since we've run out time; backoff count: %d", mBackoffCount));
|
||||
result = mCurrentContext->FlushTags();
|
||||
result = mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
else {
|
||||
// If the time since the last notification is less than
|
||||
|
@ -2289,7 +2356,7 @@ HTMLContentSink::WillInterrupt()
|
|||
else {
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("HTMLContentSink::WillInterrupt: flushing tags unconditionally"));
|
||||
result = mCurrentContext->FlushTags();
|
||||
result = mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -2343,7 +2410,7 @@ HTMLContentSink::BeginContext(PRInt32 aPosition)
|
|||
}
|
||||
// Flush everything in the current context so that we don't have
|
||||
// to worry about insertions resulting in inconsistent frame creation.
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_TRUE);
|
||||
|
||||
PRInt32 insertionPoint = -1;
|
||||
nsHTMLTag nodeType = mCurrentContext->mStack[aPosition].mType;
|
||||
|
@ -2477,8 +2544,8 @@ HTMLContentSink::CloseHTML(const nsIParserNode& aNode)
|
|||
if(mCurrentContext==mHeadContext) {
|
||||
PRInt32 numContexts = mContextStack.Count();
|
||||
// Pop off the second html context if it's not done earlier
|
||||
mContextStack.RemoveElementAt(--numContexts);
|
||||
mCurrentContext = nsnull;
|
||||
mCurrentContext = (SinkContext*)mContextStack.ElementAt(--numContexts);
|
||||
mContextStack.RemoveElementAt(numContexts);
|
||||
}
|
||||
mHeadContext->End();
|
||||
delete mHeadContext;
|
||||
|
@ -2596,7 +2663,7 @@ HTMLContentSink::CloseBody(const nsIParserNode& aNode)
|
|||
// Flush out anything that's left
|
||||
SINK_TRACE(SINK_TRACE_REFLOW,
|
||||
("HTMLContentSink::CloseBody: layout final body content"));
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_TRUE);
|
||||
mCurrentContext->CloseContainer(aNode);
|
||||
|
||||
MOZ_TIMER_DEBUGLOG(("Stop: nsHTMLContentSink::CloseBody()\n"));
|
||||
|
@ -3770,7 +3837,7 @@ IsJavaScriptLanguage(const nsString& aName, const char* *aVersion)
|
|||
void
|
||||
HTMLContentSink::ForceReflow()
|
||||
{
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3778,6 +3845,7 @@ HTMLContentSink::ForceReflow()
|
|||
void
|
||||
HTMLContentSink::NotifyAppend(nsIContent* aContainer, PRInt32 aStartIndex)
|
||||
{
|
||||
mInNotification++;
|
||||
MOZ_TIMER_DEBUGLOG(("Save and stop: nsHTMLContentSink::NotifyAppend()\n"));
|
||||
MOZ_TIMER_SAVE(mWatch)
|
||||
MOZ_TIMER_STOP(mWatch);
|
||||
|
@ -3785,6 +3853,7 @@ HTMLContentSink::NotifyAppend(nsIContent* aContainer, PRInt32 aStartIndex)
|
|||
mLastNotificationTime = PR_Now();
|
||||
MOZ_TIMER_DEBUGLOG(("Restore: nsHTMLContentSink::NotifyAppend()\n"));
|
||||
MOZ_TIMER_RESTORE(mWatch);
|
||||
mInNotification--;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3792,6 +3861,7 @@ HTMLContentSink::NotifyInsert(nsIContent* aContent,
|
|||
nsIContent* aChildContent,
|
||||
PRInt32 aIndexInContainer)
|
||||
{
|
||||
mInNotification++;
|
||||
MOZ_TIMER_DEBUGLOG(("Save and stop: nsHTMLContentSink::NotifyInsert()\n"));
|
||||
MOZ_TIMER_SAVE(mWatch)
|
||||
MOZ_TIMER_STOP(mWatch);
|
||||
|
@ -3799,6 +3869,7 @@ HTMLContentSink::NotifyInsert(nsIContent* aContent,
|
|||
mLastNotificationTime = PR_Now();
|
||||
MOZ_TIMER_DEBUGLOG(("Restore: nsHTMLContentSink::NotifyInsert()\n"));
|
||||
MOZ_TIMER_RESTORE(mWatch);
|
||||
mInNotification--;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -3835,6 +3906,37 @@ HTMLContentSink::UpdateAllContexts()
|
|||
mCurrentContext->UpdateChildCounts();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLContentSink::BeginUpdate(nsIDocument *aDocument)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
// If we're in a script and we didn't do the notification,
|
||||
// something else in the script processing caused the
|
||||
// notification to occur. Since this could result in frame
|
||||
// creation, make sure we've flushed everything before we
|
||||
// continue
|
||||
if (mInScript && !mInNotification && mCurrentContext) {
|
||||
result = mCurrentContext->FlushTags(PR_TRUE);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HTMLContentSink::EndUpdate(nsIDocument *aDocument)
|
||||
{
|
||||
|
||||
// If we're in a script and we didn't do the notification,
|
||||
// something else in the script processing caused the
|
||||
// notification to occur. Update our notion of how much
|
||||
// has been flushed to include any new content.
|
||||
if (mInScript && !mInNotification) {
|
||||
UpdateAllContexts();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLContentSink::ResumeParsing()
|
||||
{
|
||||
|
@ -3853,10 +3955,12 @@ HTMLContentSink::PreEvaluateScript()
|
|||
// to the body (so that they can be seen by scripts) and force reflow.
|
||||
SINK_TRACE(SINK_TRACE_CALLS,
|
||||
("HTMLContentSink::PreEvaluateScript: flushing tags before evaluating script"));
|
||||
mCurrentContext->FlushTags();
|
||||
mCurrentContext->FlushTags(PR_FALSE);
|
||||
mCurrentContext->SetPreAppend(PR_TRUE);
|
||||
|
||||
mInScript++;
|
||||
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -3864,8 +3968,7 @@ void
|
|||
HTMLContentSink::PostEvaluateScript(PRBool aBodyPresent)
|
||||
{
|
||||
mInScript--;
|
||||
|
||||
mCurrentContext->UpdateChildCounts();
|
||||
mCurrentContext->SetPreAppend(PR_FALSE);
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -4019,10 +4122,10 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
|
|||
if (mCurrentContext->mStack[mCurrentContext->mStackPos-1].mInsertionPoint != -1) {
|
||||
parent->InsertChildAt(element,
|
||||
mCurrentContext->mStack[mCurrentContext->mStackPos-1].mInsertionPoint++,
|
||||
IsInScript());
|
||||
PR_FALSE);
|
||||
}
|
||||
else {
|
||||
parent->AppendChildTo(element, IsInScript());
|
||||
parent->AppendChildTo(element, PR_FALSE);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -4044,7 +4147,7 @@ HTMLContentSink::ProcessSCRIPTTag(const nsIParserNode& aNode)
|
|||
tc->SetData(script);
|
||||
NS_RELEASE(tc);
|
||||
}
|
||||
element->AppendChildTo(text, IsInScript());
|
||||
element->AppendChildTo(text, PR_FALSE);
|
||||
text->SetDocument(mDocument, PR_FALSE);
|
||||
NS_RELEASE(text);
|
||||
}
|
||||
|
@ -4201,7 +4304,7 @@ HTMLContentSink::ProcessSTYLETag(const nsIParserNode& aNode)
|
|||
tc->SetData(content);
|
||||
NS_RELEASE(tc);
|
||||
}
|
||||
element->AppendChildTo(text, IsInScript());
|
||||
element->AppendChildTo(text, PR_FALSE);
|
||||
text->SetDocument(mDocument, PR_FALSE);
|
||||
NS_RELEASE(text);
|
||||
}
|
||||
|
@ -4262,13 +4365,15 @@ HTMLContentSink::NotifyError(const nsParserError* aError)
|
|||
NS_IMETHODIMP
|
||||
HTMLContentSink::FlushPendingNotifications()
|
||||
{
|
||||
/* XXX This is temporarily commented out so that this change can be tested locally.
|
||||
nsresult result = NS_OK;
|
||||
if (mCurrentContext) {
|
||||
// Only flush tags if we're not doing the notification ourselves
|
||||
// (since we aren't reentrant) and if we're in a script (since
|
||||
// we only care to flush if this is done via script).
|
||||
if (mCurrentContext && !mInNotification && mInScript) {
|
||||
result = mCurrentContext->FlushTags();
|
||||
}
|
||||
*/
|
||||
return NS_OK;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -1294,6 +1294,34 @@ nsXULDocument::RemoveObserver(nsIDocumentObserver* aObserver)
|
|||
return mObservers.RemoveElement(aObserver);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::BeginUpdate()
|
||||
{
|
||||
// XXX Never called. Does this matter?
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->BeginUpdate(this);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::EndUpdate()
|
||||
{
|
||||
// XXX Never called. Does this matter?
|
||||
for (PRInt32 i = 0; i < mObservers.Count(); i++) {
|
||||
nsIDocumentObserver* observer = (nsIDocumentObserver*) mObservers[i];
|
||||
observer->EndUpdate(this);
|
||||
if (observer != (nsIDocumentObserver*)mObservers.ElementAt(i)) {
|
||||
i--;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULDocument::BeginLoad()
|
||||
{
|
||||
|
|
|
@ -191,6 +191,10 @@ public:
|
|||
|
||||
virtual PRBool RemoveObserver(nsIDocumentObserver* aObserver);
|
||||
|
||||
NS_IMETHOD BeginUpdate();
|
||||
|
||||
NS_IMETHOD EndUpdate();
|
||||
|
||||
NS_IMETHOD BeginLoad();
|
||||
|
||||
NS_IMETHOD EndLoad();
|
||||
|
|
Загрузка…
Ссылка в новой задаче