Bug 30505

Summary: Counters aren't updated when a new counter-increment is added
Product: WebKit Reporter: Shinichiro Hamaji <hamaji>
Component: CSSAssignee: Nobody <webkit-unassigned>
Status: RESOLVED DUPLICATE    
Severity: Normal CC: darin, eric
Priority: P2    
Version: 528+ (Nightly build)   
Hardware: PC   
OS: OS X 10.5   
URL: http://shinh.skr.jp/t/add-increment.html
Attachments:
Description Flags
Patch v1
none
Patch v2
none
Patch v3
none
Patch v4
darin: review+, hamaji: commit-queue-
Resolving conflict for r50960 none

Description Shinichiro Hamaji 2009-10-19 01:29:20 PDT
This is the first step of Bug 23262.

The values of counters aren't updated when a new counter-increment element is added. Firefox and IE handle the test URL correctly.
Comment 1 Shinichiro Hamaji 2009-10-19 01:35:27 PDT
Created attachment 41401 [details]
Patch v1
Comment 2 Eric Seidel (no email) 2009-10-19 13:39:18 PDT
Comment on attachment 41401 [details]
Patch v1

Shouldn't this be dumpAsText?
Comment 3 Shinichiro Hamaji 2009-10-20 00:52:38 PDT
Comment on attachment 41401 [details]
Patch v1

As same as tests of Bug 23262, innerText doesn't output counter values.

I looked how innerText works a bit and found it is not easy to change innerText to output counter values. innerText uses TextIterator to gather texts and TextIterator doesn't care about generated contents like counters.

Another idea is adding layoutTestController.dumpCounterNodes(). I think this is reasonable. I'll file another bug. For now, I remove review? bit.
Comment 4 Shinichiro Hamaji 2009-10-30 14:39:16 PDT
Created attachment 42237 [details]
Patch v2
Comment 5 Shinichiro Hamaji 2009-10-30 14:40:20 PDT
OK, as now we have counterValueForElementById, we can test this with dumpAsText.
Comment 6 Darin Adler 2009-10-30 14:52:33 PDT
Comment on attachment 42237 [details]
Patch v2

