зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1504911 - part 1: Make all "input" event dispatcher in C++ use new utility method r=smaug
Currently, a lot of code dispatch "input" event and some of them dispatch "input" event with wrong interface and/or values. Therefore this patch creates nsContentUtils::DispatchInputEvent() to make all of them dispatch correct event. Unfortunately, due to bug 1506439, we cannot set pointer to refcountable classes of MOZ_CAN_RUN_SCRIPT method to nullptr. Therefore, this patch creates temporary RefPtr<TextEditor> a lot even though it makes damage to the performance if it's in a hot path. This patch makes eEditorInput event dispatched with InternalEditorInputEvent when "input" event should be dispatched with dom::InputEvent. However, this patch uses WidgetEvent whose message is eUnidentifiedEvent and setting WidgetEvent::mSpecifiedEventType to nsGkAtoms::oninput when "input" event should be dispatched with dom::Event because we need to keep that eEditorInput and InternalEditorInputEvent are mapped each other. Differential Revision: https://phabricator.services.mozilla.com/D12244 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
388e64d857
Коммит
abe138f771
|
@ -115,16 +115,14 @@ function triggerAutofillAndCheckProfile(profile) {
|
||||||
const checkFieldAutofilled = Promise.all([
|
const checkFieldAutofilled = Promise.all([
|
||||||
new Promise(resolve => element.addEventListener("input", (event) => {
|
new Promise(resolve => element.addEventListener("input", (event) => {
|
||||||
if (element.tagName == "INPUT" && element.type == "text") {
|
if (element.tagName == "INPUT" && element.type == "text") {
|
||||||
todo(event instanceof InputEvent,
|
ok(event instanceof InputEvent,
|
||||||
`"input" event should be dispatched with InputEvent interface on ${element.tagName}`);
|
`"input" event should be dispatched with InputEvent interface on ${element.tagName}`);
|
||||||
todo_is(event.cancelable, false,
|
|
||||||
`"input" event should be never cancelable on ${element.tagName}`);
|
|
||||||
} else {
|
} else {
|
||||||
todo(event instanceof Event && !(event instanceof UIEvent),
|
todo(event instanceof Event && !(event instanceof UIEvent),
|
||||||
`"input" event should be dispatched with Event interface on ${element.tagName}`);
|
`"input" event should be dispatched with Event interface on ${element.tagName}`);
|
||||||
is(event.cancelable, false,
|
|
||||||
`"input" event should be never cancelable on ${element.tagName}`);
|
|
||||||
}
|
}
|
||||||
|
is(event.cancelable, false,
|
||||||
|
`"input" event should be never cancelable on ${element.tagName}`);
|
||||||
is(event.bubbles, true,
|
is(event.bubbles, true,
|
||||||
`"input" event should always bubble on ${element.tagName}`);
|
`"input" event should always bubble on ${element.tagName}`);
|
||||||
resolve();
|
resolve();
|
||||||
|
|
|
@ -68,10 +68,10 @@ async function confirmClear(selector) {
|
||||||
info("Await for clearing input");
|
info("Await for clearing input");
|
||||||
let promise = new Promise(resolve =>
|
let promise = new Promise(resolve =>
|
||||||
document.querySelector(selector).addEventListener("input", (event) => {
|
document.querySelector(selector).addEventListener("input", (event) => {
|
||||||
todo(event instanceof InputEvent,
|
ok(event instanceof InputEvent,
|
||||||
'"input" event should be dispatched with InputEvent interface');
|
'"input" event should be dispatched with InputEvent interface');
|
||||||
todo_is(event.cancelable, false,
|
is(event.cancelable, false,
|
||||||
'"input" event should be never cancelable');
|
'"input" event should be never cancelable');
|
||||||
is(event.bubbles, true,
|
is(event.bubbles, true,
|
||||||
'"input" event should always bubble');
|
'"input" event should always bubble');
|
||||||
resolve();
|
resolve();
|
||||||
|
|
|
@ -50,16 +50,14 @@ function checkElementFilled(element, expectedvalue) {
|
||||||
element.addEventListener("input", function onInput(event) {
|
element.addEventListener("input", function onInput(event) {
|
||||||
ok(true, "Checking " + element.name + " field fires input event");
|
ok(true, "Checking " + element.name + " field fires input event");
|
||||||
if (element.tagName == "INPUT" && element.type == "text") {
|
if (element.tagName == "INPUT" && element.type == "text") {
|
||||||
todo(event instanceof InputEvent,
|
ok(event instanceof InputEvent,
|
||||||
`"input" event should be dispatched with InputEvent interface on ${element.name}`);
|
`"input" event should be dispatched with InputEvent interface on ${element.name}`);
|
||||||
todo_is(event.cancelable, false,
|
|
||||||
`"input" event should be never cancelable on ${element.name}`);
|
|
||||||
} else {
|
} else {
|
||||||
todo(event instanceof Event && !(event instanceof UIEvent),
|
todo(event instanceof Event && !(event instanceof UIEvent),
|
||||||
`"input" event should be dispatched with Event interface on ${element.name}`);
|
`"input" event should be dispatched with Event interface on ${element.name}`);
|
||||||
is(event.cancelable, false,
|
|
||||||
`"input" event should be never cancelable on ${element.name}`);
|
|
||||||
}
|
}
|
||||||
|
is(event.cancelable, false,
|
||||||
|
`"input" event should be never cancelable on ${element.name}`);
|
||||||
is(event.bubbles, true,
|
is(event.bubbles, true,
|
||||||
`"input" event should always bubble on ${element.name}`);
|
`"input" event should always bubble on ${element.name}`);
|
||||||
resolve();
|
resolve();
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
#include "mozilla/dom/HTMLInputElement.h"
|
#include "mozilla/dom/HTMLInputElement.h"
|
||||||
#include "mozilla/dom/HTMLSlotElement.h"
|
#include "mozilla/dom/HTMLSlotElement.h"
|
||||||
#include "mozilla/dom/HTMLTemplateElement.h"
|
#include "mozilla/dom/HTMLTemplateElement.h"
|
||||||
|
#include "mozilla/dom/HTMLTextAreaElement.h"
|
||||||
#include "mozilla/dom/IDTracker.h"
|
#include "mozilla/dom/IDTracker.h"
|
||||||
#include "mozilla/dom/MouseEventBinding.h"
|
#include "mozilla/dom/MouseEventBinding.h"
|
||||||
#include "mozilla/dom/KeyboardEventBinding.h"
|
#include "mozilla/dom/KeyboardEventBinding.h"
|
||||||
|
@ -85,6 +86,7 @@
|
||||||
#include "mozilla/dom/Selection.h"
|
#include "mozilla/dom/Selection.h"
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
#include "mozilla/StaticPrefs.h"
|
#include "mozilla/StaticPrefs.h"
|
||||||
|
#include "mozilla/TextEditor.h"
|
||||||
#include "mozilla/TextEvents.h"
|
#include "mozilla/TextEvents.h"
|
||||||
#include "nsArrayUtils.h"
|
#include "nsArrayUtils.h"
|
||||||
#include "nsAString.h"
|
#include "nsAString.h"
|
||||||
|
@ -4367,6 +4369,8 @@ nsContentUtils::DispatchTrustedEvent(nsIDocument* aDoc, nsISupports* aTarget,
|
||||||
Composed aComposed,
|
Composed aComposed,
|
||||||
bool* aDefaultAction)
|
bool* aDefaultAction)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(!aEventName.EqualsLiteral("input"),
|
||||||
|
"Use DispatchInputEvent() instead");
|
||||||
return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
|
return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
|
||||||
aComposed, Trusted::eYes, aDefaultAction);
|
aComposed, Trusted::eYes, aDefaultAction);
|
||||||
}
|
}
|
||||||
|
@ -4450,6 +4454,110 @@ nsContentUtils::DispatchEvent(nsIDocument* aDoc, nsISupports* aTarget,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
nsresult
|
||||||
|
nsContentUtils::DispatchInputEvent(Element* aEventTargetElement)
|
||||||
|
{
|
||||||
|
RefPtr<TextEditor> textEditor; // See bug 1506439
|
||||||
|
return DispatchInputEvent(aEventTargetElement, textEditor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
nsresult
|
||||||
|
nsContentUtils::DispatchInputEvent(Element* aEventTargetElement,
|
||||||
|
TextEditor* aTextEditor)
|
||||||
|
{
|
||||||
|
if (NS_WARN_IF(!aEventTargetElement)) {
|
||||||
|
return NS_ERROR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If this is called from editor, the instance should be set to aTextEditor.
|
||||||
|
// Otherwise, we need to look for an editor for aEventTargetElement.
|
||||||
|
// However, we don't need to do it for HTMLEditor since nobody shouldn't
|
||||||
|
// dispatch "input" event for HTMLEditor except HTMLEditor itself.
|
||||||
|
bool useInputEvent = false;
|
||||||
|
if (aTextEditor) {
|
||||||
|
useInputEvent = true;
|
||||||
|
} else if (HTMLTextAreaElement* textAreaElement=
|
||||||
|
HTMLTextAreaElement::FromNode(aEventTargetElement)) {
|
||||||
|
aTextEditor = textAreaElement->GetTextEditorWithoutCreation();
|
||||||
|
useInputEvent = true;
|
||||||
|
} else if (HTMLInputElement* inputElement =
|
||||||
|
HTMLInputElement::FromNode(aEventTargetElement)) {
|
||||||
|
if (inputElement->IsSingleLineTextControl()) {
|
||||||
|
aTextEditor = inputElement->GetTextEditorWithoutCreation();
|
||||||
|
useInputEvent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
else {
|
||||||
|
nsCOMPtr<nsITextControlElement> textControlElement =
|
||||||
|
do_QueryInterface(aEventTargetElement);
|
||||||
|
MOZ_ASSERT(!textControlElement,
|
||||||
|
"The event target may have editor, but we've not known it yet.");
|
||||||
|
}
|
||||||
|
#endif // #ifdef DEBUG
|
||||||
|
|
||||||
|
if (!useInputEvent) {
|
||||||
|
// Dispatch "input" event with Event instance.
|
||||||
|
WidgetEvent widgetEvent(true, eUnidentifiedEvent);
|
||||||
|
widgetEvent.mSpecifiedEventType = nsGkAtoms::oninput;
|
||||||
|
widgetEvent.mFlags.mCancelable = false;
|
||||||
|
// Using same time as nsContentUtils::DispatchEvent() for backward
|
||||||
|
// compatibility.
|
||||||
|
widgetEvent.mTime = PR_Now();
|
||||||
|
(new AsyncEventDispatcher(aEventTargetElement,
|
||||||
|
widgetEvent))->RunDOMEventWhenSafe();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIWidget> widget;
|
||||||
|
if (aTextEditor) {
|
||||||
|
widget = aTextEditor->GetWidget();
|
||||||
|
if (NS_WARN_IF(!widget)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nsIDocument* document = aEventTargetElement->OwnerDoc();
|
||||||
|
if (NS_WARN_IF(!document)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
// If we're running xpcshell tests, we fail to get presShell here.
|
||||||
|
// Even in such case, we need to dispatch "input" event without widget.
|
||||||
|
nsIPresShell* presShell = document->GetShell();
|
||||||
|
if (presShell) {
|
||||||
|
nsPresContext* presContext = presShell->GetPresContext();
|
||||||
|
if (NS_WARN_IF(!presContext)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
widget = presContext->GetRootWidget();
|
||||||
|
if (NS_WARN_IF(!widget)) {
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dispatch "input" event with InputEvent instance.
|
||||||
|
InternalEditorInputEvent inputEvent(true, eEditorInput, widget);
|
||||||
|
|
||||||
|
// Using same time as old event dispatcher in EditorBase for backward
|
||||||
|
// compatibility.
|
||||||
|
inputEvent.mTime = static_cast<uint64_t>(PR_Now() / 1000);
|
||||||
|
|
||||||
|
// If there is an editor, set isComposing to true when it has composition.
|
||||||
|
// Note that EditorBase::IsIMEComposing() may return false even when we
|
||||||
|
// need to set it to true.
|
||||||
|
// Otherwise, i.e., editor hasn't been created for the element yet,
|
||||||
|
// we should set isComposing to false since the element can never has
|
||||||
|
// composition without editor.
|
||||||
|
inputEvent.mIsComposing =
|
||||||
|
aTextEditor ? !!aTextEditor->GetComposition() : false;
|
||||||
|
|
||||||
|
(new AsyncEventDispatcher(aEventTargetElement,
|
||||||
|
inputEvent))->RunDOMEventWhenSafe();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
|
nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
|
||||||
nsISupports *aTarget,
|
nsISupports *aTarget,
|
||||||
|
|
|
@ -123,6 +123,7 @@ class Dispatcher;
|
||||||
class ErrorResult;
|
class ErrorResult;
|
||||||
class EventListenerManager;
|
class EventListenerManager;
|
||||||
class HTMLEditor;
|
class HTMLEditor;
|
||||||
|
class TextEditor;
|
||||||
|
|
||||||
namespace dom {
|
namespace dom {
|
||||||
class ContentFrameMessageManager;
|
class ContentFrameMessageManager;
|
||||||
|
@ -1377,9 +1378,12 @@ public:
|
||||||
static void MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent);
|
static void MaybeFireNodeRemoved(nsINode* aChild, nsINode* aParent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates and dispatches a trusted event.
|
* These methods create and dispatch a trusted event.
|
||||||
* Works only with events which can be created by calling
|
* Works only with events which can be created by calling
|
||||||
* nsIDocument::CreateEvent() with parameter "Events".
|
* nsIDocument::CreateEvent() with parameter "Events".
|
||||||
|
* Note that don't use these methods for "input" event. Use
|
||||||
|
* DispatchInputEvent() instead.
|
||||||
|
*
|
||||||
* @param aDoc The document which will be used to create the event.
|
* @param aDoc The document which will be used to create the event.
|
||||||
* @param aTarget The target of the event, should be QIable to
|
* @param aTarget The target of the event, should be QIable to
|
||||||
* EventTarget.
|
* EventTarget.
|
||||||
|
@ -1438,6 +1442,26 @@ public:
|
||||||
aDefaultAction, aOnlyChromeDispatch);
|
aDefaultAction, aOnlyChromeDispatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method dispatches "input" event with proper event class. If it's
|
||||||
|
* unsafe to dispatch, this put the event into the script runner queue.
|
||||||
|
* Input Events spec defines as:
|
||||||
|
* Input events are dispatched on elements that act as editing hosts,
|
||||||
|
* including elements with the contenteditable attribute set, textarea
|
||||||
|
* elements, and input elements that permit text input.
|
||||||
|
*
|
||||||
|
* @param aEventTarget The event target element of the "input" event.
|
||||||
|
* Must not be nullptr.
|
||||||
|
* @param aTextEditor Optional. If this is called by editor,
|
||||||
|
* editor should set this. Otherwise, leave
|
||||||
|
* nullptr.
|
||||||
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
|
static nsresult DispatchInputEvent(Element* aEventTarget);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
|
static nsresult DispatchInputEvent(Element* aEventTarget,
|
||||||
|
mozilla::TextEditor* aTextEditor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method creates and dispatches a untrusted event.
|
* This method creates and dispatches a untrusted event.
|
||||||
* Works only with events which can be created by calling
|
* Works only with events which can be created by calling
|
||||||
|
|
|
@ -251,16 +251,12 @@ public:
|
||||||
Unused << NS_WARN_IF(NS_FAILED(DispatchEvents()));
|
Unused << NS_WARN_IF(NS_FAILED(DispatchEvents()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
nsresult
|
nsresult
|
||||||
DispatchEvents()
|
DispatchEvents()
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = nsContentUtils::DispatchInputEvent(mInputElement);
|
||||||
rv = nsContentUtils::DispatchTrustedEvent(mInputElement->OwnerDoc(),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to dispatch input event");
|
||||||
static_cast<Element*>(mInputElement.get()),
|
|
||||||
NS_LITERAL_STRING("input"),
|
|
||||||
CanBubble::eYes,
|
|
||||||
Cancelable::eNo);
|
|
||||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "DispatchTrustedEvent failed");
|
|
||||||
|
|
||||||
rv = nsContentUtils::DispatchTrustedEvent(mInputElement->OwnerDoc(),
|
rv = nsContentUtils::DispatchTrustedEvent(mInputElement->OwnerDoc(),
|
||||||
static_cast<Element*>(mInputElement.get()),
|
static_cast<Element*>(mInputElement.get()),
|
||||||
|
@ -595,7 +591,9 @@ public:
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
NS_IMETHOD Update(const nsAString& aColor) override;
|
NS_IMETHOD Update(const nsAString& aColor) override;
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
NS_IMETHOD Done(const nsAString& aColor) override;
|
NS_IMETHOD Done(const nsAString& aColor) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -604,6 +602,7 @@ private:
|
||||||
* If aTrustedUpdate is true, it will consider that aColor is a new value.
|
* If aTrustedUpdate is true, it will consider that aColor is a new value.
|
||||||
* Otherwise, it will check that aColor is different from the current value.
|
* Otherwise, it will check that aColor is different from the current value.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsresult UpdateInternal(const nsAString& aColor, bool aTrustedUpdate);
|
nsresult UpdateInternal(const nsAString& aColor, bool aTrustedUpdate);
|
||||||
|
|
||||||
RefPtr<HTMLInputElement> mInput;
|
RefPtr<HTMLInputElement> mInput;
|
||||||
|
@ -634,15 +633,14 @@ nsColorPickerShownCallback::UpdateInternal(const nsAString& aColor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valueChanged) {
|
if (!valueChanged) {
|
||||||
mValueChanged = true;
|
return NS_OK;
|
||||||
return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
|
|
||||||
static_cast<Element*>(mInput.get()),
|
|
||||||
NS_LITERAL_STRING("input"),
|
|
||||||
CanBubble::eYes,
|
|
||||||
Cancelable::eNo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mValueChanged = true;
|
||||||
|
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(mInput);
|
||||||
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||||
|
"Failed to dispatch input event");
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2353,13 +2351,9 @@ HTMLInputElement::SetUserInput(const nsAString& aValue,
|
||||||
nsTextEditorState::eSetValue_MoveCursorToEndIfValueChanged);
|
nsTextEditorState::eSetValue_MoveCursorToEndIfValueChanged);
|
||||||
NS_ENSURE_SUCCESS_VOID(rv);
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
|
||||||
// FIXME: We're inconsistent about whether "input" events are cancelable or
|
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
|
||||||
// not.
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
"Failed to dispatch input event");
|
||||||
static_cast<Element*>(this),
|
|
||||||
NS_LITERAL_STRING("input"),
|
|
||||||
CanBubble::eYes,
|
|
||||||
Cancelable::eYes);
|
|
||||||
|
|
||||||
// If this element is not currently focused, it won't receive a change event for this
|
// If this element is not currently focused, it won't receive a change event for this
|
||||||
// update through the normal channels. So fire a change event immediately, instead.
|
// update through the normal channels. So fire a change event immediately, instead.
|
||||||
|
@ -2390,6 +2384,16 @@ HTMLInputElement::GetTextEditor()
|
||||||
return GetTextEditorFromState();
|
return GetTextEditorFromState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(TextEditor*)
|
||||||
|
HTMLInputElement::GetTextEditorWithoutCreation()
|
||||||
|
{
|
||||||
|
nsTextEditorState* state = GetEditorState();
|
||||||
|
if (!state) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return state->GetTextEditorWithoutCreation();
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(nsISelectionController*)
|
NS_IMETHODIMP_(nsISelectionController*)
|
||||||
HTMLInputElement::GetSelectionController()
|
HTMLInputElement::GetSelectionController()
|
||||||
{
|
{
|
||||||
|
@ -2735,7 +2739,7 @@ HTMLInputElement::SetFiles(FileList* aFiles)
|
||||||
/* static */ void
|
/* static */ void
|
||||||
HTMLInputElement::HandleNumberControlSpin(void* aData)
|
HTMLInputElement::HandleNumberControlSpin(void* aData)
|
||||||
{
|
{
|
||||||
HTMLInputElement* input = static_cast<HTMLInputElement*>(aData);
|
RefPtr<HTMLInputElement> input = static_cast<HTMLInputElement*>(aData);
|
||||||
|
|
||||||
NS_ASSERTION(input->mNumberControlSpinnerIsSpinning,
|
NS_ASSERTION(input->mNumberControlSpinnerIsSpinning,
|
||||||
"Should have called nsRepeatService::Stop()");
|
"Should have called nsRepeatService::Stop()");
|
||||||
|
@ -3750,12 +3754,9 @@ HTMLInputElement::CancelRangeThumbDrag(bool aIsForUserEvent)
|
||||||
if (frame) {
|
if (frame) {
|
||||||
frame->UpdateForValueChange();
|
frame->UpdateForValueChange();
|
||||||
}
|
}
|
||||||
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
|
||||||
new AsyncEventDispatcher(this,
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||||
NS_LITERAL_STRING("input"),
|
"Failed to dispatch input event");
|
||||||
CanBubble::eYes,
|
|
||||||
ChromeOnlyDispatch::eNo);
|
|
||||||
asyncDispatcher->RunDOMEventWhenSafe();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3778,11 +3779,9 @@ HTMLInputElement::SetValueOfRangeForUserEvent(Decimal aValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetValueAsDecimal() != oldValue) {
|
if (GetValueAsDecimal() != oldValue) {
|
||||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
|
||||||
static_cast<Element*>(this),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||||
NS_LITERAL_STRING("input"),
|
"Failed to dispatch input event");
|
||||||
CanBubble::eYes,
|
|
||||||
Cancelable::eNo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3877,11 +3876,9 @@ HTMLInputElement::StepNumberControlForUserEvent(int32_t aDirection)
|
||||||
SetValueInternal(newVal, nsTextEditorState::eSetValue_BySetUserInput |
|
SetValueInternal(newVal, nsTextEditorState::eSetValue_BySetUserInput |
|
||||||
nsTextEditorState::eSetValue_Notify);
|
nsTextEditorState::eSetValue_Notify);
|
||||||
|
|
||||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
|
||||||
static_cast<Element*>(this),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||||
NS_LITERAL_STRING("input"),
|
"Failed to dispatch input event");
|
||||||
CanBubble::eYes,
|
|
||||||
Cancelable::eNo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -4091,9 +4088,9 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Fire input event and then change event.
|
// Fire input event and then change event.
|
||||||
nsContentUtils::DispatchTrustedEvent<InternalEditorInputEvent>
|
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
|
||||||
(OwnerDoc(), static_cast<Element*>(this),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||||
eEditorInput, CanBubble::eYes, Cancelable::eNo);
|
"Failed to dispatch input event");
|
||||||
|
|
||||||
nsContentUtils::DispatchTrustedEvent<WidgetEvent>
|
nsContentUtils::DispatchTrustedEvent<WidgetEvent>
|
||||||
(OwnerDoc(), static_cast<Element*>(this),
|
(OwnerDoc(), static_cast<Element*>(this),
|
||||||
|
|
|
@ -187,12 +187,18 @@ public:
|
||||||
|
|
||||||
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||||
virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) override;
|
virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) override;
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
virtual nsresult PostHandleEvent(
|
virtual nsresult PostHandleEvent(
|
||||||
EventChainPostVisitor& aVisitor) override;
|
EventChainPostVisitor& aVisitor) override;
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
void PostHandleEventForRangeThumb(EventChainPostVisitor& aVisitor);
|
void PostHandleEventForRangeThumb(EventChainPostVisitor& aVisitor);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void StartRangeThumbDrag(WidgetGUIEvent* aEvent);
|
void StartRangeThumbDrag(WidgetGUIEvent* aEvent);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void FinishRangeThumbDrag(WidgetGUIEvent* aEvent = nullptr);
|
void FinishRangeThumbDrag(WidgetGUIEvent* aEvent = nullptr);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void CancelRangeThumbDrag(bool aIsForUserEvent = true);
|
void CancelRangeThumbDrag(bool aIsForUserEvent = true);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void SetValueOfRangeForUserEvent(Decimal aValue);
|
void SetValueOfRangeForUserEvent(Decimal aValue);
|
||||||
|
|
||||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||||
|
@ -223,6 +229,7 @@ public:
|
||||||
NS_IMETHOD_(bool) ValueChanged() const override;
|
NS_IMETHOD_(bool) ValueChanged() const override;
|
||||||
NS_IMETHOD_(void) GetTextEditorValue(nsAString& aValue, bool aIgnoreWrap) const override;
|
NS_IMETHOD_(void) GetTextEditorValue(nsAString& aValue, bool aIgnoreWrap) const override;
|
||||||
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditor() override;
|
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditor() override;
|
||||||
|
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditorWithoutCreation() override;
|
||||||
NS_IMETHOD_(nsISelectionController*) GetSelectionController() override;
|
NS_IMETHOD_(nsISelectionController*) GetSelectionController() override;
|
||||||
NS_IMETHOD_(nsFrameSelection*) GetConstFrameSelection() override;
|
NS_IMETHOD_(nsFrameSelection*) GetConstFrameSelection() override;
|
||||||
NS_IMETHOD BindToFrame(nsTextControlFrame* aFrame) override;
|
NS_IMETHOD BindToFrame(nsTextControlFrame* aFrame) override;
|
||||||
|
@ -891,12 +898,14 @@ public:
|
||||||
};
|
};
|
||||||
void StopNumberControlSpinnerSpin(SpinnerStopState aState =
|
void StopNumberControlSpinnerSpin(SpinnerStopState aState =
|
||||||
eAllowDispatchingEvents);
|
eAllowDispatchingEvents);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void StepNumberControlForUserEvent(int32_t aDirection);
|
void StepNumberControlForUserEvent(int32_t aDirection);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The callback function used by the nsRepeatService that we use to spin the
|
* The callback function used by the nsRepeatService that we use to spin the
|
||||||
* spinner for <input type=number>.
|
* spinner for <input type=number>.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
static void HandleNumberControlSpin(void* aData);
|
static void HandleNumberControlSpin(void* aData);
|
||||||
|
|
||||||
bool NumberSpinnerUpButtonIsDepressed() const
|
bool NumberSpinnerUpButtonIsDepressed() const
|
||||||
|
@ -916,6 +925,7 @@ public:
|
||||||
*/
|
*/
|
||||||
nsIEditor* GetEditor();
|
nsIEditor* GetEditor();
|
||||||
|
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
void SetUserInput(const nsAString& aInput,
|
void SetUserInput(const nsAString& aInput,
|
||||||
nsIPrincipal& aSubjectPrincipal);
|
nsIPrincipal& aSubjectPrincipal);
|
||||||
|
|
||||||
|
@ -1054,6 +1064,7 @@ protected:
|
||||||
/**
|
/**
|
||||||
* Called when an attribute has just been changed
|
* Called when an attribute has just been changed
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
||||||
const nsAttrValue* aValue,
|
const nsAttrValue* aValue,
|
||||||
const nsAttrValue* aOldValue,
|
const nsAttrValue* aOldValue,
|
||||||
|
@ -1180,6 +1191,7 @@ protected:
|
||||||
/**
|
/**
|
||||||
* Manages the internal data storage across type changes.
|
* Manages the internal data storage across type changes.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void HandleTypeChange(uint8_t aNewType, bool aNotify);
|
void HandleTypeChange(uint8_t aNewType, bool aNotify);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -224,6 +224,12 @@ HTMLTextAreaElement::GetTextEditor()
|
||||||
return mState.GetTextEditor();
|
return mState.GetTextEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(TextEditor*)
|
||||||
|
HTMLTextAreaElement::GetTextEditorWithoutCreation()
|
||||||
|
{
|
||||||
|
return mState.GetTextEditorWithoutCreation();
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(nsISelectionController*)
|
NS_IMETHODIMP_(nsISelectionController*)
|
||||||
HTMLTextAreaElement::GetSelectionController()
|
HTMLTextAreaElement::GetSelectionController()
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,6 +83,7 @@ public:
|
||||||
NS_IMETHOD_(bool) ValueChanged() const override;
|
NS_IMETHOD_(bool) ValueChanged() const override;
|
||||||
NS_IMETHOD_(void) GetTextEditorValue(nsAString& aValue, bool aIgnoreWrap) const override;
|
NS_IMETHOD_(void) GetTextEditorValue(nsAString& aValue, bool aIgnoreWrap) const override;
|
||||||
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditor() override;
|
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditor() override;
|
||||||
|
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditorWithoutCreation() override;
|
||||||
NS_IMETHOD_(nsISelectionController*) GetSelectionController() override;
|
NS_IMETHOD_(nsISelectionController*) GetSelectionController() override;
|
||||||
NS_IMETHOD_(nsFrameSelection*) GetConstFrameSelection() override;
|
NS_IMETHOD_(nsFrameSelection*) GetConstFrameSelection() override;
|
||||||
NS_IMETHOD BindToFrame(nsTextControlFrame* aFrame) override;
|
NS_IMETHOD BindToFrame(nsTextControlFrame* aFrame) override;
|
||||||
|
|
|
@ -102,8 +102,12 @@ public:
|
||||||
* Get the editor object associated with the text editor.
|
* Get the editor object associated with the text editor.
|
||||||
* The return value is null if the control does not support an editor
|
* The return value is null if the control does not support an editor
|
||||||
* (for example, if it is a checkbox.)
|
* (for example, if it is a checkbox.)
|
||||||
|
* Note that GetTextEditor() creates editor if it hasn't been created yet.
|
||||||
|
* If you need editor only when the editor is there, you should use
|
||||||
|
* GetTextEditorWithoutCreation().
|
||||||
*/
|
*/
|
||||||
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditor() = 0;
|
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditor() = 0;
|
||||||
|
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditorWithoutCreation() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the selection controller object associated with the text editor.
|
* Get the selection controller object associated with the text editor.
|
||||||
|
|
|
@ -1223,6 +1223,12 @@ nsTextEditorState::GetTextEditor()
|
||||||
return mTextEditor;
|
return mTextEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextEditor*
|
||||||
|
nsTextEditorState::GetTextEditorWithoutCreation()
|
||||||
|
{
|
||||||
|
return mTextEditor;
|
||||||
|
}
|
||||||
|
|
||||||
nsISelectionController*
|
nsISelectionController*
|
||||||
nsTextEditorState::GetSelectionController() const
|
nsTextEditorState::GetSelectionController() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -152,6 +152,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::TextEditor* GetTextEditor();
|
mozilla::TextEditor* GetTextEditor();
|
||||||
|
mozilla::TextEditor* GetTextEditorWithoutCreation();
|
||||||
nsISelectionController* GetSelectionController() const;
|
nsISelectionController* GetSelectionController() const;
|
||||||
nsFrameSelection* GetConstFrameSelection();
|
nsFrameSelection* GetConstFrameSelection();
|
||||||
nsresult BindToFrame(nsTextControlFrame* aFrame);
|
nsresult BindToFrame(nsTextControlFrame* aFrame);
|
||||||
|
|
|
@ -164,14 +164,19 @@ SimpleTest.waitForFocus(() => {
|
||||||
}
|
}
|
||||||
if (inputEvents.length > 0) {
|
if (inputEvents.length > 0) {
|
||||||
if (test.result.useInputEvent) {
|
if (test.result.useInputEvent) {
|
||||||
todo(inputEvents[0] instanceof InputEvent,
|
if (test.type === "number" || test.type === "time") {
|
||||||
|
todo(inputEvents[0] instanceof InputEvent,
|
||||||
|
`"input" event should be dispatched with InputEvent interface when setUserInput("${test.input.before}") is called before ${tag} gets focus`);
|
||||||
|
} else {
|
||||||
|
ok(inputEvents[0] instanceof InputEvent,
|
||||||
`"input" event should be dispatched with InputEvent interface when setUserInput("${test.input.before}") is called before ${tag} gets focus`);
|
`"input" event should be dispatched with InputEvent interface when setUserInput("${test.input.before}") is called before ${tag} gets focus`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ok(inputEvents[0] instanceof Event && !(inputEvents[0] instanceof UIEvent),
|
ok(inputEvents[0] instanceof Event && !(inputEvents[0] instanceof UIEvent),
|
||||||
`"input" event should be dispatched with Event interface when setUserInput("${test.input.before}") is called before ${tag} gets focus`);
|
`"input" event should be dispatched with Event interface when setUserInput("${test.input.before}") is called before ${tag} gets focus`);
|
||||||
}
|
}
|
||||||
todo_is(inputEvents[0].cancelable, false,
|
is(inputEvents[0].cancelable, false,
|
||||||
`"input" event should be never cancelable (${tag}, before getting focus)`);
|
`"input" event should be never cancelable (${tag}, before getting focus)`);
|
||||||
is(inputEvents[0].bubbles, true,
|
is(inputEvents[0].bubbles, true,
|
||||||
`"input" event should always bubble (${tag}, before getting focus)`);
|
`"input" event should always bubble (${tag}, before getting focus)`);
|
||||||
}
|
}
|
||||||
|
@ -222,14 +227,19 @@ SimpleTest.waitForFocus(() => {
|
||||||
}
|
}
|
||||||
if (inputEvents.length > 0) {
|
if (inputEvents.length > 0) {
|
||||||
if (test.result.useInputEvent) {
|
if (test.result.useInputEvent) {
|
||||||
todo(inputEvents[0] instanceof InputEvent,
|
if (test.type === "number" || test.type === "time") {
|
||||||
|
todo(inputEvents[0] instanceof InputEvent,
|
||||||
|
`"input" event should be dispatched with InputEvent interface when setUserInput("${test.input.after}") is called after ${tag} gets focus`);
|
||||||
|
} else {
|
||||||
|
ok(inputEvents[0] instanceof InputEvent,
|
||||||
`"input" event should be dispatched with InputEvent interface when setUserInput("${test.input.after}") is called after ${tag} gets focus`);
|
`"input" event should be dispatched with InputEvent interface when setUserInput("${test.input.after}") is called after ${tag} gets focus`);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ok(inputEvents[0] instanceof Event && !(inputEvents[0] instanceof UIEvent),
|
ok(inputEvents[0] instanceof Event && !(inputEvents[0] instanceof UIEvent),
|
||||||
`"input" event should be dispatched with Event interface when setUserInput("${test.input.after}") is called after ${tag} gets focus`);
|
`"input" event should be dispatched with Event interface when setUserInput("${test.input.after}") is called after ${tag} gets focus`);
|
||||||
}
|
}
|
||||||
todo_is(inputEvents[0].cancelable, false,
|
is(inputEvents[0].cancelable, false,
|
||||||
`"input" event should be never cancelable (${tag}, after getting focus)`);
|
`"input" event should be never cancelable (${tag}, after getting focus)`);
|
||||||
is(inputEvents[0].bubbles, true,
|
is(inputEvents[0].bubbles, true,
|
||||||
`"input" event should always bubble (${tag}, after getting focus)`);
|
`"input" event should always bubble (${tag}, after getting focus)`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,13 +57,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=851780
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkIfInputIsEvent(aEvent, aDescription) {
|
function checkIfInputIsEvent(aEvent, aDescription) {
|
||||||
if (event.target.type === "checkbox" || event.target.type === "radio") {
|
ok(event instanceof Event && !(event instanceof UIEvent),
|
||||||
todo(event instanceof Event && !(event instanceof UIEvent),
|
`"input" event should be dispatched with InputEvent interface ${aDescription}`);
|
||||||
`"input" event should be dispatched with InputEvent interface ${aDescription}`);
|
|
||||||
} else {
|
|
||||||
ok(event instanceof Event && !(event instanceof UIEvent),
|
|
||||||
`"input" event should be dispatched with InputEvent interface ${aDescription}`);
|
|
||||||
}
|
|
||||||
is(aEvent.cancelable, false,
|
is(aEvent.cancelable, false,
|
||||||
`"input" event should be never cancelable ${aDescription}`);
|
`"input" event should be never cancelable ${aDescription}`);
|
||||||
is(aEvent.bubbles, true,
|
is(aEvent.bubbles, true,
|
||||||
|
|
|
@ -2142,56 +2142,6 @@ EditorBase::NotifySelectionChanged(nsIDocument* aDocument,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
class EditorInputEventDispatcher final : public Runnable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EditorInputEventDispatcher(EditorBase* aEditorBase,
|
|
||||||
nsIContent* aTarget,
|
|
||||||
bool aIsComposing)
|
|
||||||
: Runnable("EditorInputEventDispatcher")
|
|
||||||
, mEditorBase(aEditorBase)
|
|
||||||
, mTarget(aTarget)
|
|
||||||
, mIsComposing(aIsComposing)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHOD Run() override
|
|
||||||
{
|
|
||||||
// Note that we don't need to check mDispatchInputEvent here. We need
|
|
||||||
// to check it only when the editor requests to dispatch the input event.
|
|
||||||
|
|
||||||
if (!mTarget->IsInComposedDoc()) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> ps = mEditorBase->GetPresShell();
|
|
||||||
if (!ps) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIWidget> widget = mEditorBase->GetWidget();
|
|
||||||
if (!widget) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Even if the change is caused by untrusted event, we need to dispatch
|
|
||||||
// trusted input event since it's a fact.
|
|
||||||
InternalEditorInputEvent inputEvent(true, eEditorInput, widget);
|
|
||||||
inputEvent.mTime = static_cast<uint64_t>(PR_Now() / 1000);
|
|
||||||
inputEvent.mIsComposing = mIsComposing;
|
|
||||||
nsEventStatus status = nsEventStatus_eIgnore;
|
|
||||||
nsresult rv =
|
|
||||||
ps->HandleEventWithTarget(&inputEvent, nullptr, mTarget, &status);
|
|
||||||
NS_ENSURE_SUCCESS(rv, NS_OK); // print the warning if error
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
RefPtr<EditorBase> mEditorBase;
|
|
||||||
nsCOMPtr<nsIContent> mTarget;
|
|
||||||
bool mIsComposing;
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
EditorBase::NotifyEditorObservers(NotificationForEditorObservers aNotification)
|
EditorBase::NotifyEditorObservers(NotificationForEditorObservers aNotification)
|
||||||
{
|
{
|
||||||
|
@ -2252,19 +2202,15 @@ EditorBase::NotifyEditorObservers(NotificationForEditorObservers aNotification)
|
||||||
void
|
void
|
||||||
EditorBase::FireInputEvent()
|
EditorBase::FireInputEvent()
|
||||||
{
|
{
|
||||||
// We don't need to dispatch multiple input events if there is a pending
|
RefPtr<Element> targetElement = GetInputEventTargetElement();
|
||||||
// input event. However, it may have different event target. If we resolved
|
if (NS_WARN_IF(!targetElement)) {
|
||||||
// this issue, we need to manage the pending events in an array. But it's
|
return;
|
||||||
// overwork. We don't need to do it for the very rare case.
|
}
|
||||||
|
RefPtr<TextEditor> textEditor = AsTextEditor();
|
||||||
nsCOMPtr<nsIContent> target = GetInputEventTargetContent();
|
DebugOnly<nsresult> rvIgnored =
|
||||||
NS_ENSURE_TRUE_VOID(target);
|
nsContentUtils::DispatchInputEvent(targetElement, textEditor);
|
||||||
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||||
// NOTE: Don't refer IsIMEComposing() because it returns false even before
|
"Failed to dispatch input event");
|
||||||
// compositionend. However, DOM Level 3 Events defines it should be
|
|
||||||
// true after compositionstart and before compositionend.
|
|
||||||
nsContentUtils::AddScriptRunner(
|
|
||||||
new EditorInputEventDispatcher(this, target, !!GetComposition()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -356,6 +356,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* ToggleTextDirection() toggles text-direction of the root element.
|
* ToggleTextDirection() toggles text-direction of the root element.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
nsresult ToggleTextDirection();
|
nsresult ToggleTextDirection();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -367,6 +368,7 @@ public:
|
||||||
eLTR,
|
eLTR,
|
||||||
eRTL,
|
eRTL,
|
||||||
};
|
};
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void SwitchTextDirectionTo(TextDirection aTextDirection);
|
void SwitchTextDirectionTo(TextDirection aTextDirection);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1732,7 +1734,9 @@ protected: // Called by helper classes.
|
||||||
* can later merge, if needed. Merging is unavailable between transaction
|
* can later merge, if needed. Merging is unavailable between transaction
|
||||||
* manager batches.
|
* manager batches.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
void BeginPlaceholderTransaction(nsAtom* aTransactionName);
|
void BeginPlaceholderTransaction(nsAtom* aTransactionName);
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
void EndPlaceholderTransaction();
|
void EndPlaceholderTransaction();
|
||||||
|
|
||||||
void BeginUpdateViewBatch();
|
void BeginUpdateViewBatch();
|
||||||
|
@ -1768,6 +1772,8 @@ protected: // Shouldn't be used by friend classes
|
||||||
virtual nsresult SelectAllInternal();
|
virtual nsresult SelectAllInternal();
|
||||||
|
|
||||||
nsresult DetermineCurrentDirection();
|
nsresult DetermineCurrentDirection();
|
||||||
|
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void FireInputEvent();
|
void FireInputEvent();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1888,7 +1894,7 @@ protected: // Shouldn't be used by friend classes
|
||||||
/**
|
/**
|
||||||
* Get the input event target. This might return null.
|
* Get the input event target. This might return null.
|
||||||
*/
|
*/
|
||||||
virtual already_AddRefed<nsIContent> GetInputEventTargetContent() = 0;
|
virtual already_AddRefed<Element> GetInputEventTargetElement() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if spellchecking should be enabled for this editor.
|
* Return true if spellchecking should be enabled for this editor.
|
||||||
|
@ -1950,6 +1956,7 @@ protected: // Shouldn't be used by friend classes
|
||||||
eNotifyEditorObserversOfBefore,
|
eNotifyEditorObserversOfBefore,
|
||||||
eNotifyEditorObserversOfCancel
|
eNotifyEditorObserversOfCancel
|
||||||
};
|
};
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void NotifyEditorObservers(NotificationForEditorObservers aNotification);
|
void NotifyEditorObservers(NotificationForEditorObservers aNotification);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1031,7 +1031,7 @@ EditorEventListener::HandleChangeComposition(
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextEditor* textEditor = editorBase->AsTextEditor();
|
RefPtr<TextEditor> textEditor = editorBase->AsTextEditor();
|
||||||
return textEditor->OnCompositionChange(*aCompositionChangeEvent);
|
return textEditor->OnCompositionChange(*aCompositionChangeEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1050,7 +1050,7 @@ EditorEventListener::HandleEndComposition(
|
||||||
MOZ_ASSERT(!aCompositionEndEvent->DefaultPrevented(),
|
MOZ_ASSERT(!aCompositionEndEvent->DefaultPrevented(),
|
||||||
"eCompositionEnd shouldn't be cancelable");
|
"eCompositionEnd shouldn't be cancelable");
|
||||||
|
|
||||||
TextEditor* textEditor = editorBase->AsTextEditor();
|
RefPtr<TextEditor> textEditor = editorBase->AsTextEditor();
|
||||||
textEditor->OnCompositionEnd(*aCompositionEndEvent);
|
textEditor->OnCompositionEnd(*aCompositionEndEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,11 +63,14 @@ protected:
|
||||||
|
|
||||||
#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
|
#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
|
||||||
nsresult KeyDown(const WidgetKeyboardEvent* aKeyboardEvent);
|
nsresult KeyDown(const WidgetKeyboardEvent* aKeyboardEvent);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsresult KeyUp(const WidgetKeyboardEvent* aKeyboardEvent);
|
nsresult KeyUp(const WidgetKeyboardEvent* aKeyboardEvent);
|
||||||
#endif
|
#endif
|
||||||
nsresult KeyPress(WidgetKeyboardEvent* aKeyboardEvent);
|
nsresult KeyPress(WidgetKeyboardEvent* aKeyboardEvent);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsresult HandleChangeComposition(WidgetCompositionEvent* aCompositionEvent);
|
nsresult HandleChangeComposition(WidgetCompositionEvent* aCompositionEvent);
|
||||||
nsresult HandleStartComposition(WidgetCompositionEvent* aCompositionEvent);
|
nsresult HandleStartComposition(WidgetCompositionEvent* aCompositionEvent);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void HandleEndComposition(WidgetCompositionEvent* aCompositionEvent);
|
void HandleEndComposition(WidgetCompositionEvent* aCompositionEvent);
|
||||||
MOZ_CAN_RUN_SCRIPT
|
MOZ_CAN_RUN_SCRIPT
|
||||||
virtual nsresult MouseDown(dom::MouseEvent* aMouseEvent);
|
virtual nsresult MouseDown(dom::MouseEvent* aMouseEvent);
|
||||||
|
|
|
@ -5454,10 +5454,10 @@ HTMLEditor::GetPreferredIMEState(IMEState* aState)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIContent>
|
already_AddRefed<Element>
|
||||||
HTMLEditor::GetInputEventTargetContent()
|
HTMLEditor::GetInputEventTargetElement()
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIContent> target = GetActiveEditingHost();
|
RefPtr<Element> target = GetActiveEditingHost();
|
||||||
return target.forget();
|
return target.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1778,7 +1778,7 @@ protected: // Shouldn't be used by friend classes
|
||||||
*/
|
*/
|
||||||
already_AddRefed<nsINode> GetFocusedNode();
|
already_AddRefed<nsINode> GetFocusedNode();
|
||||||
|
|
||||||
virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
|
virtual already_AddRefed<Element> GetInputEventTargetElement() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return TRUE if aElement is a table-related elemet and caret was set.
|
* Return TRUE if aElement is a table-related elemet and caret was set.
|
||||||
|
|
|
@ -1460,10 +1460,10 @@ TextEditor::OnCompositionEnd(WidgetCompositionEvent& aCompositionEndEvent)
|
||||||
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
|
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIContent>
|
already_AddRefed<Element>
|
||||||
TextEditor::GetInputEventTargetContent()
|
TextEditor::GetInputEventTargetElement()
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIContent> target = do_QueryInterface(mEventTarget);
|
nsCOMPtr<Element> target = do_QueryInterface(mEventTarget);
|
||||||
return target.forget();
|
return target.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,7 +64,9 @@ public:
|
||||||
|
|
||||||
// If there are some good name to create non-virtual Undo()/Redo() methods,
|
// If there are some good name to create non-virtual Undo()/Redo() methods,
|
||||||
// we should create them and those methods should just run them.
|
// we should create them and those methods should just run them.
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
NS_IMETHOD Undo(uint32_t aCount) final;
|
NS_IMETHOD Undo(uint32_t aCount) final;
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
NS_IMETHOD Redo(uint32_t aCount) final;
|
NS_IMETHOD Redo(uint32_t aCount) final;
|
||||||
|
|
||||||
NS_IMETHOD Cut() override;
|
NS_IMETHOD Cut() override;
|
||||||
|
@ -205,6 +207,7 @@ public:
|
||||||
* @param aCompositionChangeEvent eCompositionChange event which should
|
* @param aCompositionChangeEvent eCompositionChange event which should
|
||||||
* be handled in this editor.
|
* be handled in this editor.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsresult
|
nsresult
|
||||||
OnCompositionChange(WidgetCompositionEvent& aCompositionChangeEvent);
|
OnCompositionChange(WidgetCompositionEvent& aCompositionChangeEvent);
|
||||||
|
|
||||||
|
@ -213,6 +216,7 @@ public:
|
||||||
* event and it's followed by eCompositionEnd event and after
|
* event and it's followed by eCompositionEnd event and after
|
||||||
* OnCompositionChange() is called.
|
* OnCompositionChange() is called.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void OnCompositionEnd(WidgetCompositionEvent& aCompositionEndEvent);
|
void OnCompositionEnd(WidgetCompositionEvent& aCompositionEndEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -530,7 +534,7 @@ protected: // Shouldn't be used by friend classes
|
||||||
*/
|
*/
|
||||||
bool EnsureComposition(WidgetCompositionEvent& aCompositionEvent);
|
bool EnsureComposition(WidgetCompositionEvent& aCompositionEvent);
|
||||||
|
|
||||||
virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
|
virtual already_AddRefed<Element> GetInputEventTargetElement() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable nsCOMPtr<nsIDocumentEncoder> mCachedDocumentEncoder;
|
mutable nsCOMPtr<nsIDocumentEncoder> mCachedDocumentEncoder;
|
||||||
|
|
|
@ -128,6 +128,7 @@ public:
|
||||||
* @param aRepaint if true then force repaint (NOTE: we always force repaint currently)
|
* @param aRepaint if true then force repaint (NOTE: we always force repaint currently)
|
||||||
* @note This method might destroy |this|.
|
* @note This method might destroy |this|.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
virtual void SetFocus(bool aOn, bool aRepaint) override;
|
virtual void SetFocus(bool aOn, bool aRepaint) override;
|
||||||
|
|
||||||
bool IsDroppedDown() { return mDroppedDown; }
|
bool IsDroppedDown() { return mDroppedDown; }
|
||||||
|
|
|
@ -459,11 +459,11 @@ nsFileControlFrame::DnDListener::HandleEvent(Event* aEvent)
|
||||||
inputElement->SetFiles(fileList, true);
|
inputElement->SetFiles(fileList, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsContentUtils::DispatchTrustedEvent(inputElement->OwnerDoc(),
|
RefPtr<TextEditor> textEditor;
|
||||||
static_cast<nsINode*>(inputElement),
|
DebugOnly<nsresult> rvIgnored =
|
||||||
NS_LITERAL_STRING("input"),
|
nsContentUtils::DispatchInputEvent(inputElement);
|
||||||
CanBubble::eYes,
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||||
Cancelable::eNo);
|
"Failed to dispatch input event");
|
||||||
nsContentUtils::DispatchTrustedEvent(inputElement->OwnerDoc(),
|
nsContentUtils::DispatchTrustedEvent(inputElement->OwnerDoc(),
|
||||||
static_cast<nsINode*>(inputElement),
|
static_cast<nsINode*>(inputElement),
|
||||||
NS_LITERAL_STRING("change"),
|
NS_LITERAL_STRING("change"),
|
||||||
|
|
|
@ -123,7 +123,9 @@ protected:
|
||||||
: MouseListener(aFrame)
|
: MouseListener(aFrame)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
NS_DECL_NSIDOMEVENTLISTENER
|
// nsIDOMEventListener
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
|
NS_IMETHOD HandleEvent(mozilla::dom::Event* aEvent) override;
|
||||||
|
|
||||||
nsresult GetBlobImplForWebkitDirectory(mozilla::dom::FileList* aFileList,
|
nsresult GetBlobImplForWebkitDirectory(mozilla::dom::FileList* aFileList,
|
||||||
mozilla::dom::BlobImpl** aBlobImpl);
|
mozilla::dom::BlobImpl** aBlobImpl);
|
||||||
|
|
|
@ -70,7 +70,10 @@ public:
|
||||||
void SetFrame(nsListControlFrame *aFrame) { mFrame = aFrame; }
|
void SetFrame(nsListControlFrame *aFrame) { mFrame = aFrame; }
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSIDOMEVENTLISTENER
|
|
||||||
|
// nsIDOMEventListener
|
||||||
|
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||||
|
NS_IMETHOD HandleEvent(Event* aEvent) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~nsListEventListener() {}
|
~nsListEventListener() {}
|
||||||
|
@ -1390,14 +1393,17 @@ nsListControlFrame::FireOnInputAndOnChange()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIContent> content = mContent;
|
RefPtr<Element> element = Element::FromNodeOrNull(mContent);
|
||||||
|
if (NS_WARN_IF(!element)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Dispatch the input event.
|
// Dispatch the input event.
|
||||||
nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
|
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(element);
|
||||||
NS_LITERAL_STRING("input"),
|
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||||
CanBubble::eYes,
|
"Failed to dispatch input event");
|
||||||
Cancelable::eNo);
|
|
||||||
// Dispatch the change event.
|
// Dispatch the change event.
|
||||||
nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
|
nsContentUtils::DispatchTrustedEvent(element->OwnerDoc(), element,
|
||||||
NS_LITERAL_STRING("change"),
|
NS_LITERAL_STRING("change"),
|
||||||
CanBubble::eYes,
|
CanBubble::eYes,
|
||||||
Cancelable::eNo);
|
Cancelable::eNo);
|
||||||
|
|
|
@ -134,6 +134,7 @@ public:
|
||||||
* Dispatch a DOM oninput and onchange event synchroniously.
|
* Dispatch a DOM oninput and onchange event synchroniously.
|
||||||
* @note This method might destroy the frame, pres shell and other objects.
|
* @note This method might destroy the frame, pres shell and other objects.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void FireOnInputAndOnChange();
|
void FireOnInputAndOnChange();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,10 +161,13 @@ public:
|
||||||
* @note These methods might destroy the frame, pres shell and other objects.
|
* @note These methods might destroy the frame, pres shell and other objects.
|
||||||
*/
|
*/
|
||||||
nsresult MouseDown(mozilla::dom::Event* aMouseEvent);
|
nsresult MouseDown(mozilla::dom::Event* aMouseEvent);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsresult MouseUp(mozilla::dom::Event* aMouseEvent);
|
nsresult MouseUp(mozilla::dom::Event* aMouseEvent);
|
||||||
nsresult MouseMove(mozilla::dom::Event* aMouseEvent);
|
nsresult MouseMove(mozilla::dom::Event* aMouseEvent);
|
||||||
nsresult DragMove(mozilla::dom::Event* aMouseEvent);
|
nsresult DragMove(mozilla::dom::Event* aMouseEvent);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsresult KeyDown(mozilla::dom::Event* aKeyEvent);
|
nsresult KeyDown(mozilla::dom::Event* aKeyEvent);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
nsresult KeyPress(mozilla::dom::Event* aKeyEvent);
|
nsresult KeyPress(mozilla::dom::Event* aKeyEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -257,6 +261,7 @@ protected:
|
||||||
* @note This method might destroy the frame, pres shell and other objects.
|
* @note This method might destroy the frame, pres shell and other objects.
|
||||||
* Returns false if calling it destroyed |this|.
|
* Returns false if calling it destroyed |this|.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
bool UpdateSelection();
|
bool UpdateSelection();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -271,6 +276,7 @@ protected:
|
||||||
* Toggles (show/hide) the combobox dropdown menu.
|
* Toggles (show/hide) the combobox dropdown menu.
|
||||||
* @note This method might destroy the frame, pres shell and other objects.
|
* @note This method might destroy the frame, pres shell and other objects.
|
||||||
*/
|
*/
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void DropDownToggleKey(mozilla::dom::Event* aKeyEvent);
|
void DropDownToggleKey(mozilla::dom::Event* aKeyEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -378,6 +384,7 @@ protected:
|
||||||
bool HandleListSelection(mozilla::dom::Event * aDOMEvent,
|
bool HandleListSelection(mozilla::dom::Event * aDOMEvent,
|
||||||
int32_t selectedIndex);
|
int32_t selectedIndex);
|
||||||
void InitSelectionRange(int32_t aClickedIndex);
|
void InitSelectionRange(int32_t aClickedIndex);
|
||||||
|
MOZ_CAN_RUN_SCRIPT
|
||||||
void PostHandleKeyEvent(int32_t aNewIndex, uint32_t aCharCode,
|
void PostHandleKeyEvent(int32_t aNewIndex, uint32_t aCharCode,
|
||||||
bool aIsShift, bool aIsControlOrMeta);
|
bool aIsShift, bool aIsControlOrMeta);
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,10 @@ function handleSubmit() { // eslint-disable-line no-unused-vars
|
||||||
function handleInput(aEvent) {
|
function handleInput(aEvent) {
|
||||||
info("Input");
|
info("Input");
|
||||||
is(input.value, expectedValue, "Check input value");
|
is(input.value, expectedValue, "Check input value");
|
||||||
todo(aEvent instanceof InputEvent,
|
ok(aEvent instanceof InputEvent,
|
||||||
'"input" event should be dispatched with InputEvent interface');
|
'"input" event should be dispatched with InputEvent interface');
|
||||||
todo_is(aEvent.cancelable, false,
|
is(aEvent.cancelable, false,
|
||||||
'"input" event should be never cancelable');
|
'"input" event should be never cancelable');
|
||||||
is(aEvent.bubbles, true,
|
is(aEvent.bubbles, true,
|
||||||
'"input" event should always bubble');
|
'"input" event should always bubble');
|
||||||
input.removeEventListener("input", handleInput, true);
|
input.removeEventListener("input", handleInput, true);
|
||||||
|
|
|
@ -95,19 +95,12 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
||||||
if (aTest.inputEvents[i].todoInterfaceOnXUL && aInputEvents[i].target.tagName === "textbox") {
|
if (aTest.inputEvents[i].todoInterfaceOnXUL && aInputEvents[i].target.tagName === "textbox") {
|
||||||
this._todo_is(aInputEvents[i] instanceof this._window.InputEvent, true,
|
this._todo_is(aInputEvents[i] instanceof this._window.InputEvent, true,
|
||||||
this._description + ", " + aTest.description + ': "input" event should be dispatched with InputEvent interface');
|
this._description + ", " + aTest.description + ': "input" event should be dispatched with InputEvent interface');
|
||||||
this._is(aInputEvents[i].cancelable, false,
|
|
||||||
this._description + ", " + aTest.description + ': "input" event should be never cancelable');
|
|
||||||
} else if (aTest.inputEvents[i].inputType === "insertReplacementText") {
|
|
||||||
this._todo_is(aInputEvents[i] instanceof this._window.InputEvent, true,
|
|
||||||
this._description + ", " + aTest.description + ': "input" event should be dispatched with InputEvent interface');
|
|
||||||
this._todo_is(aInputEvents[i].cancelable, false,
|
|
||||||
this._description + ", " + aTest.description + ': "input" event should be never cancelable');
|
|
||||||
} else {
|
} else {
|
||||||
this._is(aInputEvents[i] instanceof this._window.InputEvent, true,
|
this._is(aInputEvents[i] instanceof this._window.InputEvent, true,
|
||||||
this._description + ", " + aTest.description + ': "input" event should be dispatched with InputEvent interface');
|
this._description + ", " + aTest.description + ': "input" event should be dispatched with InputEvent interface');
|
||||||
this._is(aInputEvents[i].cancelable, false,
|
|
||||||
this._description + ", " + aTest.description + ': "input" event should be never cancelable');
|
|
||||||
}
|
}
|
||||||
|
this._is(aInputEvents[i].cancelable, false,
|
||||||
|
this._description + ", " + aTest.description + ': "input" event should be never cancelable');
|
||||||
this._is(aInputEvents[i].bubbles, true,
|
this._is(aInputEvents[i].bubbles, true,
|
||||||
this._description + ", " + aTest.description + ': "input" event should always bubble');
|
this._description + ", " + aTest.description + ': "input" event should always bubble');
|
||||||
}
|
}
|
||||||
|
|
|
@ -510,7 +510,8 @@ private:
|
||||||
mFlags.mBubbles = true;
|
mFlags.mBubbles = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (mMessage == eResize) {
|
if (mMessage == eResize ||
|
||||||
|
mMessage == eEditorInput) {
|
||||||
mFlags.mCancelable = false;
|
mFlags.mCancelable = false;
|
||||||
} else {
|
} else {
|
||||||
mFlags.mCancelable = true;
|
mFlags.mCancelable = true;
|
||||||
|
@ -614,7 +615,8 @@ public:
|
||||||
|
|
||||||
// If JS creates an event with unknown event type or known event type but
|
// If JS creates an event with unknown event type or known event type but
|
||||||
// for different event interface, the event type is stored to this.
|
// for different event interface, the event type is stored to this.
|
||||||
// NOTE: This is always used if the instance is a WidgetCommandEvent instance.
|
// NOTE: This is always used if the instance is a WidgetCommandEvent instance
|
||||||
|
// or "input" event is dispatched with dom::Event class.
|
||||||
RefPtr<nsAtom> mSpecifiedEventType;
|
RefPtr<nsAtom> mSpecifiedEventType;
|
||||||
|
|
||||||
// nsAtom isn't available on non-main thread due to unsafe. Therefore,
|
// nsAtom isn't available on non-main thread due to unsafe. Therefore,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче