diff --git a/editor/libeditor/HTMLEditSubActionHandler.cpp b/editor/libeditor/HTMLEditSubActionHandler.cpp index 29003f40b119..10e06d1bbbe9 100644 --- a/editor/libeditor/HTMLEditSubActionHandler.cpp +++ b/editor/libeditor/HTMLEditSubActionHandler.cpp @@ -3052,27 +3052,29 @@ EditActionResult HTMLEditor::ChangeSelectedHardLinesToList( aListElementTagName, atStartOfSelection, BRElementNextToSplitPoint::Keep, // MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868 - [&](Element& aListElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY { - Result, nsresult> listItemElementOrError = - CreateAndInsertElement(aListElement.IsInComposedDoc() - ? WithTransaction::Yes - : WithTransaction::No, - aListItemElementTagName, - EditorDOMPoint(&aListElement, 0u)); - if (listItemElementOrError.isErr()) { - NS_WARNING(nsPrintfCString( - "HTMLEditor::CreateAndInsertElement(%s) failed", - ToString(aListElement.IsInComposedDoc() - ? WithTransaction::Yes - : WithTransaction::No) - .c_str()) - .get()); - return listItemElementOrError.unwrapErr(); - } - MOZ_ASSERT(listItemElementOrError.inspect()); - newListItemElement = listItemElementOrError.unwrap(); - return NS_OK; - }); + [&newListItemElement, &aListItemElementTagName]( + HTMLEditor& aHTMLEditor, Element& aListElement, + const EditorDOMPoint& aPointToInsert) + MOZ_CAN_RUN_SCRIPT_BOUNDARY { + const auto withTransaction = aListElement.IsInComposedDoc() + ? WithTransaction::Yes + : WithTransaction::No; + Result, nsresult> listItemElementOrError = + aHTMLEditor.CreateAndInsertElement( + withTransaction, aListItemElementTagName, + EditorDOMPoint(&aListElement, 0u)); + if (listItemElementOrError.isErr()) { + NS_WARNING( + nsPrintfCString( + "HTMLEditor::CreateAndInsertElement(%s) failed", + ToString(withTransaction).c_str()) + .get()); + return listItemElementOrError.unwrapErr(); + } + MOZ_ASSERT(listItemElementOrError.inspect()); + newListItemElement = listItemElementOrError.unwrap(); + return NS_OK; + }); if (MOZ_UNLIKELY(newListElementOrError.isErr())) { NS_WARNING( nsPrintfCString( @@ -5701,12 +5703,13 @@ nsresult HTMLEditor::AlignBlockContentsWithDivElement( Result, nsresult> maybeNewDivElement = CreateAndInsertElement( WithTransaction::Yes, *nsGkAtoms::div, EditorDOMPoint(&aBlockElement, 0u), // MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868 - [&](Element& aDivElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY { - // If aDivElement has not been connected yet, we do not need transaction - // of setting align attribute here. - nsresult rv = - SetAttributeOrEquivalent(&aDivElement, nsGkAtoms::align, aAlignType, - !aDivElement.IsInComposedDoc()); + [&aAlignType](HTMLEditor& aHTMLEditor, Element& aDivElement, + const EditorDOMPoint&) MOZ_CAN_RUN_SCRIPT_BOUNDARY { + // If aDivElement has not been connected yet, we do not need + // transaction of setting align attribute here. + nsresult rv = aHTMLEditor.SetAttributeOrEquivalent( + &aDivElement, nsGkAtoms::align, aAlignType, + !aDivElement.IsInComposedDoc()); NS_WARNING_ASSERTION( NS_SUCCEEDED(rv), nsPrintfCString("EditorBase::SetAttributeOrEquivalent(nsGkAtoms:: " @@ -6949,25 +6952,24 @@ nsresult HTMLEditor::HandleInsertParagraphInHeadingElement( : MOZ_KnownLive(paraAtom), atHeader.NextPoint(), // MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868 - [&](Element& aDivOrParagraphElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY { + [](HTMLEditor& aHTMLEditor, Element& aDivOrParagraphElement, + const EditorDOMPoint&) MOZ_CAN_RUN_SCRIPT_BOUNDARY { // We don't make inserting new
element undoable // because removing the new element from the DOM tree // gets same result for the user if aDivOrParagraphElement // has not been connected yet. + const auto withTransaction = + aDivOrParagraphElement.IsInComposedDoc() + ? WithTransaction::Yes + : WithTransaction::No; Result, nsresult> brElementOrError = - InsertBRElement( - aDivOrParagraphElement.IsInComposedDoc() - ? WithTransaction::Yes - : WithTransaction::No, + aHTMLEditor.InsertBRElement( + withTransaction, EditorDOMPoint(&aDivOrParagraphElement, 0u)); if (brElementOrError.isErr()) { NS_WARNING( - nsPrintfCString( - "HTMLEditor::InsertBRElement(%s) failed", - ToString(aDivOrParagraphElement.IsInComposedDoc() - ? WithTransaction::Yes - : WithTransaction::No) - .c_str()) + nsPrintfCString("HTMLEditor::InsertBRElement(%s) failed", + ToString(withTransaction).c_str()) .get()); return brElementOrError.unwrapErr(); } @@ -7396,23 +7398,25 @@ nsresult HTMLEditor::HandleInsertParagraphInListItemElement( : MOZ_KnownLive(paraAtom), atNextSiblingOfLeftList, // MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868 - [&](Element& aDivOrParagraphElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY { + [](HTMLEditor& aHTMLEditor, Element& aDivOrParagraphElement, + const EditorDOMPoint&) MOZ_CAN_RUN_SCRIPT_BOUNDARY { // We don't make inserting new
element undoable because - // removing the new element from the DOM tree gets same result for - // the user if aDivOrParagraphElement has not been connected yet. + // removing the new element from the DOM tree gets same result + // for the user if aDivOrParagraphElement has not been + // connected yet. + const auto withTransaction = + aDivOrParagraphElement.IsInComposedDoc() + ? WithTransaction::Yes + : WithTransaction::No; Result, nsresult> brElementOrError = - InsertBRElement(aDivOrParagraphElement.IsInComposedDoc() - ? WithTransaction::Yes - : WithTransaction::No, - EditorDOMPoint(&aDivOrParagraphElement, 0u)); + aHTMLEditor.InsertBRElement( + withTransaction, + EditorDOMPoint(&aDivOrParagraphElement, 0u)); if (brElementOrError.isErr()) { - NS_WARNING(nsPrintfCString( - "HTMLEditor::InsertBRElement(%s) failed", - ToString(aDivOrParagraphElement.IsInComposedDoc() - ? WithTransaction::Yes - : WithTransaction::No) - .c_str()) - .get()); + NS_WARNING( + nsPrintfCString("HTMLEditor::InsertBRElement(%s) failed", + ToString(withTransaction).c_str()) + .get()); return brElementOrError.unwrapErr(); } return NS_OK; @@ -8072,7 +8076,7 @@ Result, nsresult> HTMLEditor::InsertElementWithSplittingAncestorsWithTransaction( nsAtom& aTagName, const EditorDOMPoint& aPointToInsert, BRElementNextToSplitPoint aBRElementNextToSplitPoint, - const std::function& aInitializer) { + const InitializeInsertingElement& aInitializer) { MOZ_ASSERT(aPointToInsert.IsSetAndValid()); SplitNodeResult splitNodeResult = diff --git a/editor/libeditor/HTMLEditor.cpp b/editor/libeditor/HTMLEditor.cpp index 93650e1eb456..217245f1703e 100644 --- a/editor/libeditor/HTMLEditor.cpp +++ b/editor/libeditor/HTMLEditor.cpp @@ -472,7 +472,9 @@ NS_IMETHODIMP HTMLEditor::SetDocumentCharacterSet( Result, nsresult> maybeNewMetaElement = CreateAndInsertElement( WithTransaction::Yes, *nsGkAtoms::meta, - EditorDOMPoint(primaryHeadElement, 0), [&](Element& aMetaElement) { + EditorDOMPoint(primaryHeadElement, 0), + [&aCharacterSet](HTMLEditor&, Element& aMetaElement, + const EditorDOMPoint&) { DebugOnly rvIgnored = aMetaElement.SetAttr( kNameSpaceID_None, nsGkAtoms::httpEquiv, u"Content-Type"_ns, aMetaElement.IsInComposedDoc()); @@ -2957,7 +2959,7 @@ already_AddRefed HTMLEditor::GetSelectedElement(const nsAtom* aTagName, Result, nsresult> HTMLEditor::CreateAndInsertElement( WithTransaction aWithTransaction, nsAtom& aTagName, const EditorDOMPoint& aPointToInsert, - const std::function& aInitializer) { + const InitializeInsertingElement& aInitializer) { MOZ_ASSERT(IsEditActionDataAvailable()); MOZ_ASSERT(aPointToInsert.IsSetAndValid()); @@ -2997,7 +2999,7 @@ Result, nsresult> HTMLEditor::CreateAndInsertElement( NS_SUCCEEDED(rv), "EditorBase::MarkElementDirty() failed, but ignored"); if (StaticPrefs::editor_initialize_element_before_connect()) { - rv = aInitializer(*newElement); + rv = aInitializer(*this, *newElement, aPointToInsert); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "aInitializer failed"); if (MOZ_UNLIKELY(rv != NS_ERROR_EDITOR_DESTROYED && NS_WARN_IF(Destroyed()))) { @@ -3057,7 +3059,7 @@ Result, nsresult> HTMLEditor::CreateAndInsertElement( } if (!StaticPrefs::editor_initialize_element_before_connect() && newElement) { - rv = aInitializer(*newElement); + rv = aInitializer(*this, *newElement, aPointToInsert); NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "aInitializer failed"); if (MOZ_UNLIKELY(rv != NS_ERROR_EDITOR_DESTROYED && NS_WARN_IF(Destroyed()))) { @@ -5074,7 +5076,7 @@ nsresult HTMLEditor::MoveNodeWithTransaction( } Result, nsresult> HTMLEditor::DeleteSelectionAndCreateElement( - nsAtom& aTag, const std::function& aInitializer) { + nsAtom& aTag, const InitializeInsertingElement& aInitializer) { MOZ_ASSERT(IsEditActionDataAvailable()); nsresult rv = DeleteSelectionAndPrepareToCreateNode(); @@ -5777,14 +5779,16 @@ nsresult HTMLEditor::CopyLastEditableChildStylesWithTransaction( WithTransaction::Yes, MOZ_KnownLive(*tagName), EditorDOMPoint(newBlock, 0u), // MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868 - [&](Element& aNewElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY { + [&elementInPreviousBlock]( + HTMLEditor& aHTMLEditor, Element& aNewElement, + const EditorDOMPoint&) MOZ_CAN_RUN_SCRIPT_BOUNDARY { // Clone all attributes. Note that despite the method name, // CloneAttributesWithTransaction does not create // transactions in this case because aNewElement has not // been connected yet. // XXX Looks like that this clones id attribute too. - CloneAttributesWithTransaction(aNewElement, - *elementInPreviousBlock); + aHTMLEditor.CloneAttributesWithTransaction( + aNewElement, *elementInPreviousBlock); return NS_OK; }); if (maybeNewElement.isErr()) { diff --git a/editor/libeditor/HTMLEditor.h b/editor/libeditor/HTMLEditor.h index 080f9c42f256..2a7b2c887434 100644 --- a/editor/libeditor/HTMLEditor.h +++ b/editor/libeditor/HTMLEditor.h @@ -1479,6 +1479,22 @@ class HTMLEditor final : public EditorBase, [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult MaybeExtendSelectionToHardLineEdgesForBlockEditAction(); + /** + * InitializeInsertingElement is a callback type of methods which inserts + * an element into the DOM tree. This is called immediately before or + * after inserting aNewElement into the DOM tree (depending on + * "editor.initialize_element_before_connect" pref whether this is called + * before or after inserting the element). + * + * @param aHTMLEditor The HTML editor which modifies the DOM tree. + * @param aNewElement The new element which will be or was inserted into + * the DOM tree. + * @param aPointToInsert The position aNewElement will be or was inserted. + */ + using InitializeInsertingElement = + std::function; + /** * Create an element node whose name is aTag at before aPointToInsert. When * this succeed to create an element node, this inserts the element to @@ -1508,9 +1524,8 @@ class HTMLEditor final : public EditorBase, CreateAndInsertElement( WithTransaction aWithTransaction, nsAtom& aTagName, const EditorDOMPoint& aPointToInsert, - const std::function& aInitializer = [](Element&) { - return NS_OK; - }); + const InitializeInsertingElement& aInitializer = + [](HTMLEditor&, Element&, const EditorDOMPoint&) { return NS_OK; }); /** * MaybeSplitAncestorsForInsertWithTransaction() does nothing if container of @@ -1558,9 +1573,8 @@ class HTMLEditor final : public EditorBase, InsertElementWithSplittingAncestorsWithTransaction( nsAtom& aTagName, const EditorDOMPoint& aPointToInsert, BRElementNextToSplitPoint aBRElementNextToSplitPoint, - const std::function& aInitializer = [](Element&) { - return NS_OK; - }); + const InitializeInsertingElement& aInitializer = + [](HTMLEditor&, Element&, const EditorDOMPoint&) { return NS_OK; }); /** * SplitRangeOffFromBlock() splits aBlockElement at two points, before @@ -3440,8 +3454,9 @@ class HTMLEditor final : public EditorBase, */ MOZ_CAN_RUN_SCRIPT Result, nsresult> DeleteSelectionAndCreateElement( - nsAtom& aTag, const std::function& aInitializer = - [](Element&) { return NS_OK; }); + nsAtom& aTag, + const InitializeInsertingElement& aInitializer = + [](HTMLEditor&, Element&, const EditorDOMPoint&) { return NS_OK; }); /** * This method first deletes the selection, if it's not collapsed. Then if diff --git a/editor/libeditor/HTMLEditorDataTransfer.cpp b/editor/libeditor/HTMLEditorDataTransfer.cpp index d909e48dcff8..4b34d60ff7f7 100644 --- a/editor/libeditor/HTMLEditorDataTransfer.cpp +++ b/editor/libeditor/HTMLEditorDataTransfer.cpp @@ -2484,19 +2484,20 @@ nsresult HTMLEditor::PasteAsQuotationAsAction(int32_t aClipboardType, DeleteSelectionAndCreateElement( *nsGkAtoms::blockquote, // MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868 - [&](Element& aBlockquoteElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY { - DebugOnly rvIgnored = aBlockquoteElement.SetAttr( - kNameSpaceID_None, nsGkAtoms::type, u"cite"_ns, - aBlockquoteElement.IsInComposedDoc()); - NS_WARNING_ASSERTION( - NS_SUCCEEDED(rvIgnored), - nsPrintfCString( - "Element::SetAttr(nsGkAtoms::type, \"cite\", %s) " - "failed, but ignored", - aBlockquoteElement.IsInComposedDoc() ? "true" : "false") - .get()); - return NS_OK; - }); + [](HTMLEditor&, Element& aBlockquoteElement, const EditorDOMPoint&) + MOZ_CAN_RUN_SCRIPT_BOUNDARY { + DebugOnly rvIgnored = aBlockquoteElement.SetAttr( + kNameSpaceID_None, nsGkAtoms::type, u"cite"_ns, + aBlockquoteElement.IsInComposedDoc()); + NS_WARNING_ASSERTION( + NS_SUCCEEDED(rvIgnored), + nsPrintfCString( + "Element::SetAttr(nsGkAtoms::type, \"cite\", %s) " + "failed, but ignored", + aBlockquoteElement.IsInComposedDoc() ? "true" : "false") + .get()); + return NS_OK; + }); if (MOZ_UNLIKELY(blockquoteElementOrError.isErr() || NS_WARN_IF(Destroyed()))) { NS_WARNING( @@ -2895,7 +2896,8 @@ nsresult HTMLEditor::InsertAsPlaintextQuotation(const nsAString& aQuotedText, // container element, the width-restricted body. Result, nsresult> spanElementOrError = DeleteSelectionAndCreateElement( - *nsGkAtoms::span, [](Element& aSpanElement) { + *nsGkAtoms::span, + [](HTMLEditor&, Element& aSpanElement, const EditorDOMPoint&) { // Add an attribute on the pre node so we'll know it's a quotation. DebugOnly rvIgnored = aSpanElement.SetAttr( kNameSpaceID_None, nsGkAtoms::mozquote, u"true"_ns, @@ -2908,6 +2910,8 @@ nsresult HTMLEditor::InsertAsPlaintextQuotation(const nsAString& aQuotedText, aSpanElement.IsInComposedDoc() ? "true" : "false") .get()); // Allow wrapping on spans so long lines get wrapped to the screen. + // TODO: Refer the insertion point because aSpanElement may not have + // been inserted into the parent element yet. if (aSpanElement.GetParent() && aSpanElement.GetParent()->IsHTMLElement(nsGkAtoms::body)) { DebugOnly rvIgnored = aSpanElement.SetAttr( @@ -3159,7 +3163,8 @@ nsresult HTMLEditor::InsertAsCitedQuotationInternal( DeleteSelectionAndCreateElement( *nsGkAtoms::blockquote, // MOZ_CAN_RUN_SCRIPT_BOUNDARY due to bug 1758868 - [&](Element& aBlockquoteElement) MOZ_CAN_RUN_SCRIPT_BOUNDARY { + [&aCitation](HTMLEditor&, Element& aBlockquoteElement, + const EditorDOMPoint&) MOZ_CAN_RUN_SCRIPT_BOUNDARY { // Try to set type=cite. Ignore it if this fails. DebugOnly rvIgnored = aBlockquoteElement.SetAttr( kNameSpaceID_None, nsGkAtoms::type, u"cite"_ns,