Closed
Bug 807911
Opened 12 years ago
Closed 12 years ago
whittle mutation events processing
Categories
(Core :: Disability Access APIs, defect)
Core
Disability Access APIs
Tracking
()
RESOLVED
FIXED
mozilla19
People
(Reporter: surkov, Assigned: surkov)
References
(Blocks 1 open bug)
Details
(Keywords: access)
Attachments
(1 file, 4 obsolete files)
52.53 KB,
patch
|
tbsaunde
:
review+
|
Details | Diff | Splinter Review |
it's not nice but it seems an improvement, we need a good code reorg for eventing
Attachment #677681 -
Flags: review?(trev.saunders)
Assignee | ||
Comment 1•12 years ago
|
||
fix some evident oversights
Attachment #677685 -
Flags: review?(trev.saunders)
Assignee | ||
Updated•12 years ago
|
Attachment #677681 -
Attachment is obsolete: true
Attachment #677681 -
Flags: review?(trev.saunders)
Comment 2•12 years ago
|
||
Comment on attachment 677685 [details] [diff] [review] patch2 >+AccReorderEvent::IsShowHideEventTarget(Accessible* aTarget) const const Accessible* ? >+ for (int32_t index = mDependentEvents.Length() - 1; index >= 0; index--) { so, that doesn't work when you have more than 2^31 events which is a bit of an edge case, but why not do for (uint32_t idx = count - 1; idx < count; idx--) ? (here and a couple places below) > enum EventGroup { it'd be nice to unify these type things somehow... >+ void ConnectTo(AccMutationEvent* aEvent) ConnectTo() makes me think we make this event subordinate of argument, not the reverse, how about AddSubMutationEvent() or something? >+ nsTArray<nsRefPtr<AccMutationEvent> > mDependentEvents; so, these evnets are all in the queue too right? so why do we need strong refs? Shouldn't you add cycle collector goo if we need strong refs here? >+ } break; // case eCoalesceReorder ugh at the style of this switch. nit, why not just get rid fo the braces for this case since you declare no locals? > case AccEvent::eCoalesceOfSameType: > { > // Coalesce old events by newer event. > for (int32_t index = tail - 1; index >= 0; index--) { > AccEvent* accEvent = mEvents[index]; > if (accEvent->mEventType == tailEvent->mEventType && >+ accEvent->mEventRule == tailEvent->mEventRule) { >+ accEvent->mEventRule = AccEvent::eDoNotEmit; >+ return; >+ } >+ } >+ for (int32_t index = tail - 1; index >= 0; index--) { >+ AccEvent* accEvent = mEvents[index]; >+ if (accEvent->mEventType == tailEvent->mEventType && > accEvent->mEventRule == tailEvent->mEventRule) { > accEvent->mEventRule = AccEvent::eDoNotEmit; > return; > } > } what is this second loop for? it looks exactly the same as the one above, so I don't see why it isn't a really slow nop >+NotificationController::CoalesceReorderEvents(AccEvent* aTailEvent) > { >+ for (int32_t index = mEvents.Length() - 2; index >= 0; index--) { nit, s/index/idx/ ? nit, for (uint32_t idx = length - 2; idx < length; idx--) >+ // Skip event from different document since we don't coalesce them. >+ if (thisEvent->mAccessible->Document() != >+ aTailEvent->mAccessible->Document()) >+ continue; I shtis actually possible? if not why don't we just assert this never happens >+ DocAccessible* document = thisEvent->mAccessible->Document(); nit, get rid of or move to first use? >+ else if (eventType == nsIAccessibleEvent::EVENT_HIDE) >+ NS_ERROR("Accessible tree was modified after it was removed! Huh?"); seems sort of dangerious to have macro like that, iirc some of those old macros are broken and don't end up being a statement in non debug builds. >+NotificationController::ProcessEventQueue() >+ AccEvent* event = events[idx]; >+ if (event->mEventRule != AccEvent::eDoNotEmit) { nit, if == continue ? >+ if (hyperText && >+ NS_SUCCEEDED(hyperText->GetCaretOffset(&caretOffset))) { don't we have a decomified version of that? >+ nsRefPtr<AccEvent> caretMoveEvent = >+ new AccCaretMoveEvent(hyperText, caretOffset); >+ nsEventShell::FireEvent(caretMoveEvent); >+ >+ // There's a selection so fire selection change as well. >+ int32_t selectionCount; >+ hyperText->GetSelectionCount(&selectionCount); >+ if (selectionCount) >+ nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED, >+ hyperText); >+ } >+ continue; this whole thing is rather ugly DocAccessible::ProcessContentInserted(Accessible* aContainer, > const nsTArray<nsCOMPtr<nsIContent> >* aInsertedContent) >+ if (presentContainer != aContainer) >+ continue; shouldn't you check presentContainer is not null too? >+ if (containerNotUpdated) { >+ containerNotUpdated = false; why not just do this before the loop?
Assignee | ||
Comment 3•12 years ago
|
||
(In reply to Trevor Saunders (:tbsaunde) from comment #2) > >+ for (int32_t index = mDependentEvents.Length() - 1; index >= 0; index--) { > > so, that doesn't work when you have more than 2^31 events which is a bit of > an edge case, but why not do > > for (uint32_t idx = count - 1; idx < count; idx--) ? (here and a couple > places below) It's tricky, I don't mind I guess but is it part of good coding style (for example are there mozilla precedents of its usage)? Alternatively I could go with do/while or 64 bit int but not sure it's nicer. > > enum EventGroup { > > it'd be nice to unify these type things somehow... ideas? > >+ void ConnectTo(AccMutationEvent* aEvent) > > ConnectTo() makes me think we make this event subordinate of argument, not > the reverse, how about AddSubMutationEvent() or something? ok, I don't mind. In future we might want to have something unified through different event classes. > >+ nsTArray<nsRefPtr<AccMutationEvent> > mDependentEvents; > > so, these evnets are all in the queue too right? so why do we need strong > refs? Shouldn't you add cycle collector goo if we need strong refs here? it's safe to keep weak refs because we clean the queue after it was processed. I'll fix it. > >+ } break; // case eCoalesceReorder > > ugh at the style of this switch. nothing to change, right? > nit, why not just get rid fo the braces for this case since you declare no > locals? ok > what is this second loop for? it looks exactly the same as the one above, so > I don't see why it isn't a really slow nop I guess artifacts :) Thanks for the catch. > >+NotificationController::CoalesceReorderEvents(AccEvent* aTailEvent) > > { > >+ for (int32_t index = mEvents.Length() - 2; index >= 0; index--) { > > nit, s/index/idx/ ? we used to have 'index' in the whole file. I don't mind about 'index' replacement but perhaps we should do that throughoutly. > >+ // Skip event from different document since we don't coalesce them. > >+ if (thisEvent->mAccessible->Document() != > >+ aTailEvent->mAccessible->Document()) > >+ continue; > > I shtis actually possible? if not why don't we just assert this never happens It shouldn't be (just copy/paste old logic). I'll assert. > >+ DocAccessible* document = thisEvent->mAccessible->Document(); > > nit, get rid of or move to first use? ok, I'll use mDocument and will assert if queued event belongs to different document. > >+ else if (eventType == nsIAccessibleEvent::EVENT_HIDE) > >+ NS_ERROR("Accessible tree was modified after it was removed! Huh?"); > > seems sort of dangerious to have macro like that, iirc some of those old > macros are broken and don't end up being a statement in non debug builds. ok, which one should I use instead? > >+NotificationController::ProcessEventQueue() > >+ AccEvent* event = events[idx]; > >+ if (event->mEventRule != AccEvent::eDoNotEmit) { > > nit, if == continue ? no, we need to process hide event to destroy the tree (bug 759875) > >+ if (hyperText && > >+ NS_SUCCEEDED(hyperText->GetCaretOffset(&caretOffset))) { > > don't we have a decomified version of that? funny but not yet. > >+ // There's a selection so fire selection change as well. > >+ int32_t selectionCount; > >+ hyperText->GetSelectionCount(&selectionCount); > >+ if (selectionCount) > >+ nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED, > >+ hyperText); > >+ } > >+ continue; > > this whole thing is rather ugly heritage > DocAccessible::ProcessContentInserted(Accessible* aContainer, > > const nsTArray<nsCOMPtr<nsIContent> >* aInsertedContent) > >+ if (presentContainer != aContainer) > >+ continue; > > shouldn't you check presentContainer is not null too? aContainer is never null > >+ if (containerNotUpdated) { > >+ containerNotUpdated = false; > > why not just do this before the loop? to filter out the case when nothing was changed, for example, node was inserted and then moved somewhere else.
Assignee | ||
Comment 4•12 years ago
|
||
Attachment #677685 -
Attachment is obsolete: true
Attachment #677685 -
Flags: review?(trev.saunders)
Attachment #679970 -
Flags: review?(trev.saunders)
Assignee | ||
Comment 5•12 years ago
|
||
patch 3 was wrong
Attachment #679970 -
Attachment is obsolete: true
Attachment #679970 -
Flags: review?(trev.saunders)
Attachment #679971 -
Flags: review?(trev.saunders)
Assignee | ||
Comment 6•12 years ago
|
||
those document comparison stuff was about application accessible, so no AccReorderEvent for app accessible to avoid that.
Attachment #679971 -
Attachment is obsolete: true
Attachment #679971 -
Flags: review?(trev.saunders)
Attachment #679995 -
Flags: review?(trev.saunders)
Comment 7•12 years ago
|
||
(In reply to alexander :surkov from comment #3) > (In reply to Trevor Saunders (:tbsaunde) from comment #2) > > > >+ for (int32_t index = mDependentEvents.Length() - 1; index >= 0; index--) { > > > > so, that doesn't work when you have more than 2^31 events which is a bit of > > an edge case, but why not do > > > > for (uint32_t idx = count - 1; idx < count; idx--) ? (here and a couple > > places below) > > It's tricky, I don't mind I guess but is it part of good coding style (for > example are there mozilla precedents of its usage)? > > Alternatively I could go with do/while or 64 bit int but not sure it's nicer. all I know of is the m.d.platform discussion a while back about signed vs unsigned, where that approach was brought up.
Assignee | ||
Comment 8•12 years ago
|
||
Ok, I'll change it. Other findings?
Comment 9•12 years ago
|
||
>
> > >+ else if (eventType == nsIAccessibleEvent::EVENT_HIDE)
> > >+ NS_ERROR("Accessible tree was modified after it was removed! Huh?");
> >
> > seems sort of dangerious to have macro like that, iirc some of those old
> > macros are broken and don't end up being a statement in non debug builds.
>
> ok, which one should I use instead?
looks its fine I think I was thinking of the MAI_foo macros
Comment 10•12 years ago
|
||
Comment on attachment 679995 [details] [diff] [review] patch5 NotificationController::QueueEvent(AccEvent* aEvent) { + NS_ASSERTION(aEvent->mAccessible && aEvent->mAccessible->IsApplication() || + aEvent->GetDocAccessible() == mDocument, + "Queued event belongs to another document!"); && binds tighter than || no, so that isn't really what you want is it? I'd do NS_ASSERT(aEvent->mAccessible, "event fired on not accessible node!"); NS_ASSERTION(aEvent->mAccessible->IsApplication() || aEvent->mAccessible->Document() == mDOcument, "event fired on wrong document!"); I guess that makes the first assert not really necessary, but maybe nice for understanding crashes faster.
Attachment #679995 -
Flags: review?(trev.saunders) → review+
Assignee | ||
Comment 11•12 years ago
|
||
(In reply to Trevor Saunders (:tbsaunde) from comment #10) > Comment on attachment 679995 [details] [diff] [review] > patch5 > > NotificationController::QueueEvent(AccEvent* aEvent) > { > + NS_ASSERTION(aEvent->mAccessible && aEvent->mAccessible->IsApplication() > || > + aEvent->GetDocAccessible() == mDocument, > + "Queued event belongs to another document!"); > > && binds tighter than || no, so that isn't really what you want is it? I'd > do > > NS_ASSERT(aEvent->mAccessible, "event fired on not accessible node!"); > NS_ASSERTION(aEvent->mAccessible->IsApplication() || > aEvent->mAccessible->Document() == mDOcument, "event fired on wrong > document!"); we have null mAccessible events (those having mNode initialized) that's why I did aEvent->mAccessible && aEvent->mAccessible->IsApplication() || aEvent->GetDocAccessible() == mDocument i.e. if it's application accessible then don't fail since app acc doesn't have document and then (|| part) if event is fired for wrong document then assert.
Comment 12•12 years ago
|
||
(In reply to alexander :surkov from comment #11) > (In reply to Trevor Saunders (:tbsaunde) from comment #10) > > Comment on attachment 679995 [details] [diff] [review] > > patch5 > > > > NotificationController::QueueEvent(AccEvent* aEvent) > > { > > + NS_ASSERTION(aEvent->mAccessible && aEvent->mAccessible->IsApplication() > > || > > + aEvent->GetDocAccessible() == mDocument, > > + "Queued event belongs to another document!"); > > > > && binds tighter than || no, so that isn't really what you want is it? I'd > > do > > > > NS_ASSERT(aEvent->mAccessible, "event fired on not accessible node!"); > > NS_ASSERTION(aEvent->mAccessible->IsApplication() || > > aEvent->mAccessible->Document() == mDOcument, "event fired on wrong > > document!"); > > we have null mAccessible events (those having mNode initialized) that's why > I did hm, I thought AccEvent::GetAccessible() was called before this point to figure out what the accessible is, and we do need an accessible for the event at some point to be able to fire it. > aEvent->mAccessible && aEvent->mAccessible->IsApplication() || > aEvent->GetDocAccessible() == mDocument > > i.e. if it's application accessible then don't fail since app acc doesn't > have document and then (|| part) if event is fired for wrong document then > assert. well, as it is that will crash when event has no accessible right? don't you want aEvent->mAccessible && (aEvent->mAccessible->IsApplication() || aEvent->mAccessible->Document() == mDocument
Assignee | ||
Comment 13•12 years ago
|
||
(In reply to Trevor Saunders (:tbsaunde) from comment #12) > well, as it is that will crash when event has no accessible right? why it should crash? if aEvent->mAccessible is null then aEvent->mAccessible && aEvent->mAccessible->IsApplication() is false and we check aEvent->GetDocAccessible() == mDocument AccEvent::GetDocAccessible() shouldn't crash > don't you > want > aEvent->mAccessible && (aEvent->mAccessible->IsApplication() || > aEvent->mAccessible->Document() == mDocument that will be false for all events having mNode initialized instead mAccessible, right?
Assignee | ||
Comment 14•12 years ago
|
||
landed http://hg.mozilla.org/integration/mozilla-inbound/rev/a2cdd1e64267 Trev, if we still have the issue with that assertion then I'll file a follow up on it. Please let me know.
Comment 15•12 years ago
|
||
(In reply to alexander :surkov from comment #13) > (In reply to Trevor Saunders (:tbsaunde) from comment #12) > > > well, as it is that will crash when event has no accessible right? > > why it should crash? > > if aEvent->mAccessible is null > then > aEvent->mAccessible && aEvent->mAccessible->IsApplication() is false and we > check > aEvent->GetDocAccessible() == mDocument > > AccEvent::GetDocAccessible() shouldn't crash yeah, seems I just can't read sorry!
Comment 16•12 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/a2cdd1e64267
Status: ASSIGNED → RESOLVED
Closed: 12 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla19
You need to log in
before you can comment on or make changes to this bug.
Description
•