diff --git a/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form.html b/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form.html index ae65aed3186a2..547593a34681e 100644 --- a/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form.html +++ b/browser/extensions/formautofill/test/mochitest/creditCard/test_clear_form.html @@ -533,12 +533,29 @@ = false ; +let +element += document . querySelector ( selector ) +; +let +hadEditor += +SpecialPowers +. +wrap +( +element +) +. +hasEditor +; +element . addEventListener ( @@ -679,12 +696,7 @@ } ) ; -document -. -querySelector -( -selector -) +element . addEventListener ( @@ -697,16 +709,19 @@ = > { +if +( +hadEditor +) +{ todo ( beforeInputFired -' " beforeinput " event should -\ ' ve been @@ -715,9 +730,64 @@ " input " +on +< +{ +element +. +tagName +} +type += +" +{ +element +. +type +} +" +> +) +; +} +else +{ +ok +( +beforeInputFired +" +beforeinput +" +event +should ' +ve +been +fired +before +" +input +" +on +< +{ +element +. +tagName +} +type += +" +{ +element +. +type +} +" +> ) ; +} ok ( event diff --git a/browser/extensions/formautofill/test/mochitest/formautofill_common.js b/browser/extensions/formautofill/test/mochitest/formautofill_common.js index cb53b1e16078b..e7f177e26aa85 100644 --- a/browser/extensions/formautofill/test/mochitest/formautofill_common.js +++ b/browser/extensions/formautofill/test/mochitest/formautofill_common.js @@ -994,6 +994,18 @@ beforeInputFired = false ; +let +hadEditor += +SpecialPowers +. +wrap +( +element +) +. +hasEditor +; element . addEventListener @@ -1157,6 +1169,11 @@ text " ) { +if +( +hadEditor +) +{ todo ( beforeInputFired @@ -1182,6 +1199,35 @@ tagName } ) ; +} +else +{ +ok +( +beforeInputFired +" +beforeinput +" +event +should +' +ve +been +fired +before +" +input +" +event +on +{ +element +. +tagName +} +) +; +} ok ( event diff --git a/browser/extensions/formautofill/test/mochitest/test_multi_locale_CA_address_form.html b/browser/extensions/formautofill/test/mochitest/test_multi_locale_CA_address_form.html index a5ea088dca996..848468bdf2d9a 100644 --- a/browser/extensions/formautofill/test/mochitest/test_multi_locale_CA_address_form.html +++ b/browser/extensions/formautofill/test/mochitest/test_multi_locale_CA_address_form.html @@ -426,6 +426,18 @@ . value ; +let +hadEditor += +SpecialPowers +. +wrap +( +element +) +. +hasEditor +; element . addEventListener @@ -680,6 +692,11 @@ " ) { +if +( +hadEditor +) +{ todo ( beforeInputFired @@ -705,6 +722,35 @@ event ) ; +} +else +{ +ok +( +beforeInputFired +" +beforeinput +" +event +shoud +' +ve +been +fired +on +{ +element +. +name +} +before +" +input +" +event +) +; +} ok ( event diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 1a1d583ef6d91..db2f131b364d3 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -13409,6 +13409,22 @@ GetTextEditorFromState ) ; } +bool +HTMLInputElement +: +: +HasEditor +( +) +{ +return +! +! +GetTextEditorWithoutCreation +( +) +; +} TextEditor * HTMLInputElement diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h index 2a527e4fd7dd2..1e5c997523bcb 100644 --- a/dom/html/HTMLInputElement.h +++ b/dom/html/HTMLInputElement.h @@ -5143,7 +5143,10 @@ aExcludePassword GetEditor ( ) -is +and +HasEditor +( +) for webidl bindings @@ -5158,6 +5161,11 @@ GetEditor ) ; bool +HasEditor +( +) +; +bool IsInputEventTarget ( ) diff --git a/dom/html/HTMLTextAreaElement.h b/dom/html/HTMLTextAreaElement.h index 72debd9b223cb..bc7d6b5305fc1 100644 --- a/dom/html/HTMLTextAreaElement.h +++ b/dom/html/HTMLTextAreaElement.h @@ -1808,6 +1808,27 @@ GetTextEditor ; } bool +HasEditor +( +) +{ +MOZ_ASSERT +( +mState +) +; +return +! +! +mState +- +> +GetTextEditorWithoutCreation +( +) +; +} +bool IsInputEventTarget ( ) diff --git a/dom/html/TextControlState.cpp b/dom/html/TextControlState.cpp index b5d728ef53729..afbc276ea0f30 100644 --- a/dom/html/TextControlState.cpp +++ b/dom/html/TextControlState.cpp @@ -7732,6 +7732,91 @@ mEditActionHandled = false ; +/ +/ +Even +if +falling +back +to +TextControlState +: +: +SetValueWithoutTextEditor +( +) +/ +/ +due +to +editor +destruction +it +shouldn +' +t +dispatch +" +beforeinput +" +event +/ +/ +anymore +. +Therefore +we +should +mark +that +we +' +ve +already +dispatched +/ +/ +" +beforeinput +" +event +. +WillDispatchBeforeInputEvent +( +) +; +} +/ +* +* +* +WillDispatchBeforeInputEvent +( +) +is +called +immediately +before +dispatching +* +" +beforeinput +" +event +in +TextControlState +. +* +/ +void +WillDispatchBeforeInputEvent +( +) +{ +mBeforeInputEventHasBeenDispatched += +true +; } / * @@ -8208,6 +8293,16 @@ mEditActionHandled ; } bool +HasBeforeInputEventDispatched +( +) +const +{ +return +mBeforeInputEventHasBeenDispatched +; +} +bool Is ( TextControlAction @@ -8581,6 +8676,11 @@ mPreareEditorLater = false ; +bool +mBeforeInputEventHasBeenDispatched += +false +; } ; / @@ -16606,6 +16706,67 @@ commit the composition . +/ +/ +TODO +: +In +strictly +speaking +we +should +move +committing +composition +into +/ +/ +editor +because +if +" +beforeinput +" +for +this +setting +value +is +canceled +/ +/ +we +shouldn +' +t +commit +composition +. +However +in +Firefox +we +never +/ +/ +call +this +via +setUserInput +during +composition +. +Therefore +the +/ +/ +bug +must +not +be +reproducible +actually +. if ( aFlags @@ -18668,104 +18829,548 @@ dom_input_skip_cursor_move_for_same_value_set ) ) { -if -( -! -mValue -- -> -Assign +bool +handleSettingValue += +true +; +/ +/ +If +SetValue ( -aHandlingSetValue -. +) +call +is +nested GetSettingValue ( ) -fallible -) -) -{ -return -false -; -} +result +will +be / / -Since -we -have -no -editor +modified +. +So we -presumably -have -cached -selection -state +need +to +store +input +event +data +value +before +/ +/ +dispatching +beforeinput +event . -if -( -IsSelectionCached -( -) -) -{ -MOZ_ASSERT -( -AreFlagsNotDemandingContradictingMovements +nsString +inputEventData ( aHandlingSetValue . -GetSetValueFlags +GetSettingValue ( ) ) -) -; -SelectionProperties -& -props -= -GetSelectionProperties -( -) ; if ( +( aHandlingSetValue . GetSetValueFlags ( ) & -eSetValue_MoveCursorToEndIfValueChanged -) -{ -props -. -SetStart -( -aHandlingSetValue -. -GetSettingValue -( +eSetValue_BySetUserInput ) -. -Length +& +& +StaticPrefs +: +: +dom_input_events_beforeinput_enabled ( ) -) -; -props -. -SetEnd -( +& +& +! aHandlingSetValue . -GetSettingValue +HasBeforeInputEventDispatched ( ) -. +) +{ +/ +/ +This +probably +occurs +when +session +restorer +sets +the +old +value +with +/ +/ +setUserInput +. +If +so +we +need +to +dispatch +" +beforeinput +" +event +of +/ +/ +" +insertReplacementText +" +for +conforming +to +the +spec +. +However +the +/ +/ +spec +does +NOT +treat +the +session +restoring +case +. +Therefore +if +this +/ +/ +breaks +session +restorere +in +a +lot +of +web +apps +we +should +probably +/ +/ +stop +dispatching +it +or +make +it +non +- +cancelable +. +MOZ_ASSERT +( +aHandlingSetValue +. +GetTextControlElement +( +) +) +; +MOZ_ASSERT +( +! +aHandlingSetValue +. +GetSettingValue +( +) +. +IsVoid +( +) +) +; +aHandlingSetValue +. +WillDispatchBeforeInputEvent +( +) +; +nsEventStatus +status += +nsEventStatus_eIgnore +; +DebugOnly +< +nsresult +> +rvIgnored += +nsContentUtils +: +: +DispatchInputEvent +( +MOZ_KnownLive +( +aHandlingSetValue +. +GetTextControlElement +( +) +) +eEditorBeforeInput +EditorInputType +: +: +eInsertReplacementText +nullptr +nsContentUtils +: +: +InputEventOptions +( +inputEventData +) +& +status +) +; +NS_WARNING_ASSERTION +( +NS_SUCCEEDED +( +rvIgnored +) +" +Failed +to +dispatch +beforeinput +event +" +) +; +if +( +status += += +nsEventStatus_eConsumeNoDefault +) +{ +return +true +; +/ +/ +" +beforeinput +" +event +was +canceled +. +} +/ +/ +If +we +were +destroyed +by +" +beforeinput +" +event +listeners +probably +we +/ +/ +don +' +t +need +to +keep +handling +it +. +if +( +aHandlingSetValue +. +IsTextControlStateDestroyed +( +) +) +{ +return +true +; +} +/ +/ +Even +if +" +beforeinput +" +event +was +not +canceled +its +listeners +may +do +/ +/ +something +. +If +it +causes +creating +TextEditor +and +bind +this +to +a +/ +/ +frame +we +need +to +use +the +path +but +TextEditor +shouldn +' +t +fire +/ +/ +" +beforeinput +" +event +again +. +Therefore +we +need +to +prevent +editor +/ +/ +to +dispatch +it +. +if +( +mTextEditor +& +& +mBoundFrame +) +{ +AutoInputEventSuppresser +suppressInputEvent +( +mTextEditor +) +; +if +( +! +SetValueWithTextEditor +( +aHandlingSetValue +) +) +{ +return +false +; +} +/ +/ +If +we +were +destroyed +by +" +beforeinput +" +event +listeners +probably +we +/ +/ +don +' +t +need +to +keep +handling +it +. +if +( +aHandlingSetValue +. +IsTextControlStateDestroyed +( +) +) +{ +return +true +; +} +handleSettingValue += +false +; +} +} +if +( +handleSettingValue +) +{ +if +( +! +mValue +- +> +Assign +( +aHandlingSetValue +. +GetSettingValue +( +) +fallible +) +) +{ +return +false +; +} +/ +/ +Since +we +have +no +editor +we +presumably +have +cached +selection +state +. +if +( +IsSelectionCached +( +) +) +{ +MOZ_ASSERT +( +AreFlagsNotDemandingContradictingMovements +( +aHandlingSetValue +. +GetSetValueFlags +( +) +) +) +; +SelectionProperties +& +props += +GetSelectionProperties +( +) +; +if +( +aHandlingSetValue +. +GetSetValueFlags +( +) +& +eSetValue_MoveCursorToEndIfValueChanged +) +{ +props +. +SetStart +( +aHandlingSetValue +. +GetSettingValue +( +) +. +Length +( +) +) +; +props +. +SetEnd +( +aHandlingSetValue +. +GetSettingValue +( +) +. Length ( ) @@ -18914,6 +19519,7 @@ true ) ; } +} / / If @@ -19066,11 +19672,7 @@ nsContentUtils : InputEventOptions ( -aHandlingSetValue -. -GetSettingValue -( -) +inputEventData ) ) ; diff --git a/dom/html/test/forms/test_MozEditableElement_setUserInput.html b/dom/html/test/forms/test_MozEditableElement_setUserInput.html index e80f79822b5cd..84dbd70367f7a 100644 --- a/dom/html/test/forms/test_MozEditableElement_setUserInput.html +++ b/dom/html/test/forms/test_MozEditableElement_setUserInput.html @@ -1989,6 +1989,29 @@ ; } else +if +( +test +. +element += += += +" +textarea +" +| +| +test +. +type += += += +" +number +" +) { todo_is ( @@ -2029,6 +2052,47 @@ ) ; } +else +{ +is +( +beforeInputEvents +. +length +1 +Only +one +" +beforeinput +" +event +should +be +dispatched +when +setUserInput +( +" +{ +test +. +input +. +before +} +" +) +is +called +before +{ +tag +} +gets +focus +) +; +} if ( ! diff --git a/dom/html/test/forms/test_input_setting_value.html b/dom/html/test/forms/test_input_setting_value.html index 4e4ee2c0f15e3..f564cab2d4a6e 100644 --- a/dom/html/test/forms/test_input_setting_value.html +++ b/dom/html/test/forms/test_input_setting_value.html @@ -154,11 +154,37 @@ . waitForFocus ( +async ( ) = > { +await +SpecialPowers +. +pushPrefEnv +( +{ +set +: +[ +[ +" +dom +. +input_events +. +beforeinput +. +enabled +" +true +] +] +} +) +; let input = @@ -4424,11 +4450,7 @@ input ) . -editor -! -= -= -null +hasEditor { description } @@ -4799,11 +4821,7 @@ input ) . -editor -! -= -= -null +hasEditor { description } @@ -4895,6 +4913,2135 @@ editor ) ; +function +testSettingValueFromBeforeInput +( +aWithEditor +aPreventDefaultOfBeforeInput +) +{ +let +beforeInputEvents += +[ +] +; +let +inputEvents += +[ +] +; +function +recordEvent +( +aEvent +) +{ +if +( +aEvent +. +type += += += +" +beforeinput +" +) +{ +beforeInputEvents +. +push +( +aEvent +) +; +} +else +{ +inputEvents +. +push +( +aEvent +) +; +} +} +let +condition += +( +{ +aWithEditor +? +" +with +editor +" +: +" +without +editor +" +} +{ +aPreventDefaultOfBeforeInput +? +' +and +canceling +" +beforeinput +" +event +' +: +" +" +} +) +; +function +Reset +( +) +{ +beforeInputEvents += +[ +] +; +inputEvents += +[ +] +; +if +( +SpecialPowers +. +wrap +( +input +) +. +hasEditor +! += +aWithEditor +) +{ +if +( +aWithEditor +) +{ +input +. +blur +( +) +; +input +. +focus +( +) +; +/ +/ +Associate +TextEditor +with +input +if +( +! +SpecialPowers +. +wrap +( +input +) +. +hasEditor +) +{ +ok +( +false +{ +description +} +Failed +to +associate +TextEditor +with +the +input +{ +condition +} +) +; +return +false +; +} +} +else +{ +input +. +blur +( +) +; +input +. +type += +" +button +" +; +input +. +type += +" +text +" +; +if +( +SpecialPowers +. +wrap +( +input +) +. +hasEditor +) +{ +ok +( +false +{ +description +} +Failed +to +disassociate +TextEditor +from +the +input +{ +condition +} +) +; +return +false +; +} +} +} +return +true +; +} +description += +Setting +value +from +" +beforeinput +" +event +listener +whose +inputType +is +" +insertReplacementText +" +{ +condition +} +: +; +input +. +value += +" +abc +" +; +if +( +! +Reset +( +) +) +{ +return +; +} +input +. +addEventListener +( +" +beforeinput +" +( +aEvent +) += +> +{ +is +( +aEvent +. +inputType +" +insertReplacementText +" +{ +description +} +inputType +of +" +beforeinput +" +event +should +be +" +insertReplacementText +" +) +; +ok +( +aEvent +. +cancelable +{ +description +} +" +beforeinput +" +event +should +be +cancelable +) +; +is +( +input +. +value +" +abc +" +{ +description +} +The +value +shouldn +' +t +have +been +modified +yet +at +" +beforeinput +" +event +listener +) +; +input +. +addEventListener +( +" +beforeinput +" +recordEvent +) +; +input +. +addEventListener +( +" +input +" +recordEvent +) +; +input +. +value += +" +hig +" +; +if +( +aPreventDefaultOfBeforeInput +) +{ +aEvent +. +preventDefault +( +) +; +} +} +{ +once +: +true +} +) +; +SpecialPowers +. +wrap +( +input +) +. +setUserInput +( +" +def +" +) +; +is +( +beforeInputEvents +. +length +0 +{ +description +} +" +beforeinput +" +event +shouldn +' +t +be +fired +again +) +; +if +( +aPreventDefaultOfBeforeInput +) +{ +is +( +input +. +value +" +hig +" +{ +description +} +The +value +should +be +set +to +the +specified +value +in +" +beforeinput +" +event +listener +since +" +beforeinput +" +was +canceled +) +; +is +( +inputEvents +. +length +0 +{ +description +} +" +input +" +event +shouldn +' +t +be +fired +since +" +beforeinput +" +was +canceled +) +; +} +else +{ +/ +/ +XXX +This +result +is +different +from +Chrome +( +verified +with +spellchecker +) +. +/ +/ +Chrome +inserts +the +new +text +to +current +value +and +selected +range +. +/ +/ +It +might +be +reasonable +but +we +don +' +t +touch +this +for +now +since +it +/ +/ +requires +a +lot +of +changes +. +is +( +input +. +value +" +hig +" +{ +description +} +The +value +should +be +set +to +the +specified +value +in +" +beforeinput +" +event +listener +since +the +event +target +was +already +modified +) +; +is +( +inputEvents +. +length +1 +{ +description +} +" +input +" +event +should +be +fired +) +; +if +( +inputEvents +. +length +> +0 +) +{ +is +( +inputEvents +[ +0 +] +. +inputType +" +insertReplacementText +" +{ +description +} +inputType +of +" +input +" +event +should +be +" +insertReplacementText +" +) +; +is +( +inputEvents +[ +0 +] +. +data +" +def +" +{ +description +} +data +of +" +input +" +event +should +be +the +value +specified +by +setUserInput +( +) +) +; +} +} +input +. +removeEventListener +( +" +beforeinput +" +recordEvent +) +; +input +. +removeEventListener +( +" +input +" +recordEvent +) +; +description += +Setting +value +from +" +beforeinput +" +event +listener +whose +inputType +is +" +insertReplacementText +" +and +changing +the +type +to +" +button +" +{ +condition +} +: +; +input +. +value += +" +abc +" +; +if +( +! +Reset +( +) +) +{ +return +; +} +input +. +addEventListener +( +" +beforeinput +" +( +aEvent +) += +> +{ +is +( +aEvent +. +inputType +" +insertReplacementText +" +{ +description +} +inputType +of +" +beforeinput +" +event +should +be +" +insertReplacementText +" +) +; +ok +( +aEvent +. +cancelable +{ +description +} +" +beforeinput +" +event +should +be +cancelable +) +; +is +( +input +. +value +" +abc +" +{ +description +} +The +value +shouldn +' +t +have +been +modified +yet +at +" +beforeinput +" +event +listener +) +; +input +. +addEventListener +( +" +beforeinput +" +recordEvent +) +; +input +. +addEventListener +( +" +input +" +recordEvent +) +; +input +. +value += +" +hig +" +; +input +. +type += +" +button +" +; +if +( +aPreventDefaultOfBeforeInput +) +{ +aEvent +. +preventDefault +( +) +; +} +} +{ +once +: +true +} +) +; +SpecialPowers +. +wrap +( +input +) +. +setUserInput +( +" +def +" +) +; +is +( +beforeInputEvents +. +length +0 +{ +description +} +" +beforeinput +" +event +shouldn +' +t +be +fired +again +) +; +if +( +aPreventDefaultOfBeforeInput +) +{ +is +( +input +. +value +" +hig +" +{ +description +} +The +value +should +be +set +to +the +specified +value +in +" +beforeinput +" +event +listener +since +" +beforeinput +" +was +canceled +) +; +is +( +inputEvents +. +length +0 +{ +description +} +" +input +" +event +shouldn +' +t +be +fired +since +" +beforeinput +" +was +canceled +) +; +} +else +{ +/ +/ +XXX +This +result +is +same +as +Chrome +( +verified +with +spellchecker +) +. +/ +/ +But +this +behavior +is +not +consistent +with +just +setting +the +value +on +Chrome +. +is +( +input +. +value +" +hig +" +{ +description +} +The +value +should +be +set +to +the +specified +value +in +" +beforeinput +" +event +listener +since +the +event +target +was +already +modified +) +; +/ +/ +Same +as +Chrome +is +( +inputEvents +. +length +0 +{ +description +} +" +input +" +event +shouldn +' +t +be +fired +since +the +input +element +' +s +type +is +changed +) +; +} +input +. +type += +" +text +" +; +input +. +removeEventListener +( +" +beforeinput +" +recordEvent +) +; +input +. +removeEventListener +( +" +input +" +recordEvent +) +; +description += +Setting +value +from +" +beforeinput +" +event +listener +whose +inputType +is +" +insertReplacementText +" +and +destroying +the +frame +{ +condition +} +: +; +input +. +value += +" +abc +" +; +if +( +! +Reset +( +) +) +{ +return +; +} +input +. +addEventListener +( +" +beforeinput +" +( +aEvent +) += +> +{ +is +( +aEvent +. +inputType +" +insertReplacementText +" +{ +description +} +inputType +of +" +beforeinput +" +event +should +be +" +insertReplacementText +" +) +; +ok +( +aEvent +. +cancelable +{ +description +} +" +beforeinput +" +event +should +be +cancelable +) +; +is +( +input +. +value +" +abc +" +{ +description +} +The +value +shouldn +' +t +have +been +modified +yet +at +" +beforeinput +" +event +listener +) +; +input +. +addEventListener +( +" +beforeinput +" +recordEvent +) +; +input +. +addEventListener +( +" +input +" +recordEvent +) +; +input +. +value += +" +hig +" +; +input +. +style +. +display += +" +none +" +; +if +( +aPreventDefaultOfBeforeInput +) +{ +aEvent +. +preventDefault +( +) +; +} +} +{ +once +: +true +} +) +; +SpecialPowers +. +wrap +( +input +) +. +setUserInput +( +" +def +" +) +; +is +( +beforeInputEvents +. +length +0 +{ +description +} +" +beforeinput +" +event +shouldn +' +t +be +fired +again +) +; +if +( +aPreventDefaultOfBeforeInput +) +{ +is +( +input +. +value +" +hig +" +{ +description +} +The +value +should +be +set +to +the +specified +value +in +" +beforeinput +" +event +listener +since +" +beforeinput +" +was +canceled +) +; +is +( +inputEvents +. +length +0 +{ +description +} +" +input +" +event +shouldn +' +t +be +fired +since +" +beforeinput +" +was +canceled +) +; +} +else +{ +/ +/ +XXX +This +result +is +same +as +Chrome +( +verified +with +spellchecker +) +. +/ +/ +But +this +behavior +is +not +consistent +with +just +setting +the +value +on +Chrome +. +is +( +input +. +value +" +hig +" +{ +description +} +The +value +should +be +set +to +the +specified +value +in +" +beforeinput +" +event +listener +since +the +event +target +was +already +modified +) +; +/ +/ +Different +from +Chrome +is +( +inputEvents +. +length +1 +{ +description +} +" +input +" +event +should +be +fired +even +if +the +frame +of +target +is +destroyed +) +; +if +( +inputEvents +. +length +> +0 +) +{ +is +( +inputEvents +[ +0 +] +. +inputType +" +insertReplacementText +" +{ +description +} +inputType +of +" +input +" +event +should +be +" +insertReplacementText +" +) +; +is +( +inputEvents +[ +0 +] +. +data +" +def +" +{ +description +} +data +of +" +input +" +event +should +be +the +value +specified +by +setUserInput +( +) +) +; +} +} +input +. +style +. +display += +" +inline +" +; +input +. +removeEventListener +( +" +beforeinput +" +recordEvent +) +; +input +. +removeEventListener +( +" +input +" +recordEvent +) +; +if +( +aWithEditor +) +{ +return +; +} +description += +Setting +value +from +" +beforeinput +" +event +listener +whose +inputType +is +" +insertReplacementText +and +create +editor +" +{ +condition +} +: +; +input +. +value += +" +abc +" +; +if +( +! +Reset +( +) +) +{ +return +; +} +input +. +addEventListener +( +" +beforeinput +" +( +aEvent +) += +> +{ +is +( +aEvent +. +inputType +" +insertReplacementText +" +{ +description +} +inputType +of +" +beforeinput +" +event +should +be +" +insertReplacementText +" +) +; +ok +( +aEvent +. +cancelable +{ +description +} +" +beforeinput +" +event +should +be +cancelable +) +; +is +( +input +. +value +" +abc +" +{ +description +} +The +value +shouldn +' +t +have +been +modified +yet +at +" +beforeinput +" +event +listener +) +; +input +. +addEventListener +( +" +beforeinput +" +recordEvent +) +; +input +. +addEventListener +( +" +input +" +recordEvent +) +; +input +. +value += +" +hig +" +; +input +. +focus +( +) +; +if +( +aPreventDefaultOfBeforeInput +) +{ +aEvent +. +preventDefault +( +) +; +} +} +{ +once +: +true +} +) +; +SpecialPowers +. +wrap +( +input +) +. +setUserInput +( +" +def +" +) +; +is +( +beforeInputEvents +. +length +0 +{ +description +} +" +beforeinput +" +event +shouldn +' +t +be +fired +again +) +; +if +( +aPreventDefaultOfBeforeInput +) +{ +is +( +input +. +value +" +hig +" +{ +description +} +The +value +should +be +set +to +the +specified +value +in +" +beforeinput +" +event +listener +since +" +beforeinput +" +was +canceled +) +; +is +( +inputEvents +. +length +0 +{ +description +} +" +input +" +event +shouldn +' +t +be +fired +since +" +beforeinput +" +was +canceled +) +; +} +else +{ +/ +/ +XXX +This +result +is +different +from +Chrome +( +verified +with +spellchecker +) +. +/ +/ +Chrome +inserts +the +new +text +to +current +value +and +selected +range +. +/ +/ +It +might +be +reasonable +but +we +don +' +t +touch +this +for +now +since +it +/ +/ +requires +a +lot +of +changes +. +is +( +input +. +value +" +hig +" +{ +description +} +The +value +should +be +set +to +the +specified +value +in +" +beforeinput +" +event +listener +since +the +event +target +was +already +modified +) +; +is +( +inputEvents +. +length +1 +{ +description +} +" +input +" +event +should +be +fired +) +; +if +( +inputEvents +. +length +> +0 +) +{ +is +( +inputEvents +[ +0 +] +. +inputType +" +insertReplacementText +" +{ +description +} +inputType +of +" +input +" +event +should +be +" +insertReplacementText +" +) +; +is +( +inputEvents +[ +0 +] +. +data +" +def +" +{ +description +} +data +of +" +input +" +event +should +be +the +value +specified +by +setUserInput +( +) +) +; +} +} +input +. +removeEventListener +( +" +beforeinput +" +recordEvent +) +; +input +. +removeEventListener +( +" +input +" +recordEvent +) +; +} +/ +/ +testSettingValueFromBeforeInput +( +true +true +) +; +/ +/ +testSettingValueFromBeforeInput +( +true +false +) +; +testSettingValueFromBeforeInput +( +false +true +) +; +testSettingValueFromBeforeInput +( +false +false +) +; SimpleTest . finish diff --git a/dom/webidl/HTMLInputElement.webidl b/dom/webidl/HTMLInputElement.webidl index 90b029322acc0..377464c3f3f17 100644 --- a/dom/webidl/HTMLInputElement.webidl +++ b/dom/webidl/HTMLInputElement.webidl @@ -1146,6 +1146,42 @@ interface mixin MozEditableElement { +/ +/ +Returns +an +nsIEditor +instance +which +is +associated +with +the +element +. +/ +/ +If +the +element +can +be +associated +with +an +editor +but +not +yet +created +/ +/ +this +creates +new +one +automatically +. [ Pure ChromeOnly @@ -1158,6 +1194,33 @@ editor ; / / +Returns +true +if +an +nsIEditor +instance +has +already +been +associated +with +/ +/ +the +element +. +[ +Pure +ChromeOnly +] +readonly +attribute +boolean +hasEditor +; +/ +/ This is set