Closed Bug 338679 Opened 19 years ago Closed 14 years ago

DOMAttrModified event reports new value as prevValue for style changes

Categories

(Core :: DOM: Events, defect)

x86
Windows Server 2003
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: Seno.Aiko, Assigned: zwol)

References

(Blocks 1 open bug)

Details

Attachments

(1 file, 4 obsolete files)

User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9a1) Gecko/20060517 Minefield/3.0a1 Build Identifier: Mozilla/5.0 (Windows; U; Windows NT 5.2; en-US; rv:1.9a1) Gecko/20060517 Minefield/3.0a1 If the DOMAttrModified event is fired because of a change to its style object, event.prevValue isn't the old style value but the same as event.newValue. The attached testcase only tests "width" but as far as I can tell all style properties are affected. If the style is modified via setAttribute("style", newValue) instead then prevValue is reported correctly. Reproducible: Always
Attached file testcase (obsolete) (deleted) —
This particular test case seems to be a known issue, at least in the source code. The last place we have access to the old value is nsDOMCSSDeclaration.cpp#244, which then calls the subclass' implementation of DeclarationChanged(). I'm not sure we can fix this without changing the signature of nsGenericHTMLElement::SetInlineStyleRule. 80 nsDOMCSSAttributeDeclaration::DeclarationChanged() 81 { 82 NS_ASSERTION(mContent, "Must have content node to set the decl!"); 83 nsICSSStyleRule* oldRule = mContent->GetInlineStyleRule(); 84 NS_ASSERTION(oldRule, "content must have rule"); 85 86 nsCOMPtr<nsICSSStyleRule> newRule = oldRule->DeclarationChanged(PR_FALSE); ... 90 91 return mContent->SetInlineStyleRule(newRule, PR_TRUE); 92 } ------------------------------ 1755 nsGenericHTMLElement::SetInlineStyleRule(nsICSSStyleRule* aStyleRule, 1756 PRBool aNotify) 1757 { ... 1767 // There's no point in comparing the stylerule pointers since we're always 1768 // getting a new stylerule here. And we can't compare the stringvalues of 1769 // the old and the new rules since both will point to the same declaration 1770 // and thus will be the same. 1771 if (hasListeners) { 1772 // save the old attribute so we can set up the mutation event properly 1773 // XXXbz if the old rule points to the same declaration as the new one, 1774 // this is getting the new attr value, not the old one.... 1775 modification = GetAttr(kNameSpaceID_None, nsHTMLAtoms::style, 1776 oldValueStr); 1777 } 1778 else if (aNotify) { 1779 modification = !!mAttrsAndChildren.GetAttr(nsHTMLAtoms::style); 1780 } ... 1786 }
Yeah, you'd want to change the signature of SetInlineStyleRule to take the old value, and change various other stuff to propagate the old value through the system as needed. Or some other similar refactoring. This is about as low-priority as things get for me, frankly, but I'd be willing to review a patch that doesn't regress perf in the usual (no mutation listeners) case if someone writes one.
Keywords: helpwanted
(In reply to comment #3) > > This is about as low-priority as things get for me, frankly, but I'd be willing > to review a patch... OK, I'll take it. I have my head in the code already. Is it ok to pass the old value as a string?
Status: NEW → ASSIGNED
Assignee: events → sayrer
Status: ASSIGNED → NEW
You'd have to; there's not much else you can pass it as (short of an atom).
Attached patch add argument to SetInlineStyle (obsolete) (deleted) — Splinter Review
Attachment #223659 - Flags: review?(bzbarsky)
Comment on attachment 223659 [details] [diff] [review] add argument to SetInlineStyle I'd need to see numbers to convince me that this doesn't regress perf... Based on everything I know about this code, this would slow down setting inline style a good bit.
Attachment #223659 - Flags: review?(bzbarsky) → review-
(In reply to comment #7) > (From update of attachment 223659 [details] [diff] [review] [edit]) > I'd need to see numbers to convince me that this doesn't regress perf... Based > on everything I know about this code, this would slow down setting inline style > a good bit. > Hmm, tdhtml seems down in the noise (see below). what's a better test? without patch: Test Median Average Data ============================================================ colorfade: 1513 1516 1566,1481,1513,1475,1544 diagball: 1810 1823 1864,1765,1897,1810,1780 fadespacing: 2632 2651 2816,2568,2555,2632,2685 imageslide: 426 414 363,429,426,424,426 layers1: 4288 4486 5547,4288,4141,4319,4136 layers2: 108 109 108,114,108,108,108 layers4: 108 108 108,109,107,108,107 layers5: 2878 2868 2813,2879,2878,2875,2895 layers6: 254 254 256,254,253,252,256 meter: 1320 1324 1378,1284,1320,1321,1319 movingtext: 1164 1162 1154,1165,1164,1164,1165 mozilla: 2957 2959 2988,2957,2999,2944,2907 replaceimages: 3083 3183 3585,3076,3083,3075,3098 scrolling: 31581 31564 31490,31548,31581,31619,31582 slidein: 2692 2731 2898,2696,2692,2686,2682 slidingballs: 1718 1707 1763,1665,1722,1718,1669 zoom: 587 591 490,706,623,587,550 _x_x_mozilla_dhtml,1334 with patch: Test Median Average Data ============================================================ colorfade: 1516 1498 1480,1407,1551,1536,1516 diagball: 1878 1850 1738,1849,1890,1878,1893 fadespacing: 2575 2568 2575,2540,2575,2562,2587 imageslide: 423 419 391,435,422,423,426 layers1: 4563 4674 4884,4562,4563,4800,4563 layers2: 125 125 125,124,125,126,124 layers4: 124 125 127,124,124,124,124 layers5: 3339 3339 3292,3374,3339,3352,3337 layers6: 310 310 312,310,310,307,310 meter: 1272 1293 1393,1265,1275,1261,1272 movingtext: 1181 1184 1195,1181,1204,1178,1163 mozilla: 3022 3002 2920,3022,3010,3025,3034 replaceimages: 3076 3076 3076,3076,3086,3045,3097 scrolling: 31701 31684 31559,31672,31701,31753,31736 slidein: 2682 2740 2990,2670,2682,2672,2686 slidingballs: 1892 1904 1904,1855,2016,1892,1852 zoom: 576 638 893,604,553,563,576 _x_x_mozilla_dhtml,1397
That's not down in the noise; that's a 5% regression.
(In reply to comment #9) > That's not down in the noise; that's a 5% regression. Ok, I was looking at argo-vm.mozilla.org and saw the tests fluctuating in a 20% range. Other machines look more stable, though. I changed the switch in SetInlineStyle back to the old way, and that seemed to slow things down. Throw me a bone... what made you think this would be a regression?
> what made you think this would be a regression? With this change, on every single inline style set we serialize the current inline style to a string first. This doubles the amount of time we spend compressing and decompressing the css data blocks (which is a noticeable part of the total time in profiles of pages like the one in bug 229391), adds the time to actually perform the serialization, etc. As in, we do more work, by a good amount. So I would expect us to get slower. How much slower is an interesting question; at the very least it depends on the exact styles used (the more properties set in the inline style, the bigger the slowdown). In all cases, I'd need to see data indicating that the slowdown is negligible before we make this change. The other option, of course, is to only serialize when we really need to -- when we know we're going to fire the mutation event. I'd really prefer that, if possible.
It is impossible to compare prevValue and newValue. https://bugzilla.mozilla.org/attachment.cgi?id=222747 Why is this still not fixed and since 2 months still "new"?
> Why is this still not fixed Because there are finite resources and other bugs seem to be higher priority. The best way to get it fixed is to pay someone to fix it, if you can find someone with the time to do so... > and since 2 months still "new"? That's its status. It's a bug, it's not assigned to anyone. Note that it's not like you can depend on either newValue or prevValue reflecting anything sane about the state of the node at any point in time, since DOM events can be received in the opposite order from the changes actually occurring...
>Because there are finite resources and other bugs seem to be higher priority. It´s not that a feature is not working properly, an implemented feature is not working completely. IMHO only a crash can be more important than an old DOM 2 property that is not supported and should be as specs. >since DOM events can be received in the opposite order from the changes actually occurring... I don´t know why the ability of an event to bubble or not should be of any interest here. In Opera the event process is impremented this way: 1. the browser gets the command to change the attribut of a div 2. the browser saves the state of the div 3. the div gets altered 4. the new state of the div is saved 5. DOMAttrModified gets fired 6. the event bubbles or is captured by target´s childs the whole process is not cancelable and it´s unimportant if the bubbles at point 6. I don´t think that there´s another sequence possible. BTW: I´m surely not going to pay anyone, because I primary use Opera. However which source code/form is affected?
> IMHO only a crash can be more important than an old DOM 2 property I don't think others agree on this with you, especially for something like mutation events (which are of limited usefulness anyway, since they can be reentered, as I said). Frankly, if people suddenly decide it's important to have a 100% correct implementation of mutation events, my vote would be for removing support for them altogether. > I don´t know why the ability of an event to bubble or not Bubbling has nothing to do with this. Capturing has a lot more to do with it. Consider a capturing DOMAttrModified listener that changes the same attribute and think about what an at-target or bubbling listener sees. > In Opera the event process is impremented this way: I'm aware of how one would implement this in general, yes. ;) > 2. the browser saves the state of the div The point is that for the style attribute this is actually pretty expensive. Doing it unconditionally (i.e. when there are no mutation listeners) would be a pretty major performance penalty in many cases. So a correct solution would only do this if needed. > However which source code/form is affected? See attachment 223659 [details] [diff] [review]. That touches all the relevant code, I think.
i'd vote for removing mutation event support entirely :) of course, it's in my interests for browsers to be smaller and the web less pathological.
@Boris >Doing it unconditionally (i.e. when there are no mutation listeners) would be a pretty major performance penalty in many cases. I´m pretty sure that Opera always fires a mutation event. I made a few tests in the past and my mutation event script was only ~1% slower at 10000 runs (even with a RegExp) than normal rendering. Because Opera is written in C++/Qt there should be no performance issues in FF, too. >I'm aware of how one would implement this in general, yes. ;) The main point is that the whole thing is senseless when there are performance issues. It should be no problem to check the string of an attribute. If a div is changed by setAttribute, setAttributeNode, replaceData... only the string "style=''" is checked. If a script access the div via div.style.example the attribute string gets modified, or "style='example'" is add. String is saved as prevValue, changes are made and the new string is saved as newValue. Event is fired. There should be no performance loss. However I´m a little bit disappointed, Mozilla is a big company with potent sponsors and should have the ressources to implement standards. Instead of implementing new Core level 3 dom functions level 2 should be supported. >See attachment 223659 [details] [diff] [review] [edit]. Thanks.
> there should be no performance issues in FF If you can produce profiling data backing this up, great. See comment 7. > String is saved as prevValue The data is not stored as a string in this case. Getting it into string form is slow. > Mozilla is a big company Actually, it's a pretty small company. For example, as of end of 2005, Opera Software had 254 employees (see http://www.opera.com/company/investors/finance/2005/ann_rep_numbers.pdf). The Mozilla corporation has around 60 employees. Even the number of regular code contributors to the Mozilla code (many of whom are doing it very much in their spare time) is smaller than the number of Opera employees. Just figured I'd set the record straight here and all. > and should have the ressources to implement standards If all wishes came true... ;) > Instead of implementing new Core level 3 dom functions level 2 should be > supported. Parts of DOM 3 that are very useful tend to have priority over less-useful corner cases of DOM 2 in people's minds, for better or for worse.
Assignee: sayrer → events
Over two years later: >The other option, of course, is to only serialize when we really need to -- >when we know we're going to fire the mutation event. It's a pity that Mozilla took option 3: Ignoring everything and hoping that no one recognizes it. What a fortune that Acid3 just tests mutation events in general and does not compare prevValue and newValue. And yes I totally agree, supporting standards that nobody uses is totally useless. Let's just do it like MS with IE and totally ignore all SVG, events, formats and everything else that is not used very often. This would speed up FF quite some more. Perhaps implementing some CSS3 functions (while CSS2 could be dropped generously, IE works this way, too) and completing the Acid3 will do for marketing and satisfaction of everyone, or not?
Depends on: 467144
Assignee: events → nobody
QA Contact: ian → events
Attached patch new patch (depends on bug 569719) (obsolete) (deleted) — Splinter Review
With the changes in bug 569719 we can fix this a lot more cheaply. I discovered this quite by accident when those changes made the existing, xfailed test case start passing. This patch beefs up the test case -- bz, please let me know if it doesn't cover all the possibilities you can think of -- and closes the gap bz thought might still exist. Which it did, according to the revised test case.
Assignee: nobody → zweinberg
Attachment #222747 - Attachment is obsolete: true
Attachment #223659 - Attachment is obsolete: true
Status: NEW → ASSIGNED
Attachment #459916 - Flags: review?(bzbarsky)
Depends on: 569719
Comment on attachment 459916 [details] [diff] [review] new patch (depends on bug 569719) r=bzbarsky. The test looks good.
Attachment #459916 - Flags: review?(bzbarsky) → review+
Attached patch revised for changes in 569719 (obsolete) (deleted) — Splinter Review
Had to revise this a little after some changes requested by dbaron in bug 569719. There's a subtlety here: at the end of 569719, RuleMatched is the only place that calls SetImmutable on declarations, so we can use IsMutable on the declaration to detect whether RuleMatched has been called; but after this change there is another caller of SetImmutable, so we need to track RuleMatched having been called explicitly. Asking for re-review because of that. (bz: you might want to read the new part 16 of bug 569719 first.)
Attachment #459916 - Attachment is obsolete: true
Attachment #462229 - Flags: review?(bzbarsky)
Keywords: helpwanted
Attachment #462229 - Flags: approval2.0?
Comment on attachment 462229 [details] [diff] [review] revised for changes in 569719 Ah, yes. Good catch!
Attachment #462229 - Flags: review?(bzbarsky) → review+
Attached patch minor corrections (deleted) — Splinter Review
I forgot to initialize the new CSSStyleRuleImpl member variable in the other two constructors, so it blew up horribly on the try server.
Attachment #462637 - Flags: review+
Attachment #462637 - Flags: approval2.0?
Attachment #462229 - Attachment is obsolete: true
Attachment #462229 - Flags: approval2.0?
Attachment #462637 - Flags: approval2.0? → approval2.0+
Status: ASSIGNED → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
Flags: in-testsuite+
This didn't quite fix all cases of the problem. See bug 724128.
Blocks: 724128
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: