зеркало из 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([
|
||||
new Promise(resolve => element.addEventListener("input", (event) => {
|
||||
if (element.tagName == "INPUT" && element.type == "text") {
|
||||
todo(event instanceof InputEvent,
|
||||
`"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}`);
|
||||
ok(event instanceof InputEvent,
|
||||
`"input" event should be dispatched with InputEvent interface on ${element.tagName}`);
|
||||
} else {
|
||||
todo(event instanceof Event && !(event instanceof UIEvent),
|
||||
`"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,
|
||||
`"input" event should always bubble on ${element.tagName}`);
|
||||
resolve();
|
||||
|
|
|
@ -68,10 +68,10 @@ async function confirmClear(selector) {
|
|||
info("Await for clearing input");
|
||||
let promise = new Promise(resolve =>
|
||||
document.querySelector(selector).addEventListener("input", (event) => {
|
||||
todo(event instanceof InputEvent,
|
||||
'"input" event should be dispatched with InputEvent interface');
|
||||
todo_is(event.cancelable, false,
|
||||
'"input" event should be never cancelable');
|
||||
ok(event instanceof InputEvent,
|
||||
'"input" event should be dispatched with InputEvent interface');
|
||||
is(event.cancelable, false,
|
||||
'"input" event should be never cancelable');
|
||||
is(event.bubbles, true,
|
||||
'"input" event should always bubble');
|
||||
resolve();
|
||||
|
|
|
@ -50,16 +50,14 @@ function checkElementFilled(element, expectedvalue) {
|
|||
element.addEventListener("input", function onInput(event) {
|
||||
ok(true, "Checking " + element.name + " field fires input event");
|
||||
if (element.tagName == "INPUT" && element.type == "text") {
|
||||
todo(event instanceof InputEvent,
|
||||
`"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}`);
|
||||
ok(event instanceof InputEvent,
|
||||
`"input" event should be dispatched with InputEvent interface on ${element.name}`);
|
||||
} else {
|
||||
todo(event instanceof Event && !(event instanceof UIEvent),
|
||||
`"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,
|
||||
`"input" event should always bubble on ${element.name}`);
|
||||
resolve();
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#include "mozilla/dom/HTMLInputElement.h"
|
||||
#include "mozilla/dom/HTMLSlotElement.h"
|
||||
#include "mozilla/dom/HTMLTemplateElement.h"
|
||||
#include "mozilla/dom/HTMLTextAreaElement.h"
|
||||
#include "mozilla/dom/IDTracker.h"
|
||||
#include "mozilla/dom/MouseEventBinding.h"
|
||||
#include "mozilla/dom/KeyboardEventBinding.h"
|
||||
|
@ -85,6 +86,7 @@
|
|||
#include "mozilla/dom/Selection.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "mozilla/TextEditor.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "nsArrayUtils.h"
|
||||
#include "nsAString.h"
|
||||
|
@ -4367,6 +4369,8 @@ nsContentUtils::DispatchTrustedEvent(nsIDocument* aDoc, nsISupports* aTarget,
|
|||
Composed aComposed,
|
||||
bool* aDefaultAction)
|
||||
{
|
||||
MOZ_ASSERT(!aEventName.EqualsLiteral("input"),
|
||||
"Use DispatchInputEvent() instead");
|
||||
return DispatchEvent(aDoc, aTarget, aEventName, aCanBubble, aCancelable,
|
||||
aComposed, Trusted::eYes, aDefaultAction);
|
||||
}
|
||||
|
@ -4450,6 +4454,110 @@ nsContentUtils::DispatchEvent(nsIDocument* aDoc, nsISupports* aTarget,
|
|||
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
|
||||
nsContentUtils::DispatchChromeEvent(nsIDocument *aDoc,
|
||||
nsISupports *aTarget,
|
||||
|
|
|
@ -123,6 +123,7 @@ class Dispatcher;
|
|||
class ErrorResult;
|
||||
class EventListenerManager;
|
||||
class HTMLEditor;
|
||||
class TextEditor;
|
||||
|
||||
namespace dom {
|
||||
class ContentFrameMessageManager;
|
||||
|
@ -1377,9 +1378,12 @@ public:
|
|||
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
|
||||
* 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 aTarget The target of the event, should be QIable to
|
||||
* EventTarget.
|
||||
|
@ -1438,6 +1442,26 @@ public:
|
|||
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.
|
||||
* Works only with events which can be created by calling
|
||||
|
|
|
@ -251,16 +251,12 @@ public:
|
|||
Unused << NS_WARN_IF(NS_FAILED(DispatchEvents()));
|
||||
}
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
nsresult
|
||||
DispatchEvents()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
rv = nsContentUtils::DispatchTrustedEvent(mInputElement->OwnerDoc(),
|
||||
static_cast<Element*>(mInputElement.get()),
|
||||
NS_LITERAL_STRING("input"),
|
||||
CanBubble::eYes,
|
||||
Cancelable::eNo);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "DispatchTrustedEvent failed");
|
||||
nsresult rv = nsContentUtils::DispatchInputEvent(mInputElement);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to dispatch input event");
|
||||
|
||||
rv = nsContentUtils::DispatchTrustedEvent(mInputElement->OwnerDoc(),
|
||||
static_cast<Element*>(mInputElement.get()),
|
||||
|
@ -595,7 +591,9 @@ public:
|
|||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
NS_IMETHOD Update(const nsAString& aColor) override;
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
NS_IMETHOD Done(const nsAString& aColor) override;
|
||||
|
||||
private:
|
||||
|
@ -604,6 +602,7 @@ private:
|
|||
* 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.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult UpdateInternal(const nsAString& aColor, bool aTrustedUpdate);
|
||||
|
||||
RefPtr<HTMLInputElement> mInput;
|
||||
|
@ -634,15 +633,14 @@ nsColorPickerShownCallback::UpdateInternal(const nsAString& aColor,
|
|||
}
|
||||
}
|
||||
|
||||
if (valueChanged) {
|
||||
mValueChanged = true;
|
||||
return nsContentUtils::DispatchTrustedEvent(mInput->OwnerDoc(),
|
||||
static_cast<Element*>(mInput.get()),
|
||||
NS_LITERAL_STRING("input"),
|
||||
CanBubble::eYes,
|
||||
Cancelable::eNo);
|
||||
if (!valueChanged) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mValueChanged = true;
|
||||
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(mInput);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -2353,13 +2351,9 @@ HTMLInputElement::SetUserInput(const nsAString& aValue,
|
|||
nsTextEditorState::eSetValue_MoveCursorToEndIfValueChanged);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
// FIXME: We're inconsistent about whether "input" events are cancelable or
|
||||
// not.
|
||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
||||
static_cast<Element*>(this),
|
||||
NS_LITERAL_STRING("input"),
|
||||
CanBubble::eYes,
|
||||
Cancelable::eYes);
|
||||
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
|
||||
// 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.
|
||||
|
@ -2390,6 +2384,16 @@ HTMLInputElement::GetTextEditor()
|
|||
return GetTextEditorFromState();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(TextEditor*)
|
||||
HTMLInputElement::GetTextEditorWithoutCreation()
|
||||
{
|
||||
nsTextEditorState* state = GetEditorState();
|
||||
if (!state) {
|
||||
return nullptr;
|
||||
}
|
||||
return state->GetTextEditorWithoutCreation();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsISelectionController*)
|
||||
HTMLInputElement::GetSelectionController()
|
||||
{
|
||||
|
@ -2735,7 +2739,7 @@ HTMLInputElement::SetFiles(FileList* aFiles)
|
|||
/* static */ void
|
||||
HTMLInputElement::HandleNumberControlSpin(void* aData)
|
||||
{
|
||||
HTMLInputElement* input = static_cast<HTMLInputElement*>(aData);
|
||||
RefPtr<HTMLInputElement> input = static_cast<HTMLInputElement*>(aData);
|
||||
|
||||
NS_ASSERTION(input->mNumberControlSpinnerIsSpinning,
|
||||
"Should have called nsRepeatService::Stop()");
|
||||
|
@ -3750,12 +3754,9 @@ HTMLInputElement::CancelRangeThumbDrag(bool aIsForUserEvent)
|
|||
if (frame) {
|
||||
frame->UpdateForValueChange();
|
||||
}
|
||||
RefPtr<AsyncEventDispatcher> asyncDispatcher =
|
||||
new AsyncEventDispatcher(this,
|
||||
NS_LITERAL_STRING("input"),
|
||||
CanBubble::eYes,
|
||||
ChromeOnlyDispatch::eNo);
|
||||
asyncDispatcher->RunDOMEventWhenSafe();
|
||||
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3778,11 +3779,9 @@ HTMLInputElement::SetValueOfRangeForUserEvent(Decimal aValue)
|
|||
}
|
||||
|
||||
if (GetValueAsDecimal() != oldValue) {
|
||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
||||
static_cast<Element*>(this),
|
||||
NS_LITERAL_STRING("input"),
|
||||
CanBubble::eYes,
|
||||
Cancelable::eNo);
|
||||
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3877,11 +3876,9 @@ HTMLInputElement::StepNumberControlForUserEvent(int32_t aDirection)
|
|||
SetValueInternal(newVal, nsTextEditorState::eSetValue_BySetUserInput |
|
||||
nsTextEditorState::eSetValue_Notify);
|
||||
|
||||
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
|
||||
static_cast<Element*>(this),
|
||||
NS_LITERAL_STRING("input"),
|
||||
CanBubble::eYes,
|
||||
Cancelable::eNo);
|
||||
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -4091,9 +4088,9 @@ HTMLInputElement::PostHandleEvent(EventChainPostVisitor& aVisitor)
|
|||
}
|
||||
} else {
|
||||
// Fire input event and then change event.
|
||||
nsContentUtils::DispatchTrustedEvent<InternalEditorInputEvent>
|
||||
(OwnerDoc(), static_cast<Element*>(this),
|
||||
eEditorInput, CanBubble::eYes, Cancelable::eNo);
|
||||
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(this);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
|
||||
nsContentUtils::DispatchTrustedEvent<WidgetEvent>
|
||||
(OwnerDoc(), static_cast<Element*>(this),
|
||||
|
|
|
@ -187,12 +187,18 @@ public:
|
|||
|
||||
void GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
|
||||
virtual nsresult PreHandleEvent(EventChainVisitor& aVisitor) override;
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
virtual nsresult PostHandleEvent(
|
||||
EventChainPostVisitor& aVisitor) override;
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
void PostHandleEventForRangeThumb(EventChainPostVisitor& aVisitor);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void StartRangeThumbDrag(WidgetGUIEvent* aEvent);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void FinishRangeThumbDrag(WidgetGUIEvent* aEvent = nullptr);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void CancelRangeThumbDrag(bool aIsForUserEvent = true);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void SetValueOfRangeForUserEvent(Decimal aValue);
|
||||
|
||||
virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
||||
|
@ -223,6 +229,7 @@ public:
|
|||
NS_IMETHOD_(bool) ValueChanged() const override;
|
||||
NS_IMETHOD_(void) GetTextEditorValue(nsAString& aValue, bool aIgnoreWrap) const override;
|
||||
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditor() override;
|
||||
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditorWithoutCreation() override;
|
||||
NS_IMETHOD_(nsISelectionController*) GetSelectionController() override;
|
||||
NS_IMETHOD_(nsFrameSelection*) GetConstFrameSelection() override;
|
||||
NS_IMETHOD BindToFrame(nsTextControlFrame* aFrame) override;
|
||||
|
@ -891,12 +898,14 @@ public:
|
|||
};
|
||||
void StopNumberControlSpinnerSpin(SpinnerStopState aState =
|
||||
eAllowDispatchingEvents);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void StepNumberControlForUserEvent(int32_t aDirection);
|
||||
|
||||
/**
|
||||
* The callback function used by the nsRepeatService that we use to spin the
|
||||
* spinner for <input type=number>.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
static void HandleNumberControlSpin(void* aData);
|
||||
|
||||
bool NumberSpinnerUpButtonIsDepressed() const
|
||||
|
@ -916,6 +925,7 @@ public:
|
|||
*/
|
||||
nsIEditor* GetEditor();
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
void SetUserInput(const nsAString& aInput,
|
||||
nsIPrincipal& aSubjectPrincipal);
|
||||
|
||||
|
@ -1054,6 +1064,7 @@ protected:
|
|||
/**
|
||||
* Called when an attribute has just been changed
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
|
||||
const nsAttrValue* aValue,
|
||||
const nsAttrValue* aOldValue,
|
||||
|
@ -1180,6 +1191,7 @@ protected:
|
|||
/**
|
||||
* Manages the internal data storage across type changes.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void HandleTypeChange(uint8_t aNewType, bool aNotify);
|
||||
|
||||
/**
|
||||
|
|
|
@ -224,6 +224,12 @@ HTMLTextAreaElement::GetTextEditor()
|
|||
return mState.GetTextEditor();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(TextEditor*)
|
||||
HTMLTextAreaElement::GetTextEditorWithoutCreation()
|
||||
{
|
||||
return mState.GetTextEditorWithoutCreation();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(nsISelectionController*)
|
||||
HTMLTextAreaElement::GetSelectionController()
|
||||
{
|
||||
|
|
|
@ -83,6 +83,7 @@ public:
|
|||
NS_IMETHOD_(bool) ValueChanged() const override;
|
||||
NS_IMETHOD_(void) GetTextEditorValue(nsAString& aValue, bool aIgnoreWrap) const override;
|
||||
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditor() override;
|
||||
NS_IMETHOD_(mozilla::TextEditor*) GetTextEditorWithoutCreation() override;
|
||||
NS_IMETHOD_(nsISelectionController*) GetSelectionController() override;
|
||||
NS_IMETHOD_(nsFrameSelection*) GetConstFrameSelection() override;
|
||||
NS_IMETHOD BindToFrame(nsTextControlFrame* aFrame) override;
|
||||
|
|
|
@ -102,8 +102,12 @@ public:
|
|||
* Get the editor object associated with the text editor.
|
||||
* The return value is null if the control does not support an editor
|
||||
* (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*) GetTextEditorWithoutCreation() = 0;
|
||||
|
||||
/**
|
||||
* Get the selection controller object associated with the text editor.
|
||||
|
|
|
@ -1223,6 +1223,12 @@ nsTextEditorState::GetTextEditor()
|
|||
return mTextEditor;
|
||||
}
|
||||
|
||||
TextEditor*
|
||||
nsTextEditorState::GetTextEditorWithoutCreation()
|
||||
{
|
||||
return mTextEditor;
|
||||
}
|
||||
|
||||
nsISelectionController*
|
||||
nsTextEditorState::GetSelectionController() const
|
||||
{
|
||||
|
|
|
@ -152,6 +152,7 @@ public:
|
|||
}
|
||||
|
||||
mozilla::TextEditor* GetTextEditor();
|
||||
mozilla::TextEditor* GetTextEditorWithoutCreation();
|
||||
nsISelectionController* GetSelectionController() const;
|
||||
nsFrameSelection* GetConstFrameSelection();
|
||||
nsresult BindToFrame(nsTextControlFrame* aFrame);
|
||||
|
|
|
@ -164,14 +164,19 @@ SimpleTest.waitForFocus(() => {
|
|||
}
|
||||
if (inputEvents.length > 0) {
|
||||
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`);
|
||||
}
|
||||
} else {
|
||||
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`);
|
||||
}
|
||||
todo_is(inputEvents[0].cancelable, false,
|
||||
`"input" event should be never cancelable (${tag}, before getting focus)`);
|
||||
is(inputEvents[0].cancelable, false,
|
||||
`"input" event should be never cancelable (${tag}, before getting focus)`);
|
||||
is(inputEvents[0].bubbles, true,
|
||||
`"input" event should always bubble (${tag}, before getting focus)`);
|
||||
}
|
||||
|
@ -222,14 +227,19 @@ SimpleTest.waitForFocus(() => {
|
|||
}
|
||||
if (inputEvents.length > 0) {
|
||||
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`);
|
||||
}
|
||||
} else {
|
||||
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`);
|
||||
}
|
||||
todo_is(inputEvents[0].cancelable, false,
|
||||
`"input" event should be never cancelable (${tag}, after getting focus)`);
|
||||
is(inputEvents[0].cancelable, false,
|
||||
`"input" event should be never cancelable (${tag}, after getting focus)`);
|
||||
is(inputEvents[0].bubbles, true,
|
||||
`"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) {
|
||||
if (event.target.type === "checkbox" || event.target.type === "radio") {
|
||||
todo(event instanceof Event && !(event instanceof UIEvent),
|
||||
`"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}`);
|
||||
}
|
||||
ok(event instanceof Event && !(event instanceof UIEvent),
|
||||
`"input" event should be dispatched with InputEvent interface ${aDescription}`);
|
||||
is(aEvent.cancelable, false,
|
||||
`"input" event should be never cancelable ${aDescription}`);
|
||||
is(aEvent.bubbles, true,
|
||||
|
|
|
@ -2142,56 +2142,6 @@ EditorBase::NotifySelectionChanged(nsIDocument* aDocument,
|
|||
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
|
||||
EditorBase::NotifyEditorObservers(NotificationForEditorObservers aNotification)
|
||||
{
|
||||
|
@ -2252,19 +2202,15 @@ EditorBase::NotifyEditorObservers(NotificationForEditorObservers aNotification)
|
|||
void
|
||||
EditorBase::FireInputEvent()
|
||||
{
|
||||
// We don't need to dispatch multiple input events if there is a pending
|
||||
// input event. However, it may have different event target. If we resolved
|
||||
// this issue, we need to manage the pending events in an array. But it's
|
||||
// overwork. We don't need to do it for the very rare case.
|
||||
|
||||
nsCOMPtr<nsIContent> target = GetInputEventTargetContent();
|
||||
NS_ENSURE_TRUE_VOID(target);
|
||||
|
||||
// NOTE: Don't refer IsIMEComposing() because it returns false even before
|
||||
// compositionend. However, DOM Level 3 Events defines it should be
|
||||
// true after compositionstart and before compositionend.
|
||||
nsContentUtils::AddScriptRunner(
|
||||
new EditorInputEventDispatcher(this, target, !!GetComposition()));
|
||||
RefPtr<Element> targetElement = GetInputEventTargetElement();
|
||||
if (NS_WARN_IF(!targetElement)) {
|
||||
return;
|
||||
}
|
||||
RefPtr<TextEditor> textEditor = AsTextEditor();
|
||||
DebugOnly<nsresult> rvIgnored =
|
||||
nsContentUtils::DispatchInputEvent(targetElement, textEditor);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
@ -356,6 +356,7 @@ public:
|
|||
/**
|
||||
* ToggleTextDirection() toggles text-direction of the root element.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
nsresult ToggleTextDirection();
|
||||
|
||||
/**
|
||||
|
@ -367,6 +368,7 @@ public:
|
|||
eLTR,
|
||||
eRTL,
|
||||
};
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void SwitchTextDirectionTo(TextDirection aTextDirection);
|
||||
|
||||
/**
|
||||
|
@ -1732,7 +1734,9 @@ protected: // Called by helper classes.
|
|||
* can later merge, if needed. Merging is unavailable between transaction
|
||||
* manager batches.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
void BeginPlaceholderTransaction(nsAtom* aTransactionName);
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
void EndPlaceholderTransaction();
|
||||
|
||||
void BeginUpdateViewBatch();
|
||||
|
@ -1768,6 +1772,8 @@ protected: // Shouldn't be used by friend classes
|
|||
virtual nsresult SelectAllInternal();
|
||||
|
||||
nsresult DetermineCurrentDirection();
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void FireInputEvent();
|
||||
|
||||
/**
|
||||
|
@ -1888,7 +1894,7 @@ protected: // Shouldn't be used by friend classes
|
|||
/**
|
||||
* 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.
|
||||
|
@ -1950,6 +1956,7 @@ protected: // Shouldn't be used by friend classes
|
|||
eNotifyEditorObserversOfBefore,
|
||||
eNotifyEditorObserversOfCancel
|
||||
};
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void NotifyEditorObservers(NotificationForEditorObservers aNotification);
|
||||
|
||||
private:
|
||||
|
|
|
@ -1031,7 +1031,7 @@ EditorEventListener::HandleChangeComposition(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
TextEditor* textEditor = editorBase->AsTextEditor();
|
||||
RefPtr<TextEditor> textEditor = editorBase->AsTextEditor();
|
||||
return textEditor->OnCompositionChange(*aCompositionChangeEvent);
|
||||
}
|
||||
|
||||
|
@ -1050,7 +1050,7 @@ EditorEventListener::HandleEndComposition(
|
|||
MOZ_ASSERT(!aCompositionEndEvent->DefaultPrevented(),
|
||||
"eCompositionEnd shouldn't be cancelable");
|
||||
|
||||
TextEditor* textEditor = editorBase->AsTextEditor();
|
||||
RefPtr<TextEditor> textEditor = editorBase->AsTextEditor();
|
||||
textEditor->OnCompositionEnd(*aCompositionEndEvent);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,11 +63,14 @@ protected:
|
|||
|
||||
#ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH
|
||||
nsresult KeyDown(const WidgetKeyboardEvent* aKeyboardEvent);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult KeyUp(const WidgetKeyboardEvent* aKeyboardEvent);
|
||||
#endif
|
||||
nsresult KeyPress(WidgetKeyboardEvent* aKeyboardEvent);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult HandleChangeComposition(WidgetCompositionEvent* aCompositionEvent);
|
||||
nsresult HandleStartComposition(WidgetCompositionEvent* aCompositionEvent);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void HandleEndComposition(WidgetCompositionEvent* aCompositionEvent);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
virtual nsresult MouseDown(dom::MouseEvent* aMouseEvent);
|
||||
|
|
|
@ -5454,10 +5454,10 @@ HTMLEditor::GetPreferredIMEState(IMEState* aState)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIContent>
|
||||
HTMLEditor::GetInputEventTargetContent()
|
||||
already_AddRefed<Element>
|
||||
HTMLEditor::GetInputEventTargetElement()
|
||||
{
|
||||
nsCOMPtr<nsIContent> target = GetActiveEditingHost();
|
||||
RefPtr<Element> target = GetActiveEditingHost();
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -1778,7 +1778,7 @@ protected: // Shouldn't be used by friend classes
|
|||
*/
|
||||
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.
|
||||
|
|
|
@ -1460,10 +1460,10 @@ TextEditor::OnCompositionEnd(WidgetCompositionEvent& aCompositionEndEvent)
|
|||
NotifyEditorObservers(eNotifyEditorObserversOfEnd);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIContent>
|
||||
TextEditor::GetInputEventTargetContent()
|
||||
already_AddRefed<Element>
|
||||
TextEditor::GetInputEventTargetElement()
|
||||
{
|
||||
nsCOMPtr<nsIContent> target = do_QueryInterface(mEventTarget);
|
||||
nsCOMPtr<Element> target = do_QueryInterface(mEventTarget);
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,9 @@ public:
|
|||
|
||||
// If there are some good name to create non-virtual Undo()/Redo() methods,
|
||||
// we should create them and those methods should just run them.
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
NS_IMETHOD Undo(uint32_t aCount) final;
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
NS_IMETHOD Redo(uint32_t aCount) final;
|
||||
|
||||
NS_IMETHOD Cut() override;
|
||||
|
@ -205,6 +207,7 @@ public:
|
|||
* @param aCompositionChangeEvent eCompositionChange event which should
|
||||
* be handled in this editor.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult
|
||||
OnCompositionChange(WidgetCompositionEvent& aCompositionChangeEvent);
|
||||
|
||||
|
@ -213,6 +216,7 @@ public:
|
|||
* event and it's followed by eCompositionEnd event and after
|
||||
* OnCompositionChange() is called.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void OnCompositionEnd(WidgetCompositionEvent& aCompositionEndEvent);
|
||||
|
||||
/**
|
||||
|
@ -530,7 +534,7 @@ protected: // Shouldn't be used by friend classes
|
|||
*/
|
||||
bool EnsureComposition(WidgetCompositionEvent& aCompositionEvent);
|
||||
|
||||
virtual already_AddRefed<nsIContent> GetInputEventTargetContent() override;
|
||||
virtual already_AddRefed<Element> GetInputEventTargetElement() override;
|
||||
|
||||
protected:
|
||||
mutable nsCOMPtr<nsIDocumentEncoder> mCachedDocumentEncoder;
|
||||
|
|
|
@ -128,6 +128,7 @@ public:
|
|||
* @param aRepaint if true then force repaint (NOTE: we always force repaint currently)
|
||||
* @note This method might destroy |this|.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
virtual void SetFocus(bool aOn, bool aRepaint) override;
|
||||
|
||||
bool IsDroppedDown() { return mDroppedDown; }
|
||||
|
|
|
@ -459,11 +459,11 @@ nsFileControlFrame::DnDListener::HandleEvent(Event* aEvent)
|
|||
inputElement->SetFiles(fileList, true);
|
||||
}
|
||||
|
||||
nsContentUtils::DispatchTrustedEvent(inputElement->OwnerDoc(),
|
||||
static_cast<nsINode*>(inputElement),
|
||||
NS_LITERAL_STRING("input"),
|
||||
CanBubble::eYes,
|
||||
Cancelable::eNo);
|
||||
RefPtr<TextEditor> textEditor;
|
||||
DebugOnly<nsresult> rvIgnored =
|
||||
nsContentUtils::DispatchInputEvent(inputElement);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
nsContentUtils::DispatchTrustedEvent(inputElement->OwnerDoc(),
|
||||
static_cast<nsINode*>(inputElement),
|
||||
NS_LITERAL_STRING("change"),
|
||||
|
|
|
@ -123,7 +123,9 @@ protected:
|
|||
: 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,
|
||||
mozilla::dom::BlobImpl** aBlobImpl);
|
||||
|
|
|
@ -70,7 +70,10 @@ public:
|
|||
void SetFrame(nsListControlFrame *aFrame) { mFrame = aFrame; }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
// nsIDOMEventListener
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
NS_IMETHOD HandleEvent(Event* aEvent) override;
|
||||
|
||||
private:
|
||||
~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.
|
||||
nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
|
||||
NS_LITERAL_STRING("input"),
|
||||
CanBubble::eYes,
|
||||
Cancelable::eNo);
|
||||
DebugOnly<nsresult> rvIgnored = nsContentUtils::DispatchInputEvent(element);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rvIgnored),
|
||||
"Failed to dispatch input event");
|
||||
|
||||
// Dispatch the change event.
|
||||
nsContentUtils::DispatchTrustedEvent(content->OwnerDoc(), content,
|
||||
nsContentUtils::DispatchTrustedEvent(element->OwnerDoc(), element,
|
||||
NS_LITERAL_STRING("change"),
|
||||
CanBubble::eYes,
|
||||
Cancelable::eNo);
|
||||
|
|
|
@ -134,6 +134,7 @@ public:
|
|||
* Dispatch a DOM oninput and onchange event synchroniously.
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void FireOnInputAndOnChange();
|
||||
|
||||
/**
|
||||
|
@ -160,10 +161,13 @@ public:
|
|||
* @note These methods might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
nsresult MouseDown(mozilla::dom::Event* aMouseEvent);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult MouseUp(mozilla::dom::Event* aMouseEvent);
|
||||
nsresult MouseMove(mozilla::dom::Event* aMouseEvent);
|
||||
nsresult DragMove(mozilla::dom::Event* aMouseEvent);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult KeyDown(mozilla::dom::Event* aKeyEvent);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult KeyPress(mozilla::dom::Event* aKeyEvent);
|
||||
|
||||
/**
|
||||
|
@ -257,6 +261,7 @@ protected:
|
|||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
* Returns false if calling it destroyed |this|.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
bool UpdateSelection();
|
||||
|
||||
/**
|
||||
|
@ -271,6 +276,7 @@ protected:
|
|||
* Toggles (show/hide) the combobox dropdown menu.
|
||||
* @note This method might destroy the frame, pres shell and other objects.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void DropDownToggleKey(mozilla::dom::Event* aKeyEvent);
|
||||
|
||||
/**
|
||||
|
@ -378,6 +384,7 @@ protected:
|
|||
bool HandleListSelection(mozilla::dom::Event * aDOMEvent,
|
||||
int32_t selectedIndex);
|
||||
void InitSelectionRange(int32_t aClickedIndex);
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
void PostHandleKeyEvent(int32_t aNewIndex, uint32_t aCharCode,
|
||||
bool aIsShift, bool aIsControlOrMeta);
|
||||
|
||||
|
|
|
@ -35,10 +35,10 @@ function handleSubmit() { // eslint-disable-line no-unused-vars
|
|||
function handleInput(aEvent) {
|
||||
info("Input");
|
||||
is(input.value, expectedValue, "Check input value");
|
||||
todo(aEvent instanceof InputEvent,
|
||||
'"input" event should be dispatched with InputEvent interface');
|
||||
todo_is(aEvent.cancelable, false,
|
||||
'"input" event should be never cancelable');
|
||||
ok(aEvent instanceof InputEvent,
|
||||
'"input" event should be dispatched with InputEvent interface');
|
||||
is(aEvent.cancelable, false,
|
||||
'"input" event should be never cancelable');
|
||||
is(aEvent.bubbles, true,
|
||||
'"input" event should always bubble');
|
||||
input.removeEventListener("input", handleInput, true);
|
||||
|
|
|
@ -95,19 +95,12 @@ nsDoTestsForEditorWithAutoComplete.prototype = {
|
|||
if (aTest.inputEvents[i].todoInterfaceOnXUL && aInputEvents[i].target.tagName === "textbox") {
|
||||
this._todo_is(aInputEvents[i] instanceof this._window.InputEvent, true,
|
||||
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 {
|
||||
this._is(aInputEvents[i] instanceof this._window.InputEvent, true,
|
||||
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._description + ", " + aTest.description + ': "input" event should always bubble');
|
||||
}
|
||||
|
|
|
@ -510,7 +510,8 @@ private:
|
|||
mFlags.mBubbles = true;
|
||||
break;
|
||||
default:
|
||||
if (mMessage == eResize) {
|
||||
if (mMessage == eResize ||
|
||||
mMessage == eEditorInput) {
|
||||
mFlags.mCancelable = false;
|
||||
} else {
|
||||
mFlags.mCancelable = true;
|
||||
|
@ -614,7 +615,8 @@ public:
|
|||
|
||||
// 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.
|
||||
// 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;
|
||||
|
||||
// nsAtom isn't available on non-main thread due to unsafe. Therefore,
|
||||
|
|
Загрузка…
Ссылка в новой задаче