> +void RenderCounter::addCounterNodes(RenderObject* object) {

Brace needs to be on the following line, not the same line.

I don’t understand the high level concept of this patch enough to review it. I believe the idea here is that it's important to explicitly create some counter nodes in certain cases. So you added a function that calls the counter function in RenderCounter.cpp because of its side effect. But I don't understand why creating more counter nodes is the way to fix a bug.

What is the nature of the bug?

Further, what does isRooted have to do with any of this? It seems clearly wrong to be walking up the entire render tree looking for a RenderView in this code.
Comment 7 Shinichiro Hamaji 2009-11-02 12:53:32 PST
Created attachment 42339 [details]
Patch v3
Comment 8 Shinichiro Hamaji 2009-11-02 12:56:40 PST
I'll describe this issue and why I chose this way.

Now, counter values are calculated when their originalText() are called. originalText() calls counter() and it traverses the tree in ascending order to update counter values. This approach works if there are no dynamic changes. 

However, if a new increment element (say [I]) is inserted before an RenderCounter element (say [A]) and no other RenderCounter are inserted after the increment element, the counter value of [A] won't be updated because originalText() for [A] doesn't trigger counter() and it just uses the value of counter node which are already constructed.

(Note that if another RenderCounter (say [B]) is added after [I], [B]'s originalText() triggers counter(), notices [I] is added, creates a counter node for [I], and updates all counter values including [A]'s)

I came up with two solutions for this:

- Insert counter nodes when counter elements are added and this addition will update the values of descendants if needed. This is what my patch is doing.
- When a counter element is added, mark descendants of the added element as dirty and make the counter values to be updated in the next call of originalText(). If we can mark descendants as dirty, I think we can update the values of counters when we mark. That's why I didn't choose this way.

Of course, there may be another better way which fixes this issue. If someone kindly suggest better ways, I'm happy to fix my patch.

As for extra counter nodes, my patch doesn't create extra counter nodes actually. The counter() function doesn't create new counter nodes if corresponding counter node already exists.

> Further, what does isRooted have to do with any of this? It seems clearly wrong
> to be walking up the entire render tree looking for a RenderView in this code.

Ah, I think !isAnonymous() is much better here. What I want to do is

- for increment and reset, we create counter nodes when these nodes are added
- for content:counter(...), we create counter nodes when their originalText is called(). Because :before and :after are not connected to the root node in RenderObject::addChild(), we cannot create counter nodes for them with correct values here. Deferring counter node creation for them are OK because 1. they don't change the values of descendants as they aren't increment nor reset 2. originalText() will be called for them and their values will be calculated eventually.

I used isRooted() because of the second item, but I've noticed !isAnonymous() is sufficient for this purpose so I changed to use it.

> Brace needs to be on the following line, not the same line.

Sorry for this mistake... I often forgot this rule (and forgot to use check-webkit-style as well)
Comment 9 Darin Adler 2009-11-05 16:29:03 PST
Comment on attachment 42339 [details]
Patch v3

It seems more elegant to me to delete the possibly-invalid counter nodes than to create new counter nodes just because something is going into the tree. The counter value may never be used and it seems unfortunate to compute its value explicitly instead of lazily. That having been said, the fix seems OK to me and won't have any effect on pages not using counters, so I'll say r=me

I think the name of the "counter" function, which I named, is extremely weak. It's really unclear you would call it to create a counter for its side effects.
Comment 10 Shinichiro Hamaji 2009-11-09 07:57:36 PST
Created attachment 42751 [details]
Patch v4
Comment 11 Shinichiro Hamaji 2009-11-09 08:13:11 PST
(In reply to comment #9)
> (From update of attachment 42339 [details])
> It seems more elegant to me to delete the possibly-invalid counter nodes than
> to create new counter nodes just because something is going into the tree. The
> counter value may never be used and it seems unfortunate to compute its value
> explicitly instead of lazily. That having been said, the fix seems OK to me and
> won't have any effect on pages not using counters, so I'll say r=me

OK, I uploaded another patch with invalidating approach. Indeed, this approach would be faster than the previous approach for usual (no-dynamic-change) cases. Thank you for the comment!
 
> I think the name of the "counter" function, which I named, is extremely weak.
> It's really unclear you would call it to create a counter for its side effects.

Agreed. I'd like to create another patch to fix this naming, but I couldn't figure out a good name for this function. Do you have any good idea for this? createCounterNodeIfNeeded or something like this?
Comment 12 Darin Adler 2009-11-09 10:07:41 PST
(In reply to comment #11)
> Agreed. I'd like to create another patch to fix this naming, but I couldn't
> figure out a good name for this function. Do you have any good idea for this?
> createCounterNodeIfNeeded or something like this?

I think just calling it create without the "if needed" may be OK even if it doesn't always create a new counter node. To avoid the "create" rule for object ownership, we should probably call it makeCounterNode.
Comment 13 Darin Adler 2009-11-09 10:08:51 PST
Comment on attachment 42751 [details]
Patch v4

Better. r=me
Comment 14 Shinichiro Hamaji 2009-11-10 00:08:57 PST
Comment on attachment 42751 [details]
Patch v4

Putting cq- as this patch cannot be committed until Bug 31286 is resolved.
Comment 15 Shinichiro Hamaji 2009-11-16 00:10:37 PST
Comment on attachment 42751 [details]
Patch v4

Rejecting patch 42751 from commit-queue.

Failed to run "WebKitTools/Scripts/build-webkit" exit_code: 1
Last 500 characters of output:
gfzddrsaowyo/WebCorePrefix.h -c /Users/hamaji/GitKit/WebCore/xml/XMLHttpRequest.cpp -o /Users/hamaji/GitKit/WebKitBuild/WebCore.build/Release/WebCore.build/Objects-normal/i386/XMLHttpRequest.o
** BUILD FAILED **

The following build commands failed:
WebCore:
	Distributed-CompileC /Users/hamaji/GitKit/WebKitBuild/WebCore.build/Release/WebCore.build/Objects-normal/i386/RenderCounter.o /Users/hamaji/GitKit/WebCore/rendering/RenderCounter.cpp normal i386 c++ com.apple.compilers.gcc.4_2
(1 failure)
Comment 16 Shinichiro Hamaji 2009-11-16 00:40:46 PST
Conflicted with Bug 31213. As it seems Carol is also working for this issue, I'll discuss on Bug 11031.
Comment 17 Shinichiro Hamaji 2009-11-16 05:37:11 PST
Created attachment 43300 [details]
Resolving conflict for r50960
Comment 18 Shinichiro Hamaji 2009-11-16 06:02:30 PST
(In reply to comment #17)
> Created an attachment (id=43300) [details]
> Resolving conflict for r50960

I added a comment on this patch in Bug 11031. I don't set the review? bit for this patch until the discussion in Bug 11031 finishes.
Comment 19 Eric Seidel (no email) 2009-12-09 14:03:10 PST
PIng?  Is Patch v4 waiting to be landed?
Comment 20 Shinichiro Hamaji 2009-12-09 18:32:05 PST
Sorry, this bug will be fixed by Carol.

*** This bug has been marked as a duplicate of bug 11031 ***