Closed Bug 1408125 Opened 7 years ago Closed 7 years ago

Reduce the ways in which InsertNode() results in a call to nsINode::GetChildAt()

Categories

(Core :: DOM: Editor, enhancement, P3)

enhancement

Tracking

()

RESOLVED FIXED
mozilla59
Tracking Status
firefox59 --- fixed

People

(Reporter: ehsan.akhgari, Assigned: masayuki)

References

Details

Attachments

(5 files, 3 obsolete files)

(deleted), text/x-review-board-request
m_kato
: review+
Details
(deleted), text/x-review-board-request
m_kato
: review+
Details
(deleted), text/x-review-board-request
m_kato
: review+
Details
(deleted), text/x-review-board-request
m_kato
: review+
Details
(deleted), text/x-review-board-request
m_kato
: review+
Details
No description provided.
This patch converts almost all of the call sites over to passing the extra argument explicitly.
Attachment #8918143 - Flags: review?(masayuki)
Comment on attachment 8918141 [details] [diff] [review] Part 1: Remove nsIEditor.insertNode(), but keep the underlying method as a protected EditorBase method I don't think we should remove this method from nsIEditor because this supports undo/redo of inserting the node. And comm-central and BlueGriffon use this method. https://searchfox.org/comm-central/search?q=.insertNode&case=false&regexp=false&path= https://github.com/therealglazou/bluegriffon/search?utf8=%E2%9C%93&q=.insertNode&type= Even if we need to remove this method from mozilla-central, we need more discussion.
Attachment #8918141 - Flags: review?(masayuki) → review-
Please comment something about how do you think about removing nsIEditor.insertNode() if you think it's okay.
Comment on attachment 8918142 [details] [diff] [review] Part 2: Add an optional argument to InsertNode() to allow callers to pass the child node when they know it >@@ -1455,42 +1455,44 @@ EditorBase::CreateNode(nsAtom* aTag, > } > > return ret.forget(); > } > > nsresult > EditorBase::InsertNode(nsIDOMNode* aNode, > nsIDOMNode* aParent, >- int32_t aPosition) >+ int32_t aPosition, >+ nsIContent* aChildAtPosition) Perhaps, you can add new overload instead of adding new argument to this method.
Attachment #8918142 - Flags: review?(masayuki) → review+
Comment on attachment 8918142 [details] [diff] [review] Part 2: Add an optional argument to InsertNode() to allow callers to pass the child node when they know it > InsertNodeTransaction::InsertNodeTransaction(nsIContent& aNode, > nsINode& aParent, > int32_t aOffset, >- EditorBase& aEditorBase) >+ EditorBase& aEditorBase, >+ nsIContent* aChildAtOffset) > : mNode(&aNode) > , mParent(&aParent) > , mOffset(aOffset) > , mEditorBase(&aEditorBase) >+ , mRefNode(aChildAtOffset) > { Ah, and please add MOZ_ASSERT here: MOZ_ASSERT(!aChildAtOffset || aChildAtOffset == aParent.GetChildAt(aOffset));
> MOZ_ASSERT(!aChildAtOffset || aChildAtOffset == aParent.GetChildAt(aOffset)); Oops, aChildAtOffset->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE is also allowed.
Comment on attachment 8918143 [details] [diff] [review] Part 3: Pass the child node at the offset as an extra argument where possible to InsertNode() >@@ -1725,23 +1725,27 @@ EditorBase::RemoveContainer(nsIContent* aNode) > > // Loop through the children of inNode and promote them into inNode's parent > uint32_t nodeOrigLen = aNode->GetChildCount(); > > // notify our internal selection state listener > AutoRemoveContainerSelNotify selNotify(mRangeUpdater, aNode, parent, > offset, nodeOrigLen); > >+ nsIContent* childAtOffset = aNode; >+ > while (aNode->HasChildren()) { > nsCOMPtr<nsIContent> child = aNode->GetLastChild(); > nsresult rv = DeleteNode(child); > NS_ENSURE_SUCCESS(rv, rv); > >- rv = InsertNode(*child, *parent, offset); >+ rv = InsertNode(*child, *parent, offset, childAtOffset); > NS_ENSURE_SUCCESS(rv, rv); >+ >+ childAtOffset = childAtOffset->GetPreviousSibling(); Perhaps, adding |MOZ_ASSERT(childAtOffset == aNode);| or doing |childAtOffset = aNode;| is safer? >@@ -1623,19 +1623,25 @@ HTMLEditor::InsertNodeAtPoint(nsIDOMNode* aNode, > NS_ENSURE_STATE(offset != -1); > *ioParent = GetAsDOMNode(parent); > *ioOffset = offset; > if (ioChildAtOffset) { > *ioChildAtOffset = GetAsDOMNode(child); > } > } > // Now we can insert the new node >- nsresult rv = InsertNode(*node, *parent, *ioOffset); >+ nsCOMPtr<nsIContent> child; >+ if (ioChildAtOffset) { >+ child = do_QueryInterface(*ioChildAtOffset); >+ } >+ nsresult rv = InsertNode(*node, *parent, *ioOffset, child); > if (isDocumentFragment) { > *ioChildAtOffset = do_QueryInterface(parent->GetChildAt(*ioOffset)); >+ } else if (ioChildAtOffset) { >+ *ioChildAtOffset = GetAsDOMNode(child); Hmm, QI is also slow... We should make it nsINode or nsIContent later. >@@ -129,24 +129,28 @@ HTMLEditor::LoadHTML(const nsAString& aInputString) > // create fragment for pasted html > nsCOMPtr<nsIDOMDocumentFragment> docfrag; > rv = range->CreateContextualFragment(aInputString, getter_AddRefs(docfrag)); > NS_ENSURE_SUCCESS(rv, rv); > // put the fragment into the document > nsCOMPtr<nsINode> parent = range->GetStartContainer(); > NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER); > uint32_t childOffset = range->StartOffset(); >+ nsCOMPtr<nsIContent> child = range->GetChildAtStartOffset(); > > nsCOMPtr<nsIDOMNode> nodeToInsert; > docfrag->GetFirstChild(getter_AddRefs(nodeToInsert)); > while (nodeToInsert) { > rv = InsertNode(nodeToInsert, GetAsDOMNode(parent), >- static_cast<int32_t>(childOffset++)); >+ static_cast<int32_t>(childOffset++), child); childOffset is incremented *after* InsertNode() call... This is really tricky. Could you put off the increment after following NS_ENSURE_SUCCESS? Calling GetNextSibling() at every increment of offset is too dangerous. I guess we should have a struct like RangeBoundary anyway. I'll take a look if I have much time during your vacation.
Attachment #8918143 - Flags: review?(masayuki) → review+
(In reply to Masayuki Nakano [:masayuki] (JST, +0900)(offline: 10/17 and 10/23) from comment #6) > Comment on attachment 8918142 [details] [diff] [review] > Part 2: Add an optional argument to InsertNode() to allow callers to pass > the child node when they know it > > >@@ -1455,42 +1455,44 @@ EditorBase::CreateNode(nsAtom* aTag, > > } > > > > return ret.forget(); > > } > > > > nsresult > > EditorBase::InsertNode(nsIDOMNode* aNode, > > nsIDOMNode* aParent, > >- int32_t aPosition) > >+ int32_t aPosition, > >+ nsIContent* aChildAtPosition) > > Perhaps, you can add new overload instead of adding new argument to this > method. I think adding an overload instead of removing the IDL method works fine. The IDL method will just take the slow path unconditionally...
(In reply to Masayuki Nakano [:masayuki] (JST, +0900)(offline: 10/17 and 10/23) from comment #9) > >+ nsIContent* childAtOffset = aNode; > >+ > > while (aNode->HasChildren()) { > > nsCOMPtr<nsIContent> child = aNode->GetLastChild(); > > nsresult rv = DeleteNode(child); > > NS_ENSURE_SUCCESS(rv, rv); > > > >- rv = InsertNode(*child, *parent, offset); > >+ rv = InsertNode(*child, *parent, offset, childAtOffset); > > NS_ENSURE_SUCCESS(rv, rv); > >+ > >+ childAtOffset = childAtOffset->GetPreviousSibling(); > > Perhaps, adding |MOZ_ASSERT(childAtOffset == aNode);| or doing > |childAtOffset = aNode;| is safer? No, childAtOffset won't be aNode in all loop iterations, since we keep inserting children at |offset| so they will push aNode off towards the right, so after the first iteration of the loop childAtOffset will no longer point to aNode. Unless I'm missing something? > >@@ -129,24 +129,28 @@ HTMLEditor::LoadHTML(const nsAString& aInputString) > > // create fragment for pasted html > > nsCOMPtr<nsIDOMDocumentFragment> docfrag; > > rv = range->CreateContextualFragment(aInputString, getter_AddRefs(docfrag)); > > NS_ENSURE_SUCCESS(rv, rv); > > // put the fragment into the document > > nsCOMPtr<nsINode> parent = range->GetStartContainer(); > > NS_ENSURE_TRUE(parent, NS_ERROR_NULL_POINTER); > > uint32_t childOffset = range->StartOffset(); > >+ nsCOMPtr<nsIContent> child = range->GetChildAtStartOffset(); > > > > nsCOMPtr<nsIDOMNode> nodeToInsert; > > docfrag->GetFirstChild(getter_AddRefs(nodeToInsert)); > > while (nodeToInsert) { > > rv = InsertNode(nodeToInsert, GetAsDOMNode(parent), > >- static_cast<int32_t>(childOffset++)); > >+ static_cast<int32_t>(childOffset++), child); > > childOffset is incremented *after* InsertNode() call... This is really > tricky. Could you put off the increment after following NS_ENSURE_SUCCESS? Sure. > Calling GetNextSibling() at every increment of offset is too dangerous. I > guess we should have a struct like RangeBoundary anyway. I'll take a look if > I have much time during your vacation. Thank you!
Pushed by eakhgari@mozilla.com: https://hg.mozilla.org/integration/mozilla-inbound/rev/d59889304b3f Part 1: Add an optional argument to InsertNode() to allow callers to pass the child node when they know it; r=masayuki https://hg.mozilla.org/integration/mozilla-inbound/rev/19fee71d7e27 Part 2: Pass the child node at the offset as an extra argument where possible to InsertNode(); r=masayuki
Backed out for asserting in clipboard test editor/libeditor/tests/test_bug1306532.html: https://hg.mozilla.org/integration/mozilla-inbound/rev/1f8ee2e6f0658e2ab760a5a7618ac0fa2298760d https://hg.mozilla.org/integration/mozilla-inbound/rev/f5034aeb64077a10abfabc0d58d046b2e6cee5c7 Push with failures: https://treeherder.mozilla.org/#/jobs?repo=mozilla-inbound&revision=19fee71d7e277ee56f7674ca7d40bea8eb5d7945&filter-resultStatus=testfailed&filter-resultStatus=busted&filter-resultStatus=exception&filter-resultStatus=retry&filter-resultStatus=usercancel Failure log: https://treeherder.mozilla.org/logviewer.html#?job_id=136901413&repo=mozilla-inbound 14:35:50 INFO - TEST-START | editor/libeditor/tests/test_bug1306532.html 14:35:50 INFO - GECKO(4556) | ++DOMWINDOW == 22 (090FBC00) [pid = 3204] [serial = 22] [outer = 10267000] 14:35:50 INFO - GECKO(4556) | [Child 3204, Main Thread] WARNING: stylo: Web Components not supported yet: file z:/build/build/src/dom/base/nsDocument.cpp, line 6457 14:35:50 INFO - GECKO(4556) | [Child 3204, Main Thread] WARNING: stylo: Web Components not supported yet: file z:/build/build/src/dom/base/nsDocument.cpp, line 6457 14:35:50 INFO - GECKO(4556) | [Child 3204, Main Thread] WARNING: Unable to find interface object on global: file z:/build/build/src/dom/base/nsDOMClassInfo.cpp, line 1765 14:35:50 INFO - GECKO(4556) | ++DOCSHELL 0918B400 == 4 [pid = 3204] [id = {18f75a03-c5ca-4009-bb57-554730f1ec79}] 14:35:50 INFO - GECKO(4556) | ++DOMWINDOW == 23 (0918E800) [pid = 3204] [serial = 23] [outer = 00000000] 14:35:50 INFO - GECKO(4556) | ++DOMWINDOW == 24 (0918F400) [pid = 3204] [serial = 24] [outer = 0918E800] 14:35:50 INFO - GECKO(4556) | [Child 3204, Main Thread] WARNING: stylo: Web Components not supported yet: file z:/build/build/src/dom/base/nsDocument.cpp, line 6457 14:35:50 INFO - GECKO(4556) | [Child 3204, Main Thread] WARNING: stylo: Web Components not supported yet: file z:/build/build/src/dom/base/nsDocument.cpp, line 6457 14:35:50 INFO - GECKO(4556) | Assertion failure: !aChildAtOffset || aChildAtOffset->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE || aChildAtOffset == aParent.GetChildAt(aOffset), at z:/build/build/src/editor/libeditor/InsertNodeTransaction.cpp:37 14:35:50 INFO - GECKO(4556) | #01: mozilla::InsertNodeTransaction::InsertNodeTransaction(nsIContent &,nsINode &,int,mozilla::EditorBase &,nsIContent *) [editor/libeditor/InsertNodeTransaction.cpp:37] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #02: mozilla::EditorBase::CreateTxnForInsertNode(nsIContent &,nsINode &,int,nsIContent *) [editor/libeditor/EditorBase.cpp:4412] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #03: mozilla::EditorBase::InsertNode(nsIContent &,nsINode &,int,nsIContent *) [editor/libeditor/EditorBase.cpp:1498] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #04: mozilla::HTMLEditor::InsertNodeAtPoint(nsIDOMNode *,nsCOMPtr<nsIDOMNode> *,int *,bool,nsCOMPtr<nsIDOMNode> *) [editor/libeditor/HTMLEditor.cpp:1635] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #05: mozilla::HTMLEditor::DoInsertHTMLWithContext(nsTSubstring<char16_t> const &,nsTSubstring<char16_t> const &,nsTSubstring<char16_t> const &,nsTSubstring<char16_t> const &,nsIDOMDocument *,nsIDOMNode *,int,bool,bool,bool) [editor/libeditor/HTMLEditorDataTransfer.cpp:551] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #06: mozilla::HTMLEditor::InsertFromTransferable(nsITransferable *,nsIDOMDocument *,nsTSubstring<char16_t> const &,nsTSubstring<char16_t> const &,bool,nsIDOMNode *,int,bool) [editor/libeditor/HTMLEditorDataTransfer.cpp:1198] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #07: mozilla::HTMLEditor::Paste(int) [editor/libeditor/HTMLEditorDataTransfer.cpp:1465] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #08: mozilla::PasteCommand::DoCommand(char const *,nsISupports *) [editor/libeditor/EditorCommands.cpp:551] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #09: nsControllerCommandTable::DoCommand(char const *,nsISupports *) [dom/commandhandler/nsControllerCommandTable.cpp:147] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #10: nsBaseCommandController::DoCommand(char const *) [dom/commandhandler/nsBaseCommandController.cpp:136] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #11: nsCommandManager::DoCommand(char const *,nsICommandParams *,mozIDOMWindowProxy *) [dom/commandhandler/nsCommandManager.cpp:214] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #12: nsHTMLDocument::ExecCommand(nsTSubstring<char16_t> const &,bool,nsTSubstring<char16_t> const &,nsIPrincipal &,mozilla::ErrorResult &) [dom/html/nsHTMLDocument.cpp:3334] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #13: mozilla::dom::HTMLDocumentBinding::execCommand [s3:gecko-generated-sources:a01b707c2c606b06856aa6e34e7f0f04cce604dfefff96795dea5235e28836bee41d7368001060e59e9f5e8a7e386eff281167cb624e4b7b79e8ff7de55d46b2/dom/bindings/HTMLDocumentBinding.cpp::892] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #14: mozilla::dom::GenericBindingMethod(JSContext *,unsigned int,JS::Value *) [dom/bindings/BindingUtils.cpp:3039] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #15: js::CallJSNative(JSContext *,bool (*)(JSContext *,unsigned int,JS::Value *),JS::CallArgs const &) [js/src/jscntxtinlines.h:291] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #16: js::InternalCallOrConstruct(JSContext *,JS::CallArgs const &,js::MaybeConstruct) [js/src/vm/Interpreter.cpp:482] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #17: InternalCall [js/src/vm/Interpreter.cpp:531] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #18: js::Call(JSContext *,JS::Handle<JS::Value>,JS::Handle<JS::Value>,js::AnyInvokeArgs const &,JS::MutableHandle<JS::Value>) [js/src/vm/Interpreter.cpp:550] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #19: js::fun_apply(JSContext *,unsigned int,JS::Value *) [js/src/jsfun.cpp:1306] 14:35:50 INFO - 14:35:50 INFO - GECKO(4556) | #20: js::CallJSNative(JSContext *,bool (*)(JSContext *,unsigned int,JS::Value *),JS::CallArgs const &) [js/src/jscntxtinlines.h:291] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #21: js::InternalCallOrConstruct(JSContext *,JS::CallArgs const &,js::MaybeConstruct) [js/src/vm/Interpreter.cpp:482] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #22: InternalCall [js/src/vm/Interpreter.cpp:531] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #23: Interpret [js/src/vm/Interpreter.cpp:3076] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #24: js::RunScript(JSContext *,js::RunState &) [js/src/vm/Interpreter.cpp:432] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #25: js::InternalCallOrConstruct(JSContext *,JS::CallArgs const &,js::MaybeConstruct) [js/src/vm/Interpreter.cpp:504] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #26: InternalCall [js/src/vm/Interpreter.cpp:531] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #27: Interpret [js/src/vm/Interpreter.cpp:3076] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #28: js::RunScript(JSContext *,js::RunState &) [js/src/vm/Interpreter.cpp:432] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #29: js::InternalCallOrConstruct(JSContext *,JS::CallArgs const &,js::MaybeConstruct) [js/src/vm/Interpreter.cpp:504] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #30: InternalCall [js/src/vm/Interpreter.cpp:531] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #31: js::Call(JSContext *,JS::Handle<JS::Value>,JS::Handle<JS::Value>,js::AnyInvokeArgs const &,JS::MutableHandle<JS::Value>) [js/src/vm/Interpreter.cpp:550] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #32: js::ScriptedProxyHandler::call(JSContext *,JS::Handle<JSObject *>,JS::CallArgs const &) [js/src/proxy/ScriptedProxyHandler.cpp:1159] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #33: js::Proxy::call(JSContext *,JS::Handle<JSObject *>,JS::CallArgs const &) [js/src/proxy/Proxy.cpp:512] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #34: js::proxy_Call(JSContext *,unsigned int,JS::Value *) [js/src/proxy/Proxy.cpp:787] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #35: js::CallJSNative(JSContext *,bool (*)(JSContext *,unsigned int,JS::Value *),JS::CallArgs const &) [js/src/jscntxtinlines.h:291] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #36: js::InternalCallOrConstruct(JSContext *,JS::CallArgs const &,js::MaybeConstruct) [js/src/vm/Interpreter.cpp:464] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #37: InternalCall [js/src/vm/Interpreter.cpp:531] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #38: js::Call(JSContext *,JS::Handle<JS::Value>,JS::Handle<JS::Value>,js::AnyInvokeArgs const &,JS::MutableHandle<JS::Value>) [js/src/vm/Interpreter.cpp:550] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #39: js::ForwardingProxyHandler::call(JSContext *,JS::Handle<JSObject *>,JS::CallArgs const &) [js/src/proxy/Wrapper.cpp:175] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #40: js::CrossCompartmentWrapper::call(JSContext *,JS::Handle<JSObject *>,JS::CallArgs const &) [js/src/proxy/CrossCompartmentWrapper.cpp:359] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #41: js::Proxy::call(JSContext *,JS::Handle<JSObject *>,JS::CallArgs const &) [js/src/proxy/Proxy.cpp:512] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #42: js::proxy_Call(JSContext *,unsigned int,JS::Value *) [js/src/proxy/Proxy.cpp:787] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #43: js::CallJSNative(JSContext *,bool (*)(JSContext *,unsigned int,JS::Value *),JS::CallArgs const &) [js/src/jscntxtinlines.h:291] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #44: js::InternalCallOrConstruct(JSContext *,JS::CallArgs const &,js::MaybeConstruct) [js/src/vm/Interpreter.cpp:464] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #45: InternalCall [js/src/vm/Interpreter.cpp:531] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #46: Interpret [js/src/vm/Interpreter.cpp:3076] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #47: js::RunScript(JSContext *,js::RunState &) [js/src/vm/Interpreter.cpp:432] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #48: js::InternalCallOrConstruct(JSContext *,JS::CallArgs const &,js::MaybeConstruct) [js/src/vm/Interpreter.cpp:504] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #49: InternalCall [js/src/vm/Interpreter.cpp:531] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #50: js::Call(JSContext *,JS::Handle<JS::Value>,JS::Handle<JS::Value>,js::AnyInvokeArgs const &,JS::MutableHandle<JS::Value>) [js/src/vm/Interpreter.cpp:550] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #51: JS::Call(JSContext *,JS::Handle<JS::Value>,JS::Handle<JS::Value>,JS::HandleValueArray const &,JS::MutableHandle<JS::Value>) [js/src/jsapi.cpp:3021] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #52: mozilla::dom::EventHandlerNonNull::Call(JSContext *,JS::Handle<JS::Value>,mozilla::dom::Event &,JS::MutableHandle<JS::Value>,mozilla::ErrorResult &) [s3:gecko-generated-sources:8f2503e2a83a57ff67424bb2177bac17c2b07748c3acb3d2fac390df70e68c519ac141cf000a4148cae8b3ef7faa4c6cde18b6b81d422adb7d2f27a13de7a49c/dom/bindings/EventHandlerBinding.cpp::260] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #53: mozilla::dom::EventHandlerNonNull::Call<nsISupports *>(nsISupports * const &,mozilla::dom::Event &,JS::MutableHandle<JS::Value>,mozilla::ErrorResult &,char const *,mozilla::dom::CallbackObject::ExceptionHandling,JSCompartment *) [s3:gecko-generated-sources:c4fc45fd92579da9bf575e45c43cfa1acedef7bc1a869011df870211d66123c95c9bf5b8404577e68c1f52ad0aad4be07158002e35b350409da31660e5fba70e/dist/include/mozilla/dom/EventHandlerBinding.h::362] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #54: mozilla::JSEventHandler::HandleEvent(nsIDOMEvent *) [dom/events/JSEventHandler.cpp:216] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #55: mozilla::EventListenerManager::HandleEventSubType(mozilla::EventListenerManager::Listener *,nsIDOMEvent *,mozilla::dom::EventTarget *) [dom/events/EventListenerManager.cpp:1118] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #56: mozilla::EventListenerManager::HandleEventInternal(nsPresContext *,mozilla::WidgetEvent *,nsIDOMEvent * *,mozilla::dom::EventTarget *,nsEventStatus *) [dom/events/EventListenerManager.cpp:1298] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #57: mozilla::EventListenerManager::HandleEvent(nsPresContext *,mozilla::WidgetEvent *,nsIDOMEvent * *,mozilla::dom::EventTarget *,nsEventStatus *) [dom/events/EventListenerManager.h:375] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #58: mozilla::EventTargetChainItem::HandleEvent(mozilla::EventChainPostVisitor &,mozilla::ELMCreationDetector &) [dom/events/EventDispatcher.cpp:317] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #59: mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem> &,mozilla::EventChainPostVisitor &,mozilla::EventDispatchingCallback *,mozilla::ELMCreationDetector &) [dom/events/EventDispatcher.cpp:464] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #60: mozilla::EventDispatcher::Dispatch(nsISupports *,nsPresContext *,mozilla::WidgetEvent *,nsIDOMEvent *,nsEventStatus *,mozilla::EventDispatchingCallback *,nsTArray<mozilla::dom::EventTarget *> *) [dom/events/EventDispatcher.cpp:825] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #61: nsGlobalWindow::PostHandleEvent(mozilla::EventChainPostVisitor &) [dom/base/nsGlobalWindow.cpp:4002] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #62: mozilla::EventTargetChainItem::PostHandleEvent(mozilla::EventChainPostVisitor &) [dom/events/EventDispatcher.cpp:413] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #63: mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem> &,mozilla::EventChainPostVisitor &,mozilla::EventDispatchingCallback *,mozilla::ELMCreationDetector &) [dom/events/EventDispatcher.cpp:469] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #64: mozilla::EventTargetChainItem::HandleEventTargetChain(nsTArray<mozilla::EventTargetChainItem> &,mozilla::EventChainPostVisitor &,mozilla::EventDispatchingCallback *,mozilla::ELMCreationDetector &) [dom/events/EventDispatcher.cpp:519] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #65: mozilla::EventDispatcher::Dispatch(nsISupports *,nsPresContext *,mozilla::WidgetEvent *,nsIDOMEvent *,nsEventStatus *,mozilla::EventDispatchingCallback *,nsTArray<mozilla::dom::EventTarget *> *) [dom/events/EventDispatcher.cpp:825] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #66: nsDocumentViewer::LoadComplete(nsresult) [layout/base/nsDocumentViewer.cpp:1065] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #67: nsDocShell::EndPageLoad(nsIWebProgress *,nsIChannel *,nsresult) [docshell/base/nsDocShell.cpp:7761] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #68: nsDocShell::OnStateChange(nsIWebProgress *,nsIRequest *,unsigned int,nsresult) [docshell/base/nsDocShell.cpp:7559] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #69: nsDocLoader::DoFireOnStateChange(nsIWebProgress * const,nsIRequest * const,int &,nsresult) [uriloader/base/nsDocLoader.cpp:1320] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #70: nsDocLoader::doStopDocumentLoad(nsIRequest *,nsresult) [uriloader/base/nsDocLoader.cpp:861] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #71: nsDocLoader::DocLoaderIsEmpty(bool) [uriloader/base/nsDocLoader.cpp:752] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #72: nsDocLoader::OnStopRequest(nsIRequest *,nsISupports *,nsresult) [uriloader/base/nsDocLoader.cpp:633] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #73: mozilla::net::nsLoadGroup::RemoveRequest(nsIRequest *,nsISupports *,nsresult) [netwerk/base/nsLoadGroup.cpp:629] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #74: nsDocument::DoUnblockOnload() [dom/base/nsDocument.cpp:9368] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #75: nsDocument::UnblockOnload(bool) [dom/base/nsDocument.cpp:9289] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #76: nsDocument::DispatchContentLoadedEvents() [dom/base/nsDocument.cpp:5644] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #77: mozilla::detail::RunnableMethodImpl<nsDocument * const,void ( nsDocument::*)(void),1,0>::Run() [xpcom/threads/nsThreadUtils.h:1195] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #78: mozilla::SchedulerGroup::Runnable::Run() [xpcom/threads/SchedulerGroup.cpp:396] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #79: nsThread::ProcessNextEvent(bool,bool *) [xpcom/threads/nsThread.cpp:1038] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #80: NS_ProcessNextEvent(nsIThread *,bool) [xpcom/threads/nsThreadUtils.cpp:524] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #81: mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate *) [ipc/glue/MessagePump.cpp:97] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #82: mozilla::ipc::MessagePumpForChildProcess::Run(base::MessagePump::Delegate *) [ipc/glue/MessagePump.cpp:301] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #83: MessageLoop::RunInternal() [ipc/chromium/src/base/message_loop.cc:326] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #84: MessageLoop::RunHandler() [ipc/chromium/src/base/message_loop.cc:320] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #85: MessageLoop::Run() [ipc/chromium/src/base/message_loop.cc:300] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #86: nsBaseAppShell::Run() [widget/nsBaseAppShell.cpp:160] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #87: nsAppShell::Run() [widget/windows/nsAppShell.cpp:230] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #88: XRE_RunAppShell() [toolkit/xre/nsEmbedFunctions.cpp:877] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #89: mozilla::ipc::MessagePumpForChildProcess::Run(base::MessagePump::Delegate *) [ipc/glue/MessagePump.cpp:269] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #90: MessageLoop::RunInternal() [ipc/chromium/src/base/message_loop.cc:326] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #91: MessageLoop::RunHandler() [ipc/chromium/src/base/message_loop.cc:320] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #92: MessageLoop::Run() [ipc/chromium/src/base/message_loop.cc:300] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #93: XRE_InitChildProcess(int,char * * const,XREChildData const *) [toolkit/xre/nsEmbedFunctions.cpp:707] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #94: mozilla::BootstrapImpl::XRE_InitChildProcess(int,char * * const,XREChildData const *) [toolkit/xre/Bootstrap.cpp:69] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #95: content_process_main(mozilla::Bootstrap *,int,char * * const) [ipc/contentproc/plugin-container.cpp:63] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #96: NS_internal_main(int,char * *,char * *) [browser/app/nsBrowserApp.cpp:280] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #97: wmain [toolkit/xre/nsWindowsWMain.cpp:114] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #98: __scrt_common_main_seh [f:/dd/vctools/crt/vcstartup/src/startup/exe_common.inl:253] 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #99: kernel32.dll + 0x53c45 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #100: ntdll.dll + 0x637f5 14:35:51 INFO - 14:35:51 INFO - GECKO(4556) | #101: ntdll.dll + 0x637c8
Priority: -- → P3
No longer depends on: 1414710
Let's make them use Editor(Raw)DOMPoint.
Assignee: ehsan → masayuki
Status: NEW → ASSIGNED
OS: Unspecified → All
Hardware: Unspecified → All
Version: unspecified → Trunk
Attachment #8918141 - Attachment is obsolete: true
Attachment #8918142 - Attachment is obsolete: true
Attachment #8918143 - Attachment is obsolete: true
Comment on attachment 8935279 [details] Bug 1408125 - part 4: Redesign HTMLEditor::InsertNodeAtPoint() with EditorRawDOMPoint https://reviewboard.mozilla.org/r/203874/#review211752 C/C++ static analysis found 1 defect in this patch. You can run this analysis locally with: `./mach static-analysis check path/to/file.cpp` ::: editor/libeditor/HTMLEditorDataTransfer.cpp:587 (Diff revision 1) > + insertedPoint = > + InsertNodeIntoProperAncestor( > + *content->GetParent(), pointToInsert.AsRaw(), > + SplitAtEdges::eDoNotCreateEmptyContainer); > + if (insertedPoint.IsSet()) { > + bDidInsert = true; Warning: Value stored to 'bdidinsert' is never read [clang-tidy: clang-analyzer-deadcode.DeadStores]
Comment on attachment 8935276 [details] Bug 1408125 - part 1: Make InsertNodeTransaction use EditorRawDOMPoint and RangeBoundary instead of pair of container node and offset in it https://reviewboard.mozilla.org/r/203868/#review212624
Attachment #8935276 - Flags: review?(m_kato) → review+
Comment on attachment 8935277 [details] Bug 1408125 - part 2: EditorBase::CreateTxnForInsertNode() and EditorBase::InsertNode() should take |const EditorRawDOMPoint&| as an argument specifying point to insert https://reviewboard.mozilla.org/r/203870/#review212628
Attachment #8935277 - Flags: review?(m_kato) → review+
Comment on attachment 8935277 [details] Bug 1408125 - part 2: EditorBase::CreateTxnForInsertNode() and EditorBase::InsertNode() should take |const EditorRawDOMPoint&| as an argument specifying point to insert https://reviewboard.mozilla.org/r/203870/#review212630 ::: editor/libeditor/EditorBase.cpp:1717 (Diff revision 2) > - nsCOMPtr<nsIContent> parent = aOldContainer->GetParent(); > - NS_ENSURE_TRUE(parent, nullptr); > - > - int32_t offset = parent->IndexOf(aOldContainer); > + EditorDOMPoint atOldContainer(aOldContainer); > + if (NS_WARN_IF(!atOldContainer.IsSet())) { > + return nullptr; > + } > > - // create new container > + nsCOMPtr<Element> newContainer = CreateHTMLContent(aNodeType); RefPtr<Element> ... ::: editor/libeditor/EditorBase.cpp:1842 (Diff revision 2) > + DebugOnly<bool> advanced = pointToInsertNewContainer.AdvanceOffset(); > + NS_WARNING_ASSERTION(advanced, > + "Failed to advance offset to after aNode"); > > // Create new container > - nsCOMPtr<Element> newContent = CreateHTMLContent(aNodeType); > + nsCOMPtr<Element> newContainer = CreateHTMLContent(aNodeType); RefPtr<Element> ...
Comment on attachment 8935278 [details] Bug 1408125 - part 3: Redesign nsIEditActionListener::(Will|Did)InsertNode() https://reviewboard.mozilla.org/r/203872/#review212634
Attachment #8935278 - Flags: review?(m_kato) → review+
Comment on attachment 8935279 [details] Bug 1408125 - part 4: Redesign HTMLEditor::InsertNodeAtPoint() with EditorRawDOMPoint https://reviewboard.mozilla.org/r/203874/#review212636 ::: editor/libeditor/HTMLEditorDataTransfer.cpp:677 (Diff revision 2) > } > selection->Collapse(selNode, selOffset); > > // if we just pasted a link, discontinue link style > nsCOMPtr<nsIDOMNode> link; > - if (!bStartedInLink && IsInLink(selNode, address_of(link))) { > + if (!bStartedInLink && IsInLink(selNode->AsDOMNode(), address_of(link))) { If selNode is nullable, we shuld use GetAsDOMNode(selNode) instead. ::: editor/libeditor/HTMLEditorDataTransfer.cpp:684 (Diff revision 2) > // nudging selection point beyond it? Because it might have ended in a BR > // that is not visible. If so, the code above just placed selection > // inside that. So I split it instead. > nsCOMPtr<nsIContent> linkContent = do_QueryInterface(link); > NS_ENSURE_STATE(linkContent || !link); > - nsCOMPtr<nsIContent> selContent = do_QueryInterface(selNode); > + if (NS_WARN_IF(selNode && !selNode->IsContent())) { If selNode is null, IsInLink always return false. So I think nullptr check for selNode is unnecessary. ::: editor/libeditor/HTMLEditorDataTransfer.cpp:688 (Diff revision 2) > NS_ENSURE_STATE(linkContent || !link); > - nsCOMPtr<nsIContent> selContent = do_QueryInterface(selNode); > - NS_ENSURE_STATE(selContent || !selNode); > + if (NS_WARN_IF(selNode && !selNode->IsContent())) { > + return NS_ERROR_FAILURE; > + } > + nsCOMPtr<nsIContent> selContent = > + selNode ? selNode->AsContent() : nullptr; same
Attachment #8935279 - Flags: review?(m_kato) → review+
Comment on attachment 8935280 [details] Bug 1408125 - part 5: Redesign HTMLEditor::NormalizeEOLInsertPosition() with EditorRawDOMPoint https://reviewboard.mozilla.org/r/205396/#review212640
Attachment #8935280 - Flags: review?(m_kato) → review+
Comment on attachment 8935279 [details] Bug 1408125 - part 4: Redesign HTMLEditor::InsertNodeAtPoint() with EditorRawDOMPoint https://reviewboard.mozilla.org/r/203874/#review212636 > If selNode is null, IsInLink always return false. So I think nullptr check for selNode is unnecessary. Indeed. And also it's IsContent() is always true in this case.
Pushed by masayuki@d-toybox.com: https://hg.mozilla.org/integration/autoland/rev/86e780efd838 part 1: Make InsertNodeTransaction use EditorRawDOMPoint and RangeBoundary instead of pair of container node and offset in it r=m_kato https://hg.mozilla.org/integration/autoland/rev/7a72eb262642 part 2: EditorBase::CreateTxnForInsertNode() and EditorBase::InsertNode() should take |const EditorRawDOMPoint&| as an argument specifying point to insert r=m_kato https://hg.mozilla.org/integration/autoland/rev/019dac777e99 part 3: Redesign nsIEditActionListener::(Will|Did)InsertNode() r=m_kato https://hg.mozilla.org/integration/autoland/rev/a2d28cf0e5ac part 4: Redesign HTMLEditor::InsertNodeAtPoint() with EditorRawDOMPoint r=m_kato https://hg.mozilla.org/integration/autoland/rev/3b2fc3875b51 part 5: Redesign HTMLEditor::NormalizeEOLInsertPosition() with EditorRawDOMPoint r=m_kato
Depends on: 1424839
No longer depends on: 1424839
Regressions: 1625755
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: