icecat: add release icecat-140.8.0-2 for aramo

This commit is contained in:
Ark74 2026-03-11 06:58:43 -06:00
parent d9a6c0aa96
commit d570f39e11
616 changed files with 39955 additions and 33937 deletions

View file

@ -2878,13 +2878,26 @@ void EditorBase::DispatchInputEvent() {
return;
}
RefPtr<DataTransfer> dataTransfer = GetInputEventDataTransfer();
const EditAction editAction = GetEditAction();
if (editAction == EditAction::eCancelComposition ||
editAction == EditAction::eCommitComposition) {
MOZ_ASSERT(!mComposition);
if (MOZ_UNLIKELY(!CanDispatchInputEventAfterCompositionEnd())) {
MOZ_LOG(gEventLog, LogLevel::Info,
("%p %s: Blocked to dispatch \"input\" event immediately after "
"eCompositionEnd",
this, mIsHTMLEditorClass ? "HTMLEditor" : "TextEditor"));
return;
}
}
const EditorInputType inputType = ToInputType(editAction);
mEditActionData->WillDispatchInputEvent();
MOZ_LOG(gEventLog, LogLevel::Info,
("%p %s: Dispatching \"input\" event: { inputType=\"%s\" }...", this,
mIsHTMLEditorClass ? "HTMLEditor" : "TextEditor",
ToString(ToInputType(GetEditAction())).c_str()));
ToString(inputType).c_str()));
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(
targetElement, eEditorInput, ToInputType(GetEditAction()), this,
targetElement, eEditorInput, inputType, this,
dataTransfer ? InputEventOptions(dataTransfer,
InputEventOptions::NeverCancelable::No)
: InputEventOptions(GetInputEventData(),
@ -2892,7 +2905,7 @@ void EditorBase::DispatchInputEvent() {
MOZ_LOG(gEventLog, LogLevel::Debug,
("%p %s: Dispatched \"input\" event: { inputType=\"%s\" }", this,
mIsHTMLEditorClass ? "HTMLEditor" : "TextEditor",
ToString(ToInputType(GetEditAction())).c_str()));
ToString(inputType).c_str()));
mEditActionData->DidDispatchInputEvent();
NS_WARNING_ASSERTION(
NS_SUCCEEDED(rvIgnored),
@ -4215,8 +4228,10 @@ nsresult EditorBase::OnCompositionChange(
// NOTE: When the pref is enabled, the last `input` event which will be fired
// after `compositionend` won't be paired with corresponding `beforeinput`
// event.
else if (StaticPrefs::dom_input_events_dispatch_before_compositionend() &&
mDispatchInputEvent && !IsEditActionAborted()) {
else if (MOZ_LIKELY(
StaticPrefs::dom_input_events_dispatch_before_compositionend() &&
mDispatchInputEvent && !IsEditActionAborted() &&
CanDispatchInputEventBeforeCompositionEnd())) {
DispatchInputEvent();
}
@ -4297,6 +4312,56 @@ void EditorBase::OnCompositionEnd(
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
}
bool EditorBase::CanDispatchInputEventBeforeCompositionEnd() const {
Document* const doc = GetDocument();
if (NS_WARN_IF(!doc)) {
return false;
}
nsIPrincipal* const principal = doc->GetPrincipalForPrefBasedHacks();
if (!principal) {
return true;
}
constexpr static auto* kTextEditorPref =
"editor.texteditor.inputevent.hack.no_dispatch_before_compositionend";
constexpr static auto* kTextEditorAddlPref =
"editor.texteditor.inputevent.hack.no_dispatch_before_compositionend."
"addl";
constexpr static auto* kHTMLEditorPref =
"editor.htmleditor.inputevent.hack.no_dispatch_before_compositionend";
constexpr static auto* kHTMLEditorAddlPref =
"editor.htmleditor.inputevent.hack.no_dispatch_before_compositionend."
"addl";
return !principal->IsURIInPrefList(IsTextEditor() ? kTextEditorPref
: kHTMLEditorPref) &&
!principal->IsURIInPrefList(IsTextEditor() ? kTextEditorAddlPref
: kHTMLEditorAddlPref);
}
bool EditorBase::CanDispatchInputEventAfterCompositionEnd() const {
Document* const doc = GetDocument();
if (NS_WARN_IF(!doc)) {
return false;
}
nsIPrincipal* const principal = doc->GetPrincipalForPrefBasedHacks();
if (!principal) {
return true;
}
constexpr static auto* kTextEditorPref =
"editor.texteditor.inputevent.hack.no_dispatch_after_compositionend";
constexpr static auto* kTextEditorAddlPref =
"editor.texteditor.inputevent.hack.no_dispatch_after_compositionend."
"addl";
constexpr static auto* kHTMLEditorPref =
"editor.htmleditor.inputevent.hack.no_dispatch_after_compositionend";
constexpr static auto* kHTMLEditorAddlPref =
"editor.htmleditor.inputevent.hack.no_dispatch_after_compositionend."
"addl";
return !principal->IsURIInPrefList(IsTextEditor() ? kTextEditorPref
: kHTMLEditorPref) &&
!principal->IsURIInPrefList(IsTextEditor() ? kTextEditorAddlPref
: kHTMLEditorAddlPref);
}
bool EditorBase::WillHandleMouseButtonEvent(WidgetMouseEvent& aMouseEvent) {
MOZ_ASSERT(aMouseEvent.mMessage == eMouseDown ||
aMouseEvent.mMessage == eMouseUp);

View file

@ -2514,6 +2514,18 @@ class EditorBase : public nsIEditor,
*/
MOZ_CAN_RUN_SCRIPT void DispatchInputEvent();
/**
* Return true if it's NOT blocked by the pref to dispatch `input` event
* immediately before `compositionend`.
*/
[[nodiscard]] bool CanDispatchInputEventBeforeCompositionEnd() const;
/**
* Return true if it's NOT blocked by the pref to dispatch `input` event
* immediately after `compositionend`.
*/
[[nodiscard]] bool CanDispatchInputEventAfterCompositionEnd() const;
/**
* Called after a transaction is done successfully.
*/

View file

@ -622,6 +622,8 @@ support-files = ["file_sanitizer_on_paste.sjs"]
["test_select_all_without_body.html"]
support-files = ["file_select_all_without_body.html"]
["test_selectable_input_event_dispatching_for_compositionend.html"]
["test_selection_move_commands.html"]
support-files = ["!/gfx/layers/apz/test/mochitest/apz_test_utils.js"]

View file

@ -0,0 +1,108 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Test for block list of dispatching `input` event around `compositionend`</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
<script>
"use strict";
SimpleTest.waitForExplicitFinish();
SimpleTest.waitForFocus(async () => {
for (const pref of [
"editor.texteditor.inputevent.hack.no_dispatch_before_compositionend",
"editor.htmleditor.inputevent.hack.no_dispatch_before_compositionend",
"editor.texteditor.inputevent.hack.no_dispatch_before_compositionend.addl",
"editor.htmleditor.inputevent.hack.no_dispatch_before_compositionend.addl",
"editor.texteditor.inputevent.hack.no_dispatch_after_compositionend",
"editor.htmleditor.inputevent.hack.no_dispatch_after_compositionend",
"editor.texteditor.inputevent.hack.no_dispatch_after_compositionend.addl",
"editor.htmleditor.inputevent.hack.no_dispatch_after_compositionend.addl",
]) {
for (const selector of ["input", "textarea", "div[contenteditable]"]) {
const element = document.querySelector(selector);
const isTextEditor = !selector.includes("[contenteditable]");
if (isTextEditor) {
element.value = "";
} else {
element.innerHTML = "<br>";
}
element.focus();
synthesizeCompositionChange({
composition: {
string: "abc",
clauses: [
{ length: 3, attr: COMPOSITION_ATTR_RAW_CLAUSE },
]
},
caret: {
start: 3,
length: 0,
}
});
const events = [];
function recordEvent(aEvent) {
events.push(aEvent);
}
element.addEventListener("compositionend", recordEvent);
element.addEventListener("input", recordEvent);
await SpecialPowers.pushPrefEnv({
set: [[pref, document.domain]],
});
synthesizeComposition({type: "compositioncommitasis"});
await SpecialPowers.clearUserPref(pref);
element.removeEventListener("compositionend", recordEvent);
element.removeEventListener("input", recordEvent);
const expectInputBeforeCompositionEnd =
!pref.startsWith(
`editor.${isTextEditor ? "texteditor" : "htmleditor"}.inputevent.hack.no_dispatch_before_compositionend`
);
const expectInputAfterCompositionEnd =
!pref.startsWith(
`editor.${isTextEditor ? "texteditor" : "htmleditor"}.inputevent.hack.no_dispatch_after_compositionend`
);
const expectedEvents = [];
if (expectInputBeforeCompositionEnd) {
expectedEvents.push({type: "input", inputType: "insertCompositionText", isComposing: true});
}
expectedEvents.push({type: "compositionend"});
if (expectInputAfterCompositionEnd) {
expectedEvents.push({type: "input", inputType: "insertCompositionText", isComposing: false});
}
function stringifyEvents(aEvents) {
function stringifyEvent(aEvent) {
return aEvent.type == "input"
? `input(inputType=${aEvent.inputType},isComposing=${aEvent.isComposing})`
: aEvent.type;
}
let ret = "[";
for (const e of aEvents) {
if (ret != "[") {
ret += ","
}
ret += stringifyEvent(e);
}
return ret + "]";
}
is(
stringifyEvents(events),
stringifyEvents(expectedEvents),
`Events should be dispatched as expected on ${selector} when ${pref} has current domain`
);
}
}
SimpleTest.finish();
});
</script>
</head>
<body>
<input>
<textarea></textarea>
<div contenteditable><br></div>
</body>
</html>