summaryrefslogtreecommitdiff
path: root/dom/html/test
diff options
context:
space:
mode:
Diffstat (limited to 'dom/html/test')
-rw-r--r--dom/html/test/347174transform.xsl41
-rw-r--r--dom/html/test/347174transformable.xml3
-rw-r--r--dom/html/test/allowMedia.sjs12
-rw-r--r--dom/html/test/browser.ini25
-rw-r--r--dom/html/test/browser_DOMDocElementInserted.js24
-rw-r--r--dom/html/test/browser_bug1081537.js11
-rw-r--r--dom/html/test/browser_bug1108547.js113
-rw-r--r--dom/html/test/browser_bug592641.js61
-rw-r--r--dom/html/test/browser_bug649778.js82
-rw-r--r--dom/html/test/browser_content_contextmenu_userinput.js50
-rw-r--r--dom/html/test/browser_fullscreen-api-keys.js170
-rw-r--r--dom/html/test/browser_fullscreen-contextmenu-esc.js107
-rw-r--r--dom/html/test/bug100533_iframe.html8
-rw-r--r--dom/html/test/bug100533_load.html14
-rw-r--r--dom/html/test/bug1260704_iframe.html38
-rw-r--r--dom/html/test/bug1260704_iframe_empty.html15
-rw-r--r--dom/html/test/bug1292522_iframe.html10
-rw-r--r--dom/html/test/bug1292522_page.html14
-rw-r--r--dom/html/test/bug1315146-iframe.html4
-rw-r--r--dom/html/test/bug1315146-main.html15
-rw-r--r--dom/html/test/bug196523-subframe.html37
-rw-r--r--dom/html/test/bug199692-nested-d2.html14
-rw-r--r--dom/html/test/bug199692-nested.html15
-rw-r--r--dom/html/test/bug199692-popup.html188
-rw-r--r--dom/html/test/bug199692-scrolled.html34
-rw-r--r--dom/html/test/bug242709_iframe.html20
-rw-r--r--dom/html/test/bug242709_load.html11
-rw-r--r--dom/html/test/bug277724_iframe1.html28
-rw-r--r--dom/html/test/bug277724_iframe2.xhtml27
-rw-r--r--dom/html/test/bug277890_iframe.html20
-rw-r--r--dom/html/test/bug277890_load.html11
-rw-r--r--dom/html/test/bug340800_iframe.txt4
-rw-r--r--dom/html/test/bug369370-popup.pngbin0 -> 4073 bytes
-rw-r--r--dom/html/test/bug372098-link-target.html7
-rw-r--r--dom/html/test/bug392567.jarbin0 -> 120 bytes
-rw-r--r--dom/html/test/bug392567.jar^headers^1
-rw-r--r--dom/html/test/bug441930_iframe.html27
-rw-r--r--dom/html/test/bug445004-inner.html14
-rw-r--r--dom/html/test/bug445004-inner.js23
-rw-r--r--dom/html/test/bug445004-outer-abs.html11
-rw-r--r--dom/html/test/bug445004-outer-rel.html11
-rw-r--r--dom/html/test/bug445004-outer-write.html11
-rw-r--r--dom/html/test/bug446483-iframe.html10
-rw-r--r--dom/html/test/bug448564-echo.sjs6
-rw-r--r--dom/html/test/bug448564-iframe-1.html16
-rw-r--r--dom/html/test/bug448564-iframe-2.html16
-rw-r--r--dom/html/test/bug448564-iframe-3.html16
-rw-r--r--dom/html/test/bug448564-submit.js4
-rw-r--r--dom/html/test/bug499092.html6
-rw-r--r--dom/html/test/bug499092.xml4
-rw-r--r--dom/html/test/bug514856_iframe.html21
-rw-r--r--dom/html/test/bug592641_img.jpgbin0 -> 42018 bytes
-rw-r--r--dom/html/test/bug649134/file_bug649134-1.sjs12
-rw-r--r--dom/html/test/bug649134/file_bug649134-2.sjs12
-rw-r--r--dom/html/test/bug649134/index.html3
-rw-r--r--dom/html/test/chrome.ini10
-rw-r--r--dom/html/test/dummy_page.html10
-rw-r--r--dom/html/test/file_anchor_ping.html13
-rw-r--r--dom/html/test/file_bug1108547-1.html4
-rw-r--r--dom/html/test/file_bug1108547-2.html6
-rw-r--r--dom/html/test/file_bug1108547-3.html5
-rw-r--r--dom/html/test/file_bug1166138_1x.pngbin0 -> 91 bytes
-rw-r--r--dom/html/test/file_bug1166138_2x.pngbin0 -> 100 bytes
-rw-r--r--dom/html/test/file_bug1166138_def.pngbin0 -> 85 bytes
-rw-r--r--dom/html/test/file_bug1260704.pngbin0 -> 91 bytes
-rw-r--r--dom/html/test/file_bug209275_1.html28
-rw-r--r--dom/html/test/file_bug209275_2.html23
-rw-r--r--dom/html/test/file_bug209275_3.html23
-rw-r--r--dom/html/test/file_bug297761.html13
-rw-r--r--dom/html/test/file_bug417760.pngbin0 -> 1991 bytes
-rw-r--r--dom/html/test/file_bug649778.html11
-rw-r--r--dom/html/test/file_bug649778.html^headers^1
-rw-r--r--dom/html/test/file_bug871161-1.html16
-rw-r--r--dom/html/test/file_bug871161-2.html14
-rw-r--r--dom/html/test/file_bug893537.html9
-rw-r--r--dom/html/test/file_content_contextmenu.html20
-rw-r--r--dom/html/test/file_cookiemanager.js20
-rw-r--r--dom/html/test/file_formSubmission_img.jpgbin0 -> 2711 bytes
-rw-r--r--dom/html/test/file_formSubmission_text.txt1
-rw-r--r--dom/html/test/file_fullscreen-api-keys.html32
-rw-r--r--dom/html/test/file_fullscreen-api.html317
-rw-r--r--dom/html/test/file_fullscreen-backdrop.html107
-rw-r--r--dom/html/test/file_fullscreen-denied-inner.html24
-rw-r--r--dom/html/test/file_fullscreen-denied.html129
-rw-r--r--dom/html/test/file_fullscreen-esc-exit-inner.html58
-rw-r--r--dom/html/test/file_fullscreen-esc-exit.html63
-rw-r--r--dom/html/test/file_fullscreen-hidden.html55
-rw-r--r--dom/html/test/file_fullscreen-lenient-setters.html61
-rw-r--r--dom/html/test/file_fullscreen-multiple-inner.html28
-rw-r--r--dom/html/test/file_fullscreen-multiple.html64
-rw-r--r--dom/html/test/file_fullscreen-navigation.html52
-rw-r--r--dom/html/test/file_fullscreen-nested.html120
-rw-r--r--dom/html/test/file_fullscreen-plugins.html160
-rw-r--r--dom/html/test/file_fullscreen-prefixed.html153
-rw-r--r--dom/html/test/file_fullscreen-rollback.html128
-rw-r--r--dom/html/test/file_fullscreen-scrollbar.html126
-rw-r--r--dom/html/test/file_fullscreen-selector.html178
-rw-r--r--dom/html/test/file_fullscreen-svg-element.html49
-rw-r--r--dom/html/test/file_fullscreen-top-layer.html160
-rw-r--r--dom/html/test/file_fullscreen-unprefix-disabled-inner.html96
-rw-r--r--dom/html/test/file_fullscreen-unprefix-disabled.html34
-rw-r--r--dom/html/test/file_fullscreen-utils.js82
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if1.html13
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if10.html12
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if11.html23
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if12.html23
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if13.html13
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if14.html34
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if15.html33
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if16.html25
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if17.html27
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if18.html26
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if19.html21
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if2.html21
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if3.html24
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if4.html30
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if5.html22
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if6.html21
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if7.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if8.html26
-rw-r--r--dom/html/test/file_iframe_sandbox_a_if9.html18
-rw-r--r--dom/html/test/file_iframe_sandbox_b_if1.html11
-rw-r--r--dom/html/test/file_iframe_sandbox_b_if2.html49
-rw-r--r--dom/html/test/file_iframe_sandbox_b_if3.html92
-rw-r--r--dom/html/test/file_iframe_sandbox_c_if1.html35
-rw-r--r--dom/html/test/file_iframe_sandbox_c_if2.html23
-rw-r--r--dom/html/test/file_iframe_sandbox_c_if3.html26
-rw-r--r--dom/html/test/file_iframe_sandbox_c_if4.html45
-rw-r--r--dom/html/test/file_iframe_sandbox_c_if5.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_c_if6.html24
-rw-r--r--dom/html/test/file_iframe_sandbox_c_if7.html27
-rw-r--r--dom/html/test/file_iframe_sandbox_c_if8.html27
-rw-r--r--dom/html/test/file_iframe_sandbox_c_if9.html17
-rw-r--r--dom/html/test/file_iframe_sandbox_close.html3
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if1.html19
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if10.html17
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if11.html26
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if12.html16
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if13.html35
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if14.html35
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if15.html14
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if16.html22
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if17.html24
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if18.html33
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if19.html13
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if2.html28
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if20.html25
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if21.html14
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if22.html25
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if23.html61
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if3.html13
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if4.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if5.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if6.html19
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if7.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if8.html18
-rw-r--r--dom/html/test/file_iframe_sandbox_d_if9.html17
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if1.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if10.html19
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if11.html24
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if12.html19
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if13.html19
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if14.html24
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if15.html17
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if16.html27
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if2.html12
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if3.html11
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if4.html11
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if5.html19
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if6.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if7.html17
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if8.html23
-rw-r--r--dom/html/test/file_iframe_sandbox_e_if9.html19
-rw-r--r--dom/html/test/file_iframe_sandbox_f_if1.html13
-rw-r--r--dom/html/test/file_iframe_sandbox_f_if2.html11
-rw-r--r--dom/html/test/file_iframe_sandbox_f_if2.html^headers^1
-rw-r--r--dom/html/test/file_iframe_sandbox_fail.js1
-rw-r--r--dom/html/test/file_iframe_sandbox_form_fail.html19
-rw-r--r--dom/html/test/file_iframe_sandbox_form_pass.html17
-rw-r--r--dom/html/test/file_iframe_sandbox_g_if1.html60
-rw-r--r--dom/html/test/file_iframe_sandbox_h_if1.html34
-rw-r--r--dom/html/test/file_iframe_sandbox_j_if1.html30
-rw-r--r--dom/html/test/file_iframe_sandbox_j_if2.html28
-rw-r--r--dom/html/test/file_iframe_sandbox_j_if3.html27
-rw-r--r--dom/html/test/file_iframe_sandbox_k_if1.html47
-rw-r--r--dom/html/test/file_iframe_sandbox_k_if2.html50
-rw-r--r--dom/html/test/file_iframe_sandbox_k_if3.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_k_if4.html34
-rw-r--r--dom/html/test/file_iframe_sandbox_k_if5.html33
-rw-r--r--dom/html/test/file_iframe_sandbox_k_if6.html21
-rw-r--r--dom/html/test/file_iframe_sandbox_k_if7.html26
-rw-r--r--dom/html/test/file_iframe_sandbox_k_if8.html36
-rw-r--r--dom/html/test/file_iframe_sandbox_k_if9.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_navigation_fail.html17
-rw-r--r--dom/html/test/file_iframe_sandbox_navigation_pass.html17
-rw-r--r--dom/html/test/file_iframe_sandbox_navigation_start.html11
-rw-r--r--dom/html/test/file_iframe_sandbox_open_window_fail.html19
-rw-r--r--dom/html/test/file_iframe_sandbox_open_window_pass.html25
-rw-r--r--dom/html/test/file_iframe_sandbox_pass.js1
-rw-r--r--dom/html/test/file_iframe_sandbox_redirect.html2
-rw-r--r--dom/html/test/file_iframe_sandbox_redirect.html^headers^2
-rw-r--r--dom/html/test/file_iframe_sandbox_redirect_target.html9
-rw-r--r--dom/html/test/file_iframe_sandbox_refresh.html2
-rw-r--r--dom/html/test/file_iframe_sandbox_refresh.html^headers^1
-rw-r--r--dom/html/test/file_iframe_sandbox_top_navigation_fail.html18
-rw-r--r--dom/html/test/file_iframe_sandbox_top_navigation_pass.html18
-rw-r--r--dom/html/test/file_iframe_sandbox_window_form_fail.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_window_form_pass.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_window_navigation_fail.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_window_navigation_pass.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html24
-rw-r--r--dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html20
-rw-r--r--dom/html/test/file_iframe_sandbox_worker.js3
-rw-r--r--dom/html/test/file_ignoreuserfocus.html10
-rw-r--r--dom/html/test/file_imports_basics.html22
-rw-r--r--dom/html/test/file_imports_redirect.html5
-rw-r--r--dom/html/test/file_imports_redirect.html^headers^2
-rw-r--r--dom/html/test/file_imports_redirected.html6
-rw-r--r--dom/html/test/file_mozaudiochannel.html91
-rw-r--r--dom/html/test/file_srcdoc-2.html10
-rw-r--r--dom/html/test/file_srcdoc.html16
-rw-r--r--dom/html/test/file_window_open_close_inner.html7
-rw-r--r--dom/html/test/file_window_open_close_outer.html5
-rw-r--r--dom/html/test/formData_test.js212
-rw-r--r--dom/html/test/formData_worker.js19
-rw-r--r--dom/html/test/formSubmission_chrome.js6
-rw-r--r--dom/html/test/form_submit_server.sjs71
-rw-r--r--dom/html/test/forms/chrome.ini5
-rw-r--r--dom/html/test/forms/mochitest.ini107
-rw-r--r--dom/html/test/forms/save_restore_radio_groups.sjs50
-rw-r--r--dom/html/test/forms/submit_invalid_file.sjs14
-rw-r--r--dom/html/test/forms/test_autocompleteinfo.html121
-rw-r--r--dom/html/test/forms/test_bug1039548.html55
-rw-r--r--dom/html/test/forms/test_bug1283915.html67
-rw-r--r--dom/html/test/forms/test_bug1286509.html49
-rw-r--r--dom/html/test/forms/test_button_attributes_reflection.html137
-rw-r--r--dom/html/test/forms/test_change_event.html287
-rw-r--r--dom/html/test/forms/test_datalist_element.html118
-rw-r--r--dom/html/test/forms/test_form_attribute-1.html473
-rw-r--r--dom/html/test/forms/test_form_attribute-2.html53
-rw-r--r--dom/html/test/forms/test_form_attribute-3.html68
-rw-r--r--dom/html/test/forms/test_form_attribute-4.html48
-rw-r--r--dom/html/test/forms/test_form_attributes_reflection.html88
-rw-r--r--dom/html/test/forms/test_form_named_getter_dynamic.html54
-rw-r--r--dom/html/test/forms/test_formaction_attribute.html176
-rw-r--r--dom/html/test/forms/test_formnovalidate_attribute.html142
-rw-r--r--dom/html/test/forms/test_input_attributes_reflection.html275
-rw-r--r--dom/html/test/forms/test_input_autocomplete.html106
-rw-r--r--dom/html/test/forms/test_input_color_input_change_events.html120
-rw-r--r--dom/html/test/forms/test_input_color_picker_initial.html79
-rw-r--r--dom/html/test/forms/test_input_color_picker_popup.html140
-rw-r--r--dom/html/test/forms/test_input_color_picker_update.html87
-rw-r--r--dom/html/test/forms/test_input_datetime_focus_blur.html58
-rw-r--r--dom/html/test/forms/test_input_datetime_tabindex.html72
-rw-r--r--dom/html/test/forms/test_input_defaultValue.html81
-rw-r--r--dom/html/test/forms/test_input_email.html237
-rw-r--r--dom/html/test/forms/test_input_event.html234
-rw-r--r--dom/html/test/forms/test_input_file_picker.html267
-rw-r--r--dom/html/test/forms/test_input_list_attribute.html253
-rw-r--r--dom/html/test/forms/test_input_number_data.js38
-rw-r--r--dom/html/test/forms/test_input_number_focus.html54
-rw-r--r--dom/html/test/forms/test_input_number_key_events.html244
-rw-r--r--dom/html/test/forms/test_input_number_l10n.html75
-rw-r--r--dom/html/test/forms/test_input_number_mouse_events.html196
-rw-r--r--dom/html/test/forms/test_input_number_rounding.html120
-rw-r--r--dom/html/test/forms/test_input_number_validation.html143
-rw-r--r--dom/html/test/forms/test_input_radio_indeterminate.html109
-rw-r--r--dom/html/test/forms/test_input_radio_radiogroup.html75
-rw-r--r--dom/html/test/forms/test_input_radio_required.html31
-rw-r--r--dom/html/test/forms/test_input_range_attr_order.html48
-rw-r--r--dom/html/test/forms/test_input_range_key_events.html210
-rw-r--r--dom/html/test/forms/test_input_range_mouse_and_touch_events.html199
-rw-r--r--dom/html/test/forms/test_input_range_rounding.html106
-rw-r--r--dom/html/test/forms/test_input_sanitization.html565
-rw-r--r--dom/html/test/forms/test_input_textarea_set_value_no_scroll.html122
-rw-r--r--dom/html/test/forms/test_input_time_focus_blur_events.html82
-rw-r--r--dom/html/test/forms/test_input_time_key_events.html197
-rw-r--r--dom/html/test/forms/test_input_types_pref.html114
-rw-r--r--dom/html/test/forms/test_input_typing_sanitization.html260
-rw-r--r--dom/html/test/forms/test_input_untrusted_key_events.html96
-rw-r--r--dom/html/test/forms/test_input_url.html89
-rw-r--r--dom/html/test/forms/test_interactive_content_in_label.html83
-rw-r--r--dom/html/test/forms/test_label_control_attribute.html100
-rw-r--r--dom/html/test/forms/test_label_input_controls.html84
-rw-r--r--dom/html/test/forms/test_max_attribute.html437
-rw-r--r--dom/html/test/forms/test_maxlength_attribute.html129
-rw-r--r--dom/html/test/forms/test_meter_element.html384
-rw-r--r--dom/html/test/forms/test_meter_pseudo-classes.html170
-rw-r--r--dom/html/test/forms/test_min_attribute.html437
-rw-r--r--dom/html/test/forms/test_minlength_attribute.html130
-rw-r--r--dom/html/test/forms/test_mozistextfield.html111
-rw-r--r--dom/html/test/forms/test_novalidate_attribute.html87
-rw-r--r--dom/html/test/forms/test_option_disabled.html123
-rw-r--r--dom/html/test/forms/test_option_index_attribute.html76
-rw-r--r--dom/html/test/forms/test_option_text.html57
-rw-r--r--dom/html/test/forms/test_output_element.html182
-rw-r--r--dom/html/test/forms/test_pattern_attribute.html324
-rw-r--r--dom/html/test/forms/test_progress_element.html314
-rw-r--r--dom/html/test/forms/test_radio_in_label.html54
-rw-r--r--dom/html/test/forms/test_radio_radionodelist.html57
-rw-r--r--dom/html/test/forms/test_reportValidation_preventDefault.html93
-rw-r--r--dom/html/test/forms/test_required_attribute.html382
-rw-r--r--dom/html/test/forms/test_restore_form_elements.html174
-rw-r--r--dom/html/test/forms/test_save_restore_radio_groups.html73
-rw-r--r--dom/html/test/forms/test_select_change_event.html54
-rw-r--r--dom/html/test/forms/test_select_input_change_event.html122
-rw-r--r--dom/html/test/forms/test_select_selectedOptions.html120
-rw-r--r--dom/html/test/forms/test_select_validation.html39
-rw-r--r--dom/html/test/forms/test_set_range_text.html244
-rw-r--r--dom/html/test/forms/test_step_attribute.html965
-rw-r--r--dom/html/test/forms/test_stepup_stepdown.html1018
-rw-r--r--dom/html/test/forms/test_submit_invalid_file.html53
-rw-r--r--dom/html/test/forms/test_textarea_attributes_reflection.html104
-rw-r--r--dom/html/test/forms/test_validation.html358
-rw-r--r--dom/html/test/forms/test_validation_not_in_doc.html19
-rw-r--r--dom/html/test/forms/test_valueAsDate_pref.html57
-rw-r--r--dom/html/test/forms/test_valueasdate_attribute.html649
-rw-r--r--dom/html/test/forms/test_valueasnumber_attribute.html744
-rw-r--r--dom/html/test/head.js54
-rw-r--r--dom/html/test/image-allow-credentials.pngbin0 -> 844 bytes
-rw-r--r--dom/html/test/image-allow-credentials.png^headers^2
-rw-r--r--dom/html/test/image.pngbin0 -> 268 bytes
-rw-r--r--dom/html/test/imports/file_CSP_sandbox.html7
-rw-r--r--dom/html/test/imports/file_CSP_sandbox_import.html9
-rw-r--r--dom/html/test/imports/file_blocking_DOMContentLoaded_A.html11
-rw-r--r--dom/html/test/imports/file_blocking_DOMContentLoaded_B.html11
-rw-r--r--dom/html/test/imports/file_blocking_DOMContentLoaded_C.html11
-rw-r--r--dom/html/test/imports/file_blocking_DOMContentLoaded_D.html10
-rw-r--r--dom/html/test/imports/file_cycle_1_A.html11
-rw-r--r--dom/html/test/imports/file_cycle_1_B.html12
-rw-r--r--dom/html/test/imports/file_cycle_1_C.html12
-rw-r--r--dom/html/test/imports/file_cycle_2_A.html11
-rw-r--r--dom/html/test/imports/file_cycle_2_B.html13
-rw-r--r--dom/html/test/imports/file_cycle_2_C.html10
-rw-r--r--dom/html/test/imports/file_cycle_2_D.html10
-rw-r--r--dom/html/test/imports/file_cycle_3_A.html11
-rw-r--r--dom/html/test/imports/file_cycle_3_B.html11
-rw-r--r--dom/html/test/imports/file_cycle_3_C.html12
-rw-r--r--dom/html/test/imports/file_cycle_4_A.html11
-rw-r--r--dom/html/test/imports/file_cycle_4_B.html11
-rw-r--r--dom/html/test/imports/file_cycle_4_C.html11
-rw-r--r--dom/html/test/imports/file_cycle_4_D.html12
-rw-r--r--dom/html/test/imports/file_cycle_4_E.html11
-rw-r--r--dom/html/test/imports/file_element_upgrade.html15
-rw-r--r--dom/html/test/imports/file_encoding.html5
-rw-r--r--dom/html/test/imports/file_importA1.html11
-rw-r--r--dom/html/test/imports/file_importA2.html10
-rw-r--r--dom/html/test/imports/file_importB1.html11
-rw-r--r--dom/html/test/imports/file_importB2.html10
-rw-r--r--dom/html/test/imports/file_importC1.html11
-rw-r--r--dom/html/test/imports/file_importC10.html11
-rw-r--r--dom/html/test/imports/file_importC2.html11
-rw-r--r--dom/html/test/imports/file_importC3.html11
-rw-r--r--dom/html/test/imports/file_importC4.html11
-rw-r--r--dom/html/test/imports/file_importC5.html11
-rw-r--r--dom/html/test/imports/file_importC6.html11
-rw-r--r--dom/html/test/imports/file_importC7.html11
-rw-r--r--dom/html/test/imports/file_importC8.html11
-rw-r--r--dom/html/test/imports/file_importC9.html11
-rw-r--r--dom/html/test/imports/file_importD.html8
-rw-r--r--dom/html/test/imports/file_importE.html11
-rw-r--r--dom/html/test/imports/file_simple_import.html4
-rw-r--r--dom/html/test/imports/mochitest.ini52
-rw-r--r--dom/html/test/imports/test_CSP_sandbox.html26
-rw-r--r--dom/html/test/imports/test_blocking_DOMContentLoaded.html36
-rw-r--r--dom/html/test/imports/test_cycle_1.html36
-rw-r--r--dom/html/test/imports/test_cycle_2.html36
-rw-r--r--dom/html/test/imports/test_cycle_3.html37
-rw-r--r--dom/html/test/imports/test_cycle_4.html37
-rw-r--r--dom/html/test/imports/test_defaultView.html31
-rw-r--r--dom/html/test/imports/test_element_upgrade.html34
-rw-r--r--dom/html/test/imports/test_encoding.html30
-rw-r--r--dom/html/test/mochitest.ini608
-rw-r--r--dom/html/test/nnc_lockup.gifbin0 -> 732 bytes
-rw-r--r--dom/html/test/reflect.js625
-rw-r--r--dom/html/test/simpleFileOpener.js32
-rw-r--r--dom/html/test/test_a_text.html44
-rw-r--r--dom/html/test/test_allowMedia.html99
-rw-r--r--dom/html/test/test_anchor_href_cache_invalidation.html30
-rw-r--r--dom/html/test/test_anchor_ping.html309
-rw-r--r--dom/html/test/test_applet_attributes_reflection.html86
-rw-r--r--dom/html/test/test_audio_wakelock.html125
-rw-r--r--dom/html/test/test_base_attributes_reflection.html34
-rw-r--r--dom/html/test/test_bug1003539.html37
-rw-r--r--dom/html/test/test_bug100533.html47
-rw-r--r--dom/html/test/test_bug1013316.html46
-rw-r--r--dom/html/test/test_bug1045270.html46
-rw-r--r--dom/html/test/test_bug1081037.html133
-rw-r--r--dom/html/test/test_bug109445.html55
-rw-r--r--dom/html/test/test_bug109445.xhtml55
-rw-r--r--dom/html/test/test_bug1146116.html59
-rw-r--r--dom/html/test/test_bug1166138.html130
-rw-r--r--dom/html/test/test_bug1203668.html62
-rw-r--r--dom/html/test/test_bug1230665.html46
-rw-r--r--dom/html/test/test_bug1233598.html35
-rw-r--r--dom/html/test/test_bug1250401.html97
-rw-r--r--dom/html/test/test_bug1260664.html54
-rw-r--r--dom/html/test/test_bug1260704.html90
-rw-r--r--dom/html/test/test_bug1261673.html77
-rw-r--r--dom/html/test/test_bug1261674-1.html77
-rw-r--r--dom/html/test/test_bug1261674-2.html70
-rw-r--r--dom/html/test/test_bug1264157.html90
-rw-r--r--dom/html/test/test_bug1287321.html57
-rw-r--r--dom/html/test/test_bug1292522_same_domain_with_different_port_number.html43
-rw-r--r--dom/html/test/test_bug1295719_event_sequence_for_arrow_keys.html67
-rw-r--r--dom/html/test/test_bug1295719_event_sequence_for_number_keys.html65
-rw-r--r--dom/html/test/test_bug1297.html46
-rw-r--r--dom/html/test/test_bug1310865.html18
-rw-r--r--dom/html/test/test_bug1315146.html33
-rw-r--r--dom/html/test/test_bug1366.html35
-rw-r--r--dom/html/test/test_bug1400.html42
-rw-r--r--dom/html/test/test_bug143220.html72
-rw-r--r--dom/html/test/test_bug1682.html37
-rw-r--r--dom/html/test/test_bug172261.html67
-rw-r--r--dom/html/test/test_bug182279.html35
-rw-r--r--dom/html/test/test_bug1823.html30
-rw-r--r--dom/html/test/test_bug196523.html41
-rw-r--r--dom/html/test/test_bug199692.html21
-rw-r--r--dom/html/test/test_bug2082.html30
-rw-r--r--dom/html/test/test_bug209275.xhtml261
-rw-r--r--dom/html/test/test_bug237071.html28
-rw-r--r--dom/html/test/test_bug242709.html33
-rw-r--r--dom/html/test/test_bug24958.html31
-rw-r--r--dom/html/test/test_bug255820.html123
-rw-r--r--dom/html/test/test_bug259332.html64
-rw-r--r--dom/html/test/test_bug274626.html97
-rw-r--r--dom/html/test/test_bug277724.html141
-rw-r--r--dom/html/test/test_bug277890.html33
-rw-r--r--dom/html/test/test_bug287465.html45
-rw-r--r--dom/html/test/test_bug295561.html86
-rw-r--r--dom/html/test/test_bug297761.html77
-rw-r--r--dom/html/test/test_bug300691-1.html120
-rw-r--r--dom/html/test/test_bug300691-2.html142
-rw-r--r--dom/html/test/test_bug300691-3.xhtml48
-rw-r--r--dom/html/test/test_bug311681.html99
-rw-r--r--dom/html/test/test_bug311681.xhtml102
-rw-r--r--dom/html/test/test_bug324378.html76
-rw-r--r--dom/html/test/test_bug330705-1.html41
-rw-r--r--dom/html/test/test_bug332246.html75
-rw-r--r--dom/html/test/test_bug332848.xhtml86
-rw-r--r--dom/html/test/test_bug332893-1.html38
-rw-r--r--dom/html/test/test_bug332893-2.html53
-rw-r--r--dom/html/test/test_bug332893-3.html58
-rw-r--r--dom/html/test/test_bug332893-4.html29
-rw-r--r--dom/html/test/test_bug332893-5.html29
-rw-r--r--dom/html/test/test_bug332893-6.html27
-rw-r--r--dom/html/test/test_bug332893-7.html69
-rw-r--r--dom/html/test/test_bug3348.html33
-rw-r--r--dom/html/test/test_bug340017.xhtml27
-rw-r--r--dom/html/test/test_bug340800.html55
-rw-r--r--dom/html/test/test_bug347174.html64
-rw-r--r--dom/html/test/test_bug347174_write.html71
-rw-r--r--dom/html/test/test_bug347174_xsl.html55
-rw-r--r--dom/html/test/test_bug347174_xslp.html61
-rw-r--r--dom/html/test/test_bug353415-1.html42
-rw-r--r--dom/html/test/test_bug353415-2.html67
-rw-r--r--dom/html/test/test_bug359657.html40
-rw-r--r--dom/html/test/test_bug369370.html151
-rw-r--r--dom/html/test/test_bug371375.html58
-rw-r--r--dom/html/test/test_bug372098.html75
-rw-r--r--dom/html/test/test_bug373589.html29
-rw-r--r--dom/html/test/test_bug375003-1.html156
-rw-r--r--dom/html/test/test_bug375003-2.html109
-rw-r--r--dom/html/test/test_bug377624.html25
-rw-r--r--dom/html/test/test_bug380383.html39
-rw-r--r--dom/html/test/test_bug383383.html41
-rw-r--r--dom/html/test/test_bug383383_2.xhtml20
-rw-r--r--dom/html/test/test_bug384419.html56
-rw-r--r--dom/html/test/test_bug386496.html53
-rw-r--r--dom/html/test/test_bug386728.html45
-rw-r--r--dom/html/test/test_bug386996.html43
-rw-r--r--dom/html/test/test_bug388558.html76
-rw-r--r--dom/html/test/test_bug388746.html62
-rw-r--r--dom/html/test/test_bug388794.html104
-rw-r--r--dom/html/test/test_bug389797.html267
-rw-r--r--dom/html/test/test_bug390975.html61
-rw-r--r--dom/html/test/test_bug391777.html25
-rw-r--r--dom/html/test/test_bug391994.html184
-rw-r--r--dom/html/test/test_bug392567.html88
-rw-r--r--dom/html/test/test_bug394700.html49
-rw-r--r--dom/html/test/test_bug395107.html108
-rw-r--r--dom/html/test/test_bug401160.xhtml27
-rw-r--r--dom/html/test/test_bug402680.html50
-rw-r--r--dom/html/test/test_bug403868.html87
-rw-r--r--dom/html/test/test_bug403868.xhtml86
-rw-r--r--dom/html/test/test_bug405242.html35
-rw-r--r--dom/html/test/test_bug406596.html83
-rw-r--r--dom/html/test/test_bug417760.html71
-rw-r--r--dom/html/test/test_bug421640.html56
-rw-r--r--dom/html/test/test_bug424698.html94
-rw-r--r--dom/html/test/test_bug428135.xhtml156
-rw-r--r--dom/html/test/test_bug430351.html523
-rw-r--r--dom/html/test/test_bug430392.html47
-rw-r--r--dom/html/test/test_bug435128.html42
-rw-r--r--dom/html/test/test_bug441930.html29
-rw-r--r--dom/html/test/test_bug442801.html63
-rw-r--r--dom/html/test/test_bug445004.html138
-rw-r--r--dom/html/test/test_bug446483.html47
-rw-r--r--dom/html/test/test_bug448166.html35
-rw-r--r--dom/html/test/test_bug448564.html53
-rw-r--r--dom/html/test/test_bug456229.html30
-rw-r--r--dom/html/test/test_bug458037.xhtml112
-rw-r--r--dom/html/test/test_bug460568.html147
-rw-r--r--dom/html/test/test_bug463104.html25
-rw-r--r--dom/html/test/test_bug478251.html74
-rw-r--r--dom/html/test/test_bug481335.xhtml120
-rw-r--r--dom/html/test/test_bug481440.html30
-rw-r--r--dom/html/test/test_bug481647.html42
-rw-r--r--dom/html/test/test_bug482659.html64
-rw-r--r--dom/html/test/test_bug486741.html43
-rw-r--r--dom/html/test/test_bug489532.html33
-rw-r--r--dom/html/test/test_bug497242.xhtml41
-rw-r--r--dom/html/test/test_bug499092.html43
-rw-r--r--dom/html/test/test_bug500885.html63
-rw-r--r--dom/html/test/test_bug512367.html47
-rw-r--r--dom/html/test/test_bug514856.html61
-rw-r--r--dom/html/test/test_bug518122.html126
-rw-r--r--dom/html/test/test_bug519987.html33
-rw-r--r--dom/html/test/test_bug523771.html106
-rw-r--r--dom/html/test/test_bug529819.html32
-rw-r--r--dom/html/test/test_bug529859.html42
-rw-r--r--dom/html/test/test_bug535043.html90
-rw-r--r--dom/html/test/test_bug536891.html67
-rw-r--r--dom/html/test/test_bug536895.html54
-rw-r--r--dom/html/test/test_bug546995.html40
-rw-r--r--dom/html/test/test_bug547850.html45
-rw-r--r--dom/html/test/test_bug551846.html164
-rw-r--r--dom/html/test/test_bug555567.html42
-rw-r--r--dom/html/test/test_bug556645.html50
-rw-r--r--dom/html/test/test_bug557087-1.html126
-rw-r--r--dom/html/test/test_bug557087-2.html359
-rw-r--r--dom/html/test/test_bug557087-3.html215
-rw-r--r--dom/html/test/test_bug557087-4.html90
-rw-r--r--dom/html/test/test_bug557087-5.html93
-rw-r--r--dom/html/test/test_bug557087-6.html44
-rw-r--r--dom/html/test/test_bug557620.html30
-rw-r--r--dom/html/test/test_bug558788-1.html211
-rw-r--r--dom/html/test/test_bug558788-2.html174
-rw-r--r--dom/html/test/test_bug560112.html211
-rw-r--r--dom/html/test/test_bug561634.html126
-rw-r--r--dom/html/test/test_bug561636.html118
-rw-r--r--dom/html/test/test_bug561640.html72
-rw-r--r--dom/html/test/test_bug564001.html48
-rw-r--r--dom/html/test/test_bug566046.html207
-rw-r--r--dom/html/test/test_bug567938-1.html69
-rw-r--r--dom/html/test/test_bug567938-2.html70
-rw-r--r--dom/html/test/test_bug567938-3.html70
-rw-r--r--dom/html/test/test_bug567938-4.html44
-rw-r--r--dom/html/test/test_bug569955.html37
-rw-r--r--dom/html/test/test_bug573969.html37
-rw-r--r--dom/html/test/test_bug57600.html42
-rw-r--r--dom/html/test/test_bug579079.html43
-rw-r--r--dom/html/test/test_bug582412-1.html209
-rw-r--r--dom/html/test/test_bug582412-2.html209
-rw-r--r--dom/html/test/test_bug583514.html71
-rw-r--r--dom/html/test/test_bug583533.html81
-rw-r--r--dom/html/test/test_bug586763.html43
-rw-r--r--dom/html/test/test_bug586786.html57
-rw-r--r--dom/html/test/test_bug587469.html41
-rw-r--r--dom/html/test/test_bug589.html42
-rw-r--r--dom/html/test/test_bug590353-1.html36
-rw-r--r--dom/html/test/test_bug590353-2.html79
-rw-r--r--dom/html/test/test_bug590363.html133
-rw-r--r--dom/html/test/test_bug592802.html97
-rw-r--r--dom/html/test/test_bug593689.html50
-rw-r--r--dom/html/test/test_bug595429.html56
-rw-r--r--dom/html/test/test_bug595447.html29
-rw-r--r--dom/html/test/test_bug595449.html95
-rw-r--r--dom/html/test/test_bug596350.html65
-rw-r--r--dom/html/test/test_bug596511.html229
-rw-r--r--dom/html/test/test_bug598643.html80
-rw-r--r--dom/html/test/test_bug598833-1.html45
-rw-r--r--dom/html/test/test_bug600155.html44
-rw-r--r--dom/html/test/test_bug601030.html54
-rw-r--r--dom/html/test/test_bug605124-1.html107
-rw-r--r--dom/html/test/test_bug605124-2.html112
-rw-r--r--dom/html/test/test_bug605125-1.html113
-rw-r--r--dom/html/test/test_bug605125-2.html145
-rw-r--r--dom/html/test/test_bug606817.html64
-rw-r--r--dom/html/test/test_bug607145.html82
-rw-r--r--dom/html/test/test_bug610212.html42
-rw-r--r--dom/html/test/test_bug610687.html201
-rw-r--r--dom/html/test/test_bug611189.html45
-rw-r--r--dom/html/test/test_bug612730.html53
-rw-r--r--dom/html/test/test_bug613019.html84
-rw-r--r--dom/html/test/test_bug613113.html57
-rw-r--r--dom/html/test/test_bug613722.html32
-rw-r--r--dom/html/test/test_bug613979.html50
-rw-r--r--dom/html/test/test_bug615595.htmlbin0 -> 2704 bytes
-rw-r--r--dom/html/test/test_bug615833.html156
-rw-r--r--dom/html/test/test_bug617528.html73
-rw-r--r--dom/html/test/test_bug618948.html88
-rw-r--r--dom/html/test/test_bug619278.html58
-rw-r--r--dom/html/test/test_bug622558.html89
-rw-r--r--dom/html/test/test_bug622597.html115
-rw-r--r--dom/html/test/test_bug623291.html46
-rw-r--r--dom/html/test/test_bug6296.html31
-rw-r--r--dom/html/test/test_bug629801.html50
-rw-r--r--dom/html/test/test_bug633058.html68
-rw-r--r--dom/html/test/test_bug636336.html40
-rw-r--r--dom/html/test/test_bug641219.html34
-rw-r--r--dom/html/test/test_bug643051.html42
-rw-r--r--dom/html/test/test_bug646157.html95
-rw-r--r--dom/html/test/test_bug649134.html54
-rw-r--r--dom/html/test/test_bug651956.html51
-rw-r--r--dom/html/test/test_bug658746.html97
-rw-r--r--dom/html/test/test_bug659596.html96
-rw-r--r--dom/html/test/test_bug659743.xml55
-rw-r--r--dom/html/test/test_bug660663.html30
-rw-r--r--dom/html/test/test_bug660959-1.html26
-rw-r--r--dom/html/test/test_bug660959-2.html31
-rw-r--r--dom/html/test/test_bug660959-3.html29
-rw-r--r--dom/html/test/test_bug666200.html43
-rw-r--r--dom/html/test/test_bug666666.html32
-rw-r--r--dom/html/test/test_bug669012.html45
-rw-r--r--dom/html/test/test_bug674558.html290
-rw-r--r--dom/html/test/test_bug674927.html55
-rw-r--r--dom/html/test/test_bug677463.html38
-rw-r--r--dom/html/test/test_bug677495-1.html34
-rw-r--r--dom/html/test/test_bug677495.html34
-rw-r--r--dom/html/test/test_bug677658.html41
-rw-r--r--dom/html/test/test_bug682886.html33
-rw-r--r--dom/html/test/test_bug691.html62
-rw-r--r--dom/html/test/test_bug694.html30
-rw-r--r--dom/html/test/test_bug694503.html75
-rw-r--r--dom/html/test/test_bug696.html28
-rw-r--r--dom/html/test/test_bug717819.html37
-rw-r--r--dom/html/test/test_bug741266.html44
-rw-r--r--dom/html/test/test_bug742030.html31
-rw-r--r--dom/html/test/test_bug742549.html47
-rw-r--r--dom/html/test/test_bug745685.html105
-rw-r--r--dom/html/test/test_bug763626.html29
-rw-r--r--dom/html/test/test_bug765780.html46
-rw-r--r--dom/html/test/test_bug780993.html39
-rw-r--r--dom/html/test/test_bug787134.html29
-rw-r--r--dom/html/test/test_bug797113.html39
-rw-r--r--dom/html/test/test_bug803677.html50
-rw-r--r--dom/html/test/test_bug821307.html41
-rw-r--r--dom/html/test/test_bug827126.html28
-rw-r--r--dom/html/test/test_bug838582.html35
-rw-r--r--dom/html/test/test_bug839371.html44
-rw-r--r--dom/html/test/test_bug839913.html14
-rw-r--r--dom/html/test/test_bug841466.html37
-rw-r--r--dom/html/test/test_bug845057.html59
-rw-r--r--dom/html/test/test_bug869040.html36
-rw-r--r--dom/html/test/test_bug870787.html84
-rw-r--r--dom/html/test/test_bug871161.html37
-rw-r--r--dom/html/test/test_bug874758.html31
-rw-r--r--dom/html/test/test_bug879319.html92
-rw-r--r--dom/html/test/test_bug885024.html46
-rw-r--r--dom/html/test/test_bug893537.html45
-rw-r--r--dom/html/test/test_bug95530.html38
-rw-r--r--dom/html/test/test_bug969346.html33
-rw-r--r--dom/html/test/test_bug982039.html46
-rw-r--r--dom/html/test/test_change_crossorigin.html89
-rw-r--r--dom/html/test/test_checked.html358
-rw-r--r--dom/html/test/test_dir_attributes_reflection.html27
-rw-r--r--dom/html/test/test_dl_attributes_reflection.html27
-rw-r--r--dom/html/test/test_document-element-inserted.html54
-rw-r--r--dom/html/test/test_document.watch.html129
-rw-r--r--dom/html/test/test_documentAll.html167
-rw-r--r--dom/html/test/test_element_prototype.html32
-rw-r--r--dom/html/test/test_embed_attributes_reflection.html57
-rw-r--r--dom/html/test/test_filepicker_default_directory.html83
-rw-r--r--dom/html/test/test_focusshift_button.html40
-rw-r--r--dom/html/test/test_form-parsing.html35
-rw-r--r--dom/html/test/test_formData.html50
-rw-r--r--dom/html/test/test_formSubmission.html825
-rw-r--r--dom/html/test/test_formSubmission2.html221
-rw-r--r--dom/html/test/test_formelements.html68
-rw-r--r--dom/html/test/test_fragment_form_pointer.html27
-rw-r--r--dom/html/test/test_fullscreen-api-race.html166
-rw-r--r--dom/html/test/test_fullscreen-api.html106
-rw-r--r--dom/html/test/test_hash_encoded.html118
-rw-r--r--dom/html/test/test_hidden.html52
-rw-r--r--dom/html/test/test_html_attributes_reflection.html27
-rw-r--r--dom/html/test/test_htmlcollection.html55
-rw-r--r--dom/html/test/test_iframe_sandbox_general.html283
-rw-r--r--dom/html/test/test_iframe_sandbox_inheritance.html203
-rw-r--r--dom/html/test/test_iframe_sandbox_modal.html122
-rw-r--r--dom/html/test/test_iframe_sandbox_navigation.html281
-rw-r--r--dom/html/test/test_iframe_sandbox_navigation2.html212
-rw-r--r--dom/html/test/test_iframe_sandbox_plugins.html141
-rw-r--r--dom/html/test/test_iframe_sandbox_popups.html78
-rw-r--r--dom/html/test/test_iframe_sandbox_popups_inheritance.html157
-rw-r--r--dom/html/test/test_iframe_sandbox_redirect.html45
-rw-r--r--dom/html/test/test_iframe_sandbox_refresh.html101
-rw-r--r--dom/html/test/test_iframe_sandbox_same_origin.html108
-rw-r--r--dom/html/test/test_iframe_sandbox_workers.html74
-rw-r--r--dom/html/test/test_ignoreuserfocus.html158
-rw-r--r--dom/html/test/test_imageSrcSet.html38
-rw-r--r--dom/html/test/test_image_clone_load.html21
-rw-r--r--dom/html/test/test_img_attributes_reflection.html103
-rw-r--r--dom/html/test/test_imports_basics.html68
-rw-r--r--dom/html/test/test_imports_nested.html41
-rw-r--r--dom/html/test/test_imports_nested_2.html56
-rw-r--r--dom/html/test/test_imports_nonhttp.html56
-rw-r--r--dom/html/test/test_imports_redirect.html39
-rw-r--r--dom/html/test/test_input_files_not_nsIFile.html48
-rw-r--r--dom/html/test/test_li_attributes_reflection.html34
-rw-r--r--dom/html/test/test_link_attributes_reflection.html84
-rw-r--r--dom/html/test/test_link_sizes.html35
-rw-r--r--dom/html/test/test_map_attributes_reflection.html27
-rw-r--r--dom/html/test/test_meta_attributes_reflection.html45
-rw-r--r--dom/html/test/test_mod_attributes_reflection.html41
-rw-r--r--dom/html/test/test_mozaudiochannel.html31
-rw-r--r--dom/html/test/test_named_options.html61
-rw-r--r--dom/html/test/test_nested_invalid_fieldsets.html47
-rw-r--r--dom/html/test/test_non-ascii-cookie.html60
-rw-r--r--dom/html/test/test_non-ascii-cookie.html^headers^1
-rw-r--r--dom/html/test/test_object_attributes_reflection.html117
-rw-r--r--dom/html/test/test_object_plugin_nav.html99
-rw-r--r--dom/html/test/test_ol_attributes_reflection.html65
-rw-r--r--dom/html/test/test_option_defaultSelected.html47
-rw-r--r--dom/html/test/test_option_selected_state.html61
-rw-r--r--dom/html/test/test_param_attributes_reflection.html45
-rw-r--r--dom/html/test/test_plugin.tst1
-rw-r--r--dom/html/test/test_q_attributes_reflection.html32
-rw-r--r--dom/html/test/test_restore_from_parser_fragment.html59
-rw-r--r--dom/html/test/test_rowscollection.html69
-rw-r--r--dom/html/test/test_srcdoc-2.html57
-rw-r--r--dom/html/test/test_srcdoc.html118
-rw-r--r--dom/html/test/test_style_attributes_reflection.html41
-rw-r--r--dom/html/test/test_track.html62
-rw-r--r--dom/html/test/test_ul_attributes_reflection.html33
-rw-r--r--dom/html/test/test_video_wakelock.html198
-rw-r--r--dom/html/test/test_viewport.html57
-rw-r--r--dom/html/test/test_viewport_resize.html44
-rw-r--r--dom/html/test/test_window_open_close.html53
-rw-r--r--dom/html/test/wakelock.oggbin0 -> 16521 bytes
-rw-r--r--dom/html/test/wakelock.ogvbin0 -> 28942 bytes
731 files changed, 51889 insertions, 0 deletions
diff --git a/dom/html/test/347174transform.xsl b/dom/html/test/347174transform.xsl
new file mode 100644
index 000000000..1b201de3f
--- /dev/null
+++ b/dom/html/test/347174transform.xsl
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:template match="/">
+<html>
+<head>
+<script>
+window.parent.frameScriptTag(document.readyState);
+
+function attachCustomEventListener(element, eventName, command) {
+ if (window.addEventListener &amp;&amp; !window.opera)
+ element.addEventListener(eventName, command, true);
+ else if (window.attachEvent)
+ element.attachEvent("on" + eventName, command);
+}
+
+function load() {
+ window.parent.frameLoad(document.readyState);
+}
+
+function readyStateChange() {
+ window.parent.frameReadyStateChange(document.readyState);
+}
+
+function DOMContentLoaded() {
+ window.parent.frameDOMContentLoaded(document.readyState);
+}
+
+window.onload=load;
+
+attachCustomEventListener(document, "readystatechange", readyStateChange);
+attachCustomEventListener(document, "DOMContentLoaded", DOMContentLoaded);
+
+</script>
+</head>
+<body>
+</body>
+</html>
+</xsl:template>
+
+</xsl:stylesheet> \ No newline at end of file
diff --git a/dom/html/test/347174transformable.xml b/dom/html/test/347174transformable.xml
new file mode 100644
index 000000000..68f7bc6dc
--- /dev/null
+++ b/dom/html/test/347174transformable.xml
@@ -0,0 +1,3 @@
+<?xml version='1.0'?>
+<?xml-stylesheet type="text/xsl" href="347174transform.xsl"?>
+<doc>This is a sample document.</doc>
diff --git a/dom/html/test/allowMedia.sjs b/dom/html/test/allowMedia.sjs
new file mode 100644
index 000000000..f29619cd8
--- /dev/null
+++ b/dom/html/test/allowMedia.sjs
@@ -0,0 +1,12 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function handleRequest(req, resp) {
+ resp.setHeader("Cache-Control", "no-cache", false);
+ resp.setHeader("Content-Type", "text/plain", false);
+
+ let stateKey = "allowMediaState";
+ let state = getState(stateKey);
+ setState(stateKey, req.queryString ? "FAIL" : "");
+ resp.write(state || "PASS");
+}
diff --git a/dom/html/test/browser.ini b/dom/html/test/browser.ini
new file mode 100644
index 000000000..49caea726
--- /dev/null
+++ b/dom/html/test/browser.ini
@@ -0,0 +1,25 @@
+[DEFAULT]
+support-files =
+ bug592641_img.jpg
+ dummy_page.html
+ file_bug649778.html
+ file_bug649778.html^headers^
+ file_fullscreen-api-keys.html
+ file_content_contextmenu.html
+ head.js
+
+[browser_bug592641.js]
+[browser_bug649778.js]
+skip-if = e10s # Bug 1271025
+[browser_bug1081537.js]
+[browser_bug1108547.js]
+support-files =
+ file_bug1108547-1.html
+ file_bug1108547-2.html
+ file_bug1108547-3.html
+[browser_content_contextmenu_userinput.js]
+[browser_DOMDocElementInserted.js]
+[browser_fullscreen-api-keys.js]
+tags = fullscreen
+[browser_fullscreen-contextmenu-esc.js]
+tags = fullscreen
diff --git a/dom/html/test/browser_DOMDocElementInserted.js b/dom/html/test/browser_DOMDocElementInserted.js
new file mode 100644
index 000000000..9fa8335e6
--- /dev/null
+++ b/dom/html/test/browser_DOMDocElementInserted.js
@@ -0,0 +1,24 @@
+// Tests that the DOMDocElementInserted event is visible on the frame
+add_task(function*() {
+ let tab = gBrowser.addTab();
+ let uri = "data:text/html;charset=utf-8,<html/>"
+
+ let eventPromise = ContentTask.spawn(tab.linkedBrowser, null, function() {
+ Cu.import("resource://gre/modules/PromiseUtils.jsm");
+ let deferred = PromiseUtils.defer();
+
+ let listener = (event) => {
+ removeEventListener("DOMDocElementInserted", listener, true);
+ deferred.resolve(event.target.documentURIObject.spec);
+ };
+ addEventListener("DOMDocElementInserted", listener, true);
+
+ return deferred.promise;
+ });
+
+ tab.linkedBrowser.loadURI(uri);
+ let loadedURI = yield eventPromise;
+ is(loadedURI, uri, "Should have seen the event for the right URI");
+
+ gBrowser.removeTab(tab);
+});
diff --git a/dom/html/test/browser_bug1081537.js b/dom/html/test/browser_bug1081537.js
new file mode 100644
index 000000000..8ae53e4ff
--- /dev/null
+++ b/dom/html/test/browser_bug1081537.js
@@ -0,0 +1,11 @@
+// This test is useful because mochitest-browser runs as an addon, so we test
+// addon-scope paths here.
+var ifr;
+function test() {
+ ifr = document.createElement('iframe');
+ document.getElementById('main-window').appendChild(ifr);
+ is(ifr.contentDocument.nodePrincipal.origin, "[System Principal]");
+ ifr.contentDocument.open();
+ ok(true, "Didn't throw");
+}
+registerCleanupFunction(() => ifr.remove());
diff --git a/dom/html/test/browser_bug1108547.js b/dom/html/test/browser_bug1108547.js
new file mode 100644
index 000000000..711dac0aa
--- /dev/null
+++ b/dom/html/test/browser_bug1108547.js
@@ -0,0 +1,113 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+requestLongerTimeout(2);
+
+function test() {
+ waitForExplicitFinish();
+
+ runPass("file_bug1108547-2.html", function() {
+ runPass("file_bug1108547-3.html", function() {
+ finish();
+ });
+ });
+}
+
+function runPass(getterFile, finishedCallback) {
+ var rootDir = "http://mochi.test:8888/browser/dom/html/test/";
+ var testBrowser;
+ var privateWin;
+
+ function whenDelayedStartupFinished(win, callback) {
+ let topic = "browser-delayed-startup-finished";
+ Services.obs.addObserver(function onStartup(aSubject) {
+ if (win != aSubject)
+ return;
+
+ Services.obs.removeObserver(onStartup, topic);
+ executeSoon(callback);
+ }, topic, false);
+ }
+
+ // First, set the cookie in a normal window.
+ gBrowser.selectedTab = gBrowser.addTab(rootDir + "file_bug1108547-1.html");
+ BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser).then(afterOpenCookieSetter);
+
+ function afterOpenCookieSetter() {
+ gBrowser.removeCurrentTab();
+
+ // Now, open a private window.
+ privateWin = OpenBrowserWindow({private: true});
+ whenDelayedStartupFinished(privateWin, afterPrivateWindowOpened);
+ }
+
+ function afterPrivateWindowOpened() {
+ // In the private window, open the getter file, and wait for a new tab to be opened.
+ privateWin.gBrowser.selectedTab = privateWin.gBrowser.addTab(rootDir + getterFile);
+ testBrowser = privateWin.gBrowser.selectedBrowser;
+ privateWin.gBrowser.tabContainer.addEventListener("TabOpen", onNewTabOpened, true);
+ }
+
+ function fetchResult() {
+ return ContentTask.spawn(testBrowser, null, function() {
+ return content.document.getElementById("result").textContent;
+ });
+ }
+
+ function onNewTabOpened() {
+ // When the new tab is opened, wait for it to load.
+ privateWin.gBrowser.tabContainer.removeEventListener("TabOpen", onNewTabOpened, true);
+ BrowserTestUtils.browserLoaded(privateWin.gBrowser.tabs[privateWin.gBrowser.tabs.length - 1].linkedBrowser).then(fetchResult).then(onNewTabLoaded);
+ }
+
+ function onNewTabLoaded(result) {
+ // Now, ensure that the private tab doesn't have access to the cookie set in normal mode.
+ is(result, "", "Shouldn't have access to the cookies");
+
+ // We're done with the private window, close it.
+ privateWin.close();
+
+ // Clear all cookies.
+ Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager).removeAll();
+
+ // Open a new private window, this time to set a cookie inside it.
+ privateWin = OpenBrowserWindow({private: true});
+ whenDelayedStartupFinished(privateWin, afterPrivateWindowOpened2);
+ }
+
+ function afterPrivateWindowOpened2() {
+ // In the private window, open the setter file, and wait for it to load.
+ privateWin.gBrowser.selectedTab = privateWin.gBrowser.addTab(rootDir + "file_bug1108547-1.html");
+ BrowserTestUtils.browserLoaded(privateWin.gBrowser.selectedBrowser).then(afterOpenCookieSetter2);
+ }
+
+ function afterOpenCookieSetter2() {
+ // We're done with the private window now, close it.
+ privateWin.close();
+
+ // Now try to read the cookie in a normal window, and wait for a new tab to be opened.
+ gBrowser.selectedTab = gBrowser.addTab(rootDir + getterFile);
+ testBrowser = gBrowser.selectedBrowser;
+ gBrowser.tabContainer.addEventListener("TabOpen", onNewTabOpened2, true);
+ }
+
+ function onNewTabOpened2() {
+ // When the new tab is opened, wait for it to load.
+ gBrowser.tabContainer.removeEventListener("TabOpen", onNewTabOpened2, true);
+ BrowserTestUtils.browserLoaded(gBrowser.tabs[gBrowser.tabs.length - 1].linkedBrowser).then(fetchResult).then(onNewTabLoaded2);
+ }
+
+ function onNewTabLoaded2(result) {
+ // Now, ensure that the normal tab doesn't have access to the cookie set in private mode.
+ is(result, "", "Shouldn't have access to the cookies");
+
+ // Remove both of the tabs opened here.
+ gBrowser.removeCurrentTab();
+ gBrowser.removeCurrentTab();
+
+ privateWin = null;
+ testBrowser = null;
+
+ finishedCallback();
+ }
+}
diff --git a/dom/html/test/browser_bug592641.js b/dom/html/test/browser_bug592641.js
new file mode 100644
index 000000000..94e2e92c2
--- /dev/null
+++ b/dom/html/test/browser_bug592641.js
@@ -0,0 +1,61 @@
+// Test for bug 592641 - Image document doesn't show dimensions of cached images
+
+// Globals
+var testPath = "http://mochi.test:8888/browser/dom/html/test/";
+var ctx = {loadsDone : 0};
+
+// Entry point from Mochikit
+function test() {
+
+ waitForExplicitFinish();
+
+ ctx.tab1 = gBrowser.addTab(testPath + "bug592641_img.jpg");
+ ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1);
+ ctx.tab1Browser.addEventListener("load", load1Soon, true);
+}
+
+function checkTitle(title) {
+
+ ctx.loadsDone++;
+ ok(/^bug592641_img\.jpg \(JPEG Image, 1500\u00A0\u00D7\u00A01500 pixels\)/.test(title),
+ "Title should be correct on load #" + ctx.loadsDone);
+}
+
+function load1Soon() {
+ ctx.tab1Browser.removeEventListener("load", load1Soon, true);
+ // onload is fired in OnStopDecode, so let's use executeSoon() to make sure
+ // that any other OnStopDecode event handlers get the chance to fire first.
+ executeSoon(load1Done);
+}
+
+function load1Done() {
+ // Check the title
+ var title = ctx.tab1Browser.contentTitle;
+ checkTitle(title);
+
+ // Try loading the same image in a new tab to make sure things work in
+ // the cached case.
+ ctx.tab2 = gBrowser.addTab(testPath + "bug592641_img.jpg");
+ ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2);
+ ctx.tab2Browser.addEventListener("load", load2Soon, true);
+}
+
+function load2Soon() {
+ ctx.tab2Browser.removeEventListener("load", load2Soon, true);
+ // onload is fired in OnStopDecode, so let's use executeSoon() to make sure
+ // that any other OnStopDecode event handlers get the chance to fire first.
+ executeSoon(load2Done);
+}
+
+function load2Done() {
+ // Check the title
+ var title = ctx.tab2Browser.contentTitle;
+ checkTitle(title);
+
+ // Clean up
+ gBrowser.removeTab(ctx.tab1);
+ gBrowser.removeTab(ctx.tab2);
+
+ // Test done
+ finish();
+}
diff --git a/dom/html/test/browser_bug649778.js b/dom/html/test/browser_bug649778.js
new file mode 100644
index 000000000..6356d20fe
--- /dev/null
+++ b/dom/html/test/browser_bug649778.js
@@ -0,0 +1,82 @@
+// Test for bug 649778 - document.write may cause a document to be written to disk cache even when the page has Cache-Control: no-store
+
+// Globals
+var testPath = "http://mochi.test:8888/browser/dom/html/test/";
+var popup;
+
+var {LoadContextInfo} = Cu.import("resource://gre/modules/LoadContextInfo.jsm", null);
+var {Services} = Cu.import("resource://gre/modules/Services.jsm", null);
+
+function checkCache(url, inMemory, shouldExist, cb)
+{
+ var cache = Services.cache2;
+ var storage = cache.diskCacheStorage(LoadContextInfo.default, false);
+
+ function CheckCacheListener(inMemory, shouldExist)
+ {
+ this.inMemory = inMemory;
+ this.shouldExist = shouldExist;
+ this.onCacheEntryCheck = function() {
+ return Components.interfaces.nsICacheEntryOpenCallback.ENTRY_WANTED;
+ };
+
+ this.onCacheEntryAvailable = function oCEA(entry, isNew, appCache, status) {
+ if (shouldExist) {
+ ok(entry, "Entry not found");
+ is(this.inMemory, !entry.persistent, "Entry is " + (inMemory ? "" : " not ") + " in memory as expected");
+ is(status, Components.results.NS_OK, "Entry not found");
+ } else {
+ ok(!entry, "Entry found");
+ is(status, Components.results.NS_ERROR_CACHE_KEY_NOT_FOUND,
+ "Invalid error code");
+ }
+
+ setTimeout(cb, 0);
+ };
+ };
+
+ storage.asyncOpenURI(Services.io.newURI(url, null, null), "",
+ Components.interfaces.nsICacheStorage.OPEN_READONLY,
+ new CheckCacheListener(inMemory, shouldExist));
+}
+function getPopupURL() {
+ var sh = popup.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+ .getInterface(Components.interfaces.nsIWebNavigation)
+ .sessionHistory;
+
+ return sh.getEntryAtIndex(sh.index, false).URI.spec;
+}
+
+var wyciwygURL;
+function testContinue() {
+ wyciwygURL = getPopupURL();
+ is(wyciwygURL.substring(0, 10), "wyciwyg://", "Unexpected URL.");
+ popup.close()
+
+ // We have to find the entry and it must not be persisted to disk
+ checkCache(wyciwygURL, true, true, finish);
+}
+
+function waitForWyciwygDocument() {
+ try {
+ var url = getPopupURL();
+ if (url.substring(0, 10) == "wyciwyg://") {
+ setTimeout(testContinue, 0);
+ return;
+ }
+ }
+ catch (e) {
+ }
+ setTimeout(waitForWyciwygDocument, 100);
+}
+
+// Entry point from Mochikit
+function test() {
+ waitForExplicitFinish();
+
+ popup = window.open(testPath + "file_bug649778.html", "popup 0",
+ "height=200,width=200,location=yes," +
+ "menubar=yes,status=yes,toolbar=yes,dependent=yes");
+
+ waitForWyciwygDocument();
+}
diff --git a/dom/html/test/browser_content_contextmenu_userinput.js b/dom/html/test/browser_content_contextmenu_userinput.js
new file mode 100644
index 000000000..7d0387715
--- /dev/null
+++ b/dom/html/test/browser_content_contextmenu_userinput.js
@@ -0,0 +1,50 @@
+"use strict";
+
+const kPage = "http://example.org/browser/" +
+ "dom/html/test/file_content_contextmenu.html";
+
+add_task(function* () {
+ yield BrowserTestUtils.withNewTab({
+ gBrowser,
+ url: kPage
+ }, function*(aBrowser) {
+ let contextMenu = document.getElementById("contentAreaContextMenu");
+ ok(contextMenu, "Got context menu");
+
+ info("Open context menu");
+ is(contextMenu.state, "closed", "Should not have opened context menu");
+ let popupShownPromise = promiseWaitForEvent(window, "popupshown");
+ EventUtils.synthesizeMouse(aBrowser, window.innerWidth / 3,
+ window.innerHeight / 3,
+ {type: "contextmenu", button: 2}, window);
+ yield popupShownPromise;
+ is(contextMenu.state, "open", "Should have opened context menu");
+
+ let pageMenuSep = document.getElementById("page-menu-separator");
+ ok(pageMenuSep && !pageMenuSep.hidden,
+ "Page menu separator should be shown");
+
+ let testMenuSep = pageMenuSep.previousSibling;
+ ok(testMenuSep && !testMenuSep.hidden,
+ "User-added menu separator should be shown");
+
+ let testMenuItem = testMenuSep.previousSibling;
+ is(testMenuItem.label, "Test Context Menu Click", "Got context menu item");
+
+ let promiseCtxMenuClick = ContentTask.spawn(aBrowser, null, function*() {
+ yield new Promise(resolve => {
+ let Ci = Components.interfaces;
+ let windowUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils);
+ let menuitem = content.document.getElementById("menuitem");
+ menuitem.addEventListener("click", function() {
+ Assert.ok(windowUtils.isHandlingUserInput,
+ "Content menu click should be a user input");
+ resolve();
+ });
+ });
+ });
+ EventUtils.synthesizeMouseAtCenter(testMenuItem, {}, window);
+ yield promiseCtxMenuClick;
+ });
+});
diff --git a/dom/html/test/browser_fullscreen-api-keys.js b/dom/html/test/browser_fullscreen-api-keys.js
new file mode 100644
index 000000000..92358efee
--- /dev/null
+++ b/dom/html/test/browser_fullscreen-api-keys.js
@@ -0,0 +1,170 @@
+"use strict";
+
+/** Test for Bug 545812 **/
+
+// List of key codes which should exit full-screen mode.
+const kKeyList = [
+ { code: "VK_ESCAPE", suppressed: true},
+ { code: "VK_F11", suppressed: false},
+];
+
+function frameScript() {
+ let doc = content.document;
+ addMessageListener("Test:RequestFullscreen", () => {
+ doc.body.requestFullscreen();
+ });
+ addMessageListener("Test:DispatchUntrustedKeyEvents", msg => {
+ var evt = new content.CustomEvent("Test:DispatchKeyEvents", {
+ detail: { code: msg.data }
+ });
+ content.dispatchEvent(evt);
+ });
+
+ doc.addEventListener("fullscreenchange", () => {
+ sendAsyncMessage("Test:FullscreenChanged", !!doc.fullscreenElement);
+ });
+
+ function keyHandler(evt) {
+ sendAsyncMessage("Test:KeyReceived", {
+ type: evt.type,
+ keyCode: evt.keyCode
+ });
+ }
+ doc.addEventListener("keydown", keyHandler, true);
+ doc.addEventListener("keyup", keyHandler, true);
+ doc.addEventListener("keypress", keyHandler, true);
+
+ function waitUntilActive() {
+ if (doc.docShell.isActive && doc.hasFocus()) {
+ sendAsyncMessage("Test:Activated");
+ } else {
+ setTimeout(waitUntilActive, 10);
+ }
+ }
+ waitUntilActive();
+}
+
+var gMessageManager;
+
+function listenOneMessage(aMsg, aListener) {
+ function listener({ data }) {
+ gMessageManager.removeMessageListener(aMsg, listener);
+ aListener(data);
+ }
+ gMessageManager.addMessageListener(aMsg, listener);
+}
+
+function promiseOneMessage(aMsg) {
+ return new Promise(resolve => listenOneMessage(aMsg, resolve));
+}
+
+function captureUnexpectedFullscreenChange() {
+ ok(false, "Caught an unexpected fullscreen change");
+}
+
+function* temporaryRemoveUnexpectedFullscreenChangeCapture(callback) {
+ gMessageManager.removeMessageListener(
+ "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+ yield* callback();
+ gMessageManager.addMessageListener(
+ "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+}
+
+function captureUnexpectedKeyEvent(type) {
+ ok(false, `Caught an unexpected ${type} event`);
+}
+
+function* temporaryRemoveUnexpectedKeyEventCapture(callback) {
+ gMessageManager.removeMessageListener(
+ "Test:KeyReceived", captureUnexpectedKeyEvent);
+ yield* callback();
+ gMessageManager.addMessageListener(
+ "Test:KeyReceived", captureUnexpectedKeyEvent);
+}
+
+function receiveExpectedKeyEvents(keyCode) {
+ return new Promise(resolve => {
+ let events = ["keydown", "keypress", "keyup"];
+ function listener({ data }) {
+ let expected = events.shift();
+ is(data.type, expected, `Should receive a ${expected} event`);
+ is(data.keyCode, keyCode,
+ `Should receive the event with key code ${keyCode}`);
+ if (!events.length) {
+ gMessageManager.removeMessageListener("Test:KeyReceived", listener);
+ resolve();
+ }
+ }
+ gMessageManager.addMessageListener("Test:KeyReceived", listener);
+ });
+}
+
+const kPage = "http://example.org/browser/" +
+ "dom/html/test/file_fullscreen-api-keys.html";
+
+add_task(function* () {
+ yield pushPrefs(
+ ["full-screen-api.transition-duration.enter", "0 0"],
+ ["full-screen-api.transition-duration.leave", "0 0"]);
+
+ let tab = gBrowser.addTab(kPage);
+ let browser = tab.linkedBrowser;
+ gBrowser.selectedTab = tab;
+ registerCleanupFunction(() => gBrowser.removeTab(tab));
+ yield waitForDocLoadComplete();
+
+ gMessageManager = browser.messageManager;
+ gMessageManager.loadFrameScript(
+ "data:,(" + frameScript.toString() + ")();", false);
+
+ // Wait for the document being actived, so that
+ // fullscreen request won't be denied.
+ yield promiseOneMessage("Test:Activated");
+
+ // Register listener to capture unexpected events
+ gMessageManager.addMessageListener(
+ "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+ gMessageManager.addMessageListener(
+ "Test:KeyReceived", captureUnexpectedKeyEvent);
+ registerCleanupFunction(() => {
+ gMessageManager.removeMessageListener(
+ "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+ gMessageManager.removeMessageListener(
+ "Test:KeyReceived", captureUnexpectedKeyEvent);
+ });
+
+ for (let {code, suppressed} of kKeyList) {
+ var keyCode = KeyEvent["DOM_" + code];
+ info(`Test keycode ${code} (${keyCode})`);
+
+ info("Enter fullscreen");
+ yield* temporaryRemoveUnexpectedFullscreenChangeCapture(function* () {
+ gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
+ let state = yield promiseOneMessage("Test:FullscreenChanged");
+ ok(state, "The content should have entered fullscreen");
+ ok(document.fullscreenElement,
+ "The chrome should also be in fullscreen");
+ });
+
+ info("Dispatch untrusted key events from content");
+ yield* temporaryRemoveUnexpectedKeyEventCapture(function* () {
+ let promiseExpectedKeyEvents = receiveExpectedKeyEvents(keyCode);
+ gMessageManager.sendAsyncMessage("Test:DispatchUntrustedKeyEvents", code);
+ yield promiseExpectedKeyEvents;
+ });
+
+ info("Send trusted key events");
+ yield* temporaryRemoveUnexpectedFullscreenChangeCapture(function* () {
+ yield* temporaryRemoveUnexpectedKeyEventCapture(function* () {
+ let promiseExpectedKeyEvents = suppressed ?
+ Promise.resolve() : receiveExpectedKeyEvents(keyCode);
+ EventUtils.synthesizeKey(code, {});
+ yield promiseExpectedKeyEvents;
+ let state = yield promiseOneMessage("Test:FullscreenChanged");
+ ok(!state, "The content should have exited fullscreen");
+ ok(!document.fullscreenElement,
+ "The chrome should also have exited fullscreen");
+ });
+ });
+ }
+});
diff --git a/dom/html/test/browser_fullscreen-contextmenu-esc.js b/dom/html/test/browser_fullscreen-contextmenu-esc.js
new file mode 100644
index 000000000..bbc741e47
--- /dev/null
+++ b/dom/html/test/browser_fullscreen-contextmenu-esc.js
@@ -0,0 +1,107 @@
+"use strict";
+
+function frameScript() {
+ addMessageListener("Test:RequestFullscreen", () => {
+ content.document.body.requestFullscreen();
+ });
+ content.document.addEventListener("fullscreenchange", () => {
+ sendAsyncMessage("Test:FullscreenChanged",
+ !!content.document.fullscreenElement);
+ });
+ addMessageListener("Test:QueryFullscreenState", () => {
+ sendAsyncMessage("Test:FullscreenState",
+ !!content.document.fullscreenElement);
+ });
+ function waitUntilActive() {
+ let doc = content.document;
+ if (doc.docShell.isActive && doc.hasFocus()) {
+ sendAsyncMessage("Test:Activated");
+ } else {
+ setTimeout(waitUntilActive, 10);
+ }
+ }
+ waitUntilActive();
+}
+
+var gMessageManager;
+
+function listenOneMessage(aMsg, aListener) {
+ function listener({ data }) {
+ gMessageManager.removeMessageListener(aMsg, listener);
+ aListener(data);
+ }
+ gMessageManager.addMessageListener(aMsg, listener);
+}
+
+function promiseOneMessage(aMsg) {
+ return new Promise(resolve => listenOneMessage(aMsg, resolve));
+}
+
+function captureUnexpectedFullscreenChange() {
+ ok(false, "Caught an unexpected fullscreen change");
+}
+
+const kPage = "http://example.org/browser/dom/html/test/dummy_page.html";
+
+add_task(function* () {
+ yield pushPrefs(
+ ["full-screen-api.transition-duration.enter", "0 0"],
+ ["full-screen-api.transition-duration.leave", "0 0"]);
+
+ let tab = gBrowser.addTab(kPage);
+ registerCleanupFunction(() => gBrowser.removeTab(tab));
+ let browser = tab.linkedBrowser;
+ gBrowser.selectedTab = tab;
+ yield waitForDocLoadComplete();
+
+ gMessageManager = browser.messageManager;
+ gMessageManager.loadFrameScript(
+ "data:,(" + frameScript.toString() + ")();", false);
+
+ // Wait for the document being activated, so that
+ // fullscreen request won't be denied.
+ yield promiseOneMessage("Test:Activated");
+
+ let contextMenu = document.getElementById("contentAreaContextMenu");
+ ok(contextMenu, "Got context menu");
+
+ let state;
+ info("Enter DOM fullscreen");
+ gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
+ state = yield promiseOneMessage("Test:FullscreenChanged");
+ ok(state, "The content should have entered fullscreen");
+ ok(document.fullscreenElement, "The chrome should also be in fullscreen");
+ gMessageManager.addMessageListener(
+ "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+
+ info("Open context menu");
+ is(contextMenu.state, "closed", "Should not have opened context menu");
+ let popupShownPromise = promiseWaitForEvent(window, "popupshown");
+ EventUtils.synthesizeMouse(browser, screen.width / 2, screen.height / 2,
+ {type: "contextmenu", button: 2}, window);
+ yield popupShownPromise;
+ is(contextMenu.state, "open", "Should have opened context menu");
+
+ info("Send the first escape");
+ let popupHidePromise = promiseWaitForEvent(window, "popuphidden");
+ EventUtils.synthesizeKey("VK_ESCAPE", {});
+ yield popupHidePromise;
+ is(contextMenu.state, "closed", "Should have closed context menu");
+
+ // Wait a small time to confirm that the first ESC key
+ // does not exit fullscreen.
+ yield new Promise(resolve => setTimeout(resolve, 1000));
+ gMessageManager.sendAsyncMessage("Test:QueryFullscreenState");
+ state = yield promiseOneMessage("Test:FullscreenState");
+ ok(state, "The content should still be in fullscreen");
+ ok(document.fullscreenElement, "The chrome should still be in fullscreen");
+
+ info("Send the second escape");
+ gMessageManager.removeMessageListener(
+ "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+ let fullscreenExitPromise = promiseOneMessage("Test:FullscreenChanged");
+ EventUtils.synthesizeKey("VK_ESCAPE", {});
+ state = yield fullscreenExitPromise;
+ ok(!state, "The content should have exited fullscreen");
+ ok(!document.fullscreenElement, "The chrome should have exited fullscreen");
+});
diff --git a/dom/html/test/bug100533_iframe.html b/dom/html/test/bug100533_iframe.html
new file mode 100644
index 000000000..ddf58a15c
--- /dev/null
+++ b/dom/html/test/bug100533_iframe.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+<title></title>
+</head>
+<body>
+<form method='get' action='bug100533_load.html' id='b'><input type="submit"/></form>
+</body>
+</html>
diff --git a/dom/html/test/bug100533_load.html b/dom/html/test/bug100533_load.html
new file mode 100644
index 000000000..99cf26640
--- /dev/null
+++ b/dom/html/test/bug100533_load.html
@@ -0,0 +1,14 @@
+<html>
+<head>
+<title></title>
+</head>
+
+
+<body onload="parent.submitted();">
+
+<span id="foo"></span>
+
+
+
+</body>
+</html>
diff --git a/dom/html/test/bug1260704_iframe.html b/dom/html/test/bug1260704_iframe.html
new file mode 100644
index 000000000..41d238958
--- /dev/null
+++ b/dom/html/test/bug1260704_iframe.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript">
+ var noDefault = (location.search.indexOf("noDefault=true") !== -1);
+ var isMap = (location.search.indexOf("isMap=true") !== -1);
+
+ window.addEventListener("load", () => {
+ let image = document.getElementById("testImage");
+ isMap ? image.setAttribute("ismap", "") : image.removeAttribute("ismap");
+ image.addEventListener("click", event => {
+ if (noDefault) {
+ ok(true, "image element prevents default");
+ event.preventDefault();
+ }
+ }, false);
+
+ window.addEventListener("click", event => {
+ ok(true, "expected prevent default = " + noDefault);
+ ok(true, "actual prevent default = " + event.defaultPrevented);
+ ok(event.defaultPrevented == noDefault, "PreventDefault should work fine");
+ if (noDefault) {
+ window.parent.postMessage("finished", "http://mochi.test:8888");
+ }
+ }, false);
+ window.parent.postMessage("started", "http://mochi.test:8888");
+ }, false);
+ </script>
+</head>
+<body>
+<a href="bug1260704_iframe_empty.html">
+ <img id="testImage" src="file_bug1260704.png" width="100" height="100"/>
+</a>
+</body>
+</html>
diff --git a/dom/html/test/bug1260704_iframe_empty.html b/dom/html/test/bug1260704_iframe_empty.html
new file mode 100644
index 000000000..3c90f9f13
--- /dev/null
+++ b/dom/html/test/bug1260704_iframe_empty.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript">
+ window.addEventListener("load", () => {
+ window.parent.postMessage("empty_frame_loaded", "http://mochi.test:8888");
+ }, false);
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/dom/html/test/bug1292522_iframe.html b/dom/html/test/bug1292522_iframe.html
new file mode 100644
index 000000000..99a3369d0
--- /dev/null
+++ b/dom/html/test/bug1292522_iframe.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html><head><title>iframe</title></head>
+ <body>
+ <p>var testvar = "testiframe"</p>
+ <script>
+ document.domain='example.org';
+ var testvar = "testiframe";
+ </script>
+ </body>
+</html>
diff --git a/dom/html/test/bug1292522_page.html b/dom/html/test/bug1292522_page.html
new file mode 100644
index 000000000..9570f12d2
--- /dev/null
+++ b/dom/html/test/bug1292522_page.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Test for Bug 1292522</title>
+ <script>
+ var check_var = function() {
+ opener.postMessage(document.getElementsByTagName('iframe')[0].contentWindow.testvar, "http://mochi.test:8888");
+ }
+ </script>
+ </head>
+ <body>
+ <iframe src="http://test2.example.org:80/tests/dom/html/test/bug1292522_iframe.html" onload="document.domain='example.org';check_var();"></iframe>
+ </body>
+</html>
diff --git a/dom/html/test/bug1315146-iframe.html b/dom/html/test/bug1315146-iframe.html
new file mode 100644
index 000000000..280db5305
--- /dev/null
+++ b/dom/html/test/bug1315146-iframe.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<script>
+document.domain = "example.org";
+</script>
diff --git a/dom/html/test/bug1315146-main.html b/dom/html/test/bug1315146-main.html
new file mode 100644
index 000000000..e9f356dda
--- /dev/null
+++ b/dom/html/test/bug1315146-main.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<iframe src="http://example.org/tests/dom/html/test/bug1315146-iframe.html"></iframe>
+<input value="test">
+<script>
+document.domain = "example.org";
+onload = function() {
+ let iframe = document.querySelector("iframe");
+ let input = document.querySelector("input");
+ input.selectionStart = input.selectionEnd = 2;
+ document.body.style.overflow = "scroll";
+ iframe.contentDocument.body.offsetWidth;
+ opener.postMessage({start: input.selectionStart,
+ end: input.selectionEnd}, "*");
+}
+</script>
diff --git a/dom/html/test/bug196523-subframe.html b/dom/html/test/bug196523-subframe.html
new file mode 100644
index 000000000..ac53572a7
--- /dev/null
+++ b/dom/html/test/bug196523-subframe.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<script>
+ function checkDomain(str, msg) {
+ window.parent.postMessage((str == document.domain) + ";" +msg,
+ "http://mochi.test:8888");
+ }
+
+ function reportException(msg) {
+ window.parent.postMessage(false + ";" + msg, "http://mochi.test:8888");
+ }
+
+ var win1;
+ try {
+ win1 = window.open("", "", "width=100,height=100");
+ var otherDomain1 = win1.document.domain;
+ win1.close();
+ checkDomain(otherDomain1, "Opened document should have our domain");
+ } catch(e) {
+ reportException("Exception getting document.domain: " + e);
+ } finally {
+ win1.close();
+ }
+
+ document.domain = "example.org";
+
+ var win2;
+ try {
+ win2 = window.open("", "", "width=100,height=100");
+ var otherDomain2 = win2.document.domain;
+ checkDomain(otherDomain2, "Opened document should have our domain");
+ win2.close();
+ } catch(e) {
+ reportException("Exception getting document.domain after domain set: " + e);
+ } finally {
+ win2.close();
+ }
+</script>
diff --git a/dom/html/test/bug199692-nested-d2.html b/dom/html/test/bug199692-nested-d2.html
new file mode 100644
index 000000000..70064efe7
--- /dev/null
+++ b/dom/html/test/bug199692-nested-d2.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=199692
+-->
+<head>
+ <title>Nested, nested iframe for bug 199692 tests</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+</head>
+<body>
+ <div id="nest2div" style="border: 2px dotted blue;">nested, depth 2</div>
+</body>
+</html>
+
diff --git a/dom/html/test/bug199692-nested.html b/dom/html/test/bug199692-nested.html
new file mode 100644
index 000000000..27201a953
--- /dev/null
+++ b/dom/html/test/bug199692-nested.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=199692
+-->
+<head>
+ <title>Nested iframe for bug 199692 tests</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+</head>
+<body>
+ <div id="nest1div" style="border: 2px dotted green;">nested, depth 1</div>
+ <iframe src="bug199692-nested-d2.html"></iframe>
+</body>
+</html>
+
diff --git a/dom/html/test/bug199692-popup.html b/dom/html/test/bug199692-popup.html
new file mode 100644
index 000000000..29512823e
--- /dev/null
+++ b/dom/html/test/bug199692-popup.html
@@ -0,0 +1,188 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=199692
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Popup in test for Bug 199692</title>
+ <style type="text/css">
+#content * {
+ border: 2px solid black;
+ margin: 2px;
+ clear: both;
+ height: 20px;
+ overflow: hidden;
+}
+
+#txt, #static, #fixed, #absolute, #relative, #hidden, #float, #empty, #static, #relative {
+ width: 200px !important;
+}
+ </style>
+
+</head>
+<!--
+Elements are styled in such a way that they don't overlap visually
+unless they also overlap structurally.
+
+This file is designed to be opened from test_bug199692.html in a popup
+window, to guarantee that the window in which document.elementFromPoint runs
+is large enough to display all the elements being tested.
+-->
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=199692">Mozilla Bug 199692</a>
+
+<div id="content" style="width: 500px; background-color: #ccc;">
+
+<!-- element containing text -->
+<div id="txt" style="height: 30px;">txt</div>
+
+<!-- element not containing text -->
+<div id="empty" style="border: 2px solid blue;"></div>
+
+<!-- element with only whitespace -->
+<p id="whitespace" style="border: 2px solid magenta;"> </p>
+
+<!-- position: static -->
+<span id="static" style="position: static; border-color: green;">static</span>
+
+<!-- floated element -->
+<div id="float" style="border-color: red; float: right;">float</div>
+
+<!-- position: fixed -->
+<span id="fixed" style="position: fixed; top: 500px; left: 100px; border: 3px solid yellow;">fixed</span>
+
+<!-- position: absolute -->
+<span id="absolute" style="position: absolute; top: 550px; left: 150px; border-color: orange;">abs</span>
+
+<!-- position: relative -->
+<div id="relative" style="position: relative; top: 200px; border-color: teal;">rel</div>
+
+<!-- visibility: hidden -->
+<div id="hidden-wrapper" style="border: 1px dashed teal;">
+ <div id="hidden" style="opacity: 0.5; background-color: blue; visibility:hidden;">hidden</div>
+</div>
+
+<!-- iframe (within iframe) -->
+<iframe id="our-iframe" src="bug199692-nested.html" style="height: 100px; overflow: scroll;"></iframe>
+
+<input type="textbox" id="textbox" value="textbox"></input>
+</div>
+
+<!-- interaction with scrolling -->
+<iframe id="scrolled-iframe"
+ src="bug199692-scrolled.html#down"
+ style="position: absolute; top: 345px; left: 325px; height: 200px; width: 200px"></iframe>
+
+<script type="application/javascript">
+
+var SimpleTest = window.opener.SimpleTest;
+function ok() { window.opener.ok.apply(window.opener, arguments); }
+function is() { window.opener.is.apply(window.opener, arguments); }
+function todo() { window.opener.todo.apply(window.opener, arguments); }
+function todo_is() { window.opener.todo_is.apply(window.opener, arguments); }
+function $(id) { return document.getElementById(id); }
+
+/**
+ * Like is, but for tests which don't always succeed or always fail on all
+ * platforms.
+ */
+function random_fail(a, b, m)
+{
+ if (a != b)
+ todo_is(a, b, m);
+ else
+ is(a, b, m);
+}
+
+/* Test for Bug 199692 */
+
+function getCoords(elt)
+{
+ var x = 0, y = 0;
+
+ do
+ {
+ x += elt.offsetLeft;
+ y += elt.offsetTop;
+ } while ((elt = elt.offsetParent));
+
+ return { x: x, y: y };
+}
+
+var elts = ["txt", "empty", "whitespace", "static", "fixed", "absolute",
+ "relative", "float", "textbox"];
+
+function testPoints()
+{
+ ok('elementFromPoint' in document, "document.elementFromPoint must exist");
+ ok(typeof document.elementFromPoint === "function", "must be a function");
+
+ var doc = document;
+ doc.pt = doc.elementFromPoint; // for shorter lines
+ is(doc.pt(-1, 0), null, "Negative coordinates (-1, 0) should return null");
+ is(doc.pt(0, -1), null, "Negative coordinates (0, -1) should return null");
+ is(doc.pt(-1, -1), null, "Negative coordinates (-1, -1) should return null");
+
+ var pos;
+ for (var i = 0; i < elts.length; i++)
+ {
+ var id = elts[i];
+ var elt = $(id);
+
+ // The upper left corner of an element (with a moderate offset) will
+ // usually contain text, and the lower right corner usually won't.
+ var pos = getCoords(elt);
+ var x = pos.x, y = pos.y;
+ var w = elt.offsetWidth, h = elt.offsetHeight;
+
+ var d = 5;
+ is(doc.pt(x + d, y + d), elt,
+ "(" + (x + d) + "," + (y + d) + ") IDs should match (upper left " +
+ "corner of " + id + ")");
+ is(doc.pt(x + w - d, y + h - d), elt,
+ "(" + (x + w - d) + "," + (y + h - d) + ") IDs should match (lower " +
+ "right corner of " + id + ")");
+ }
+
+ // content
+ var c = $("content");
+ pos = getCoords(c);
+ x = pos.x + c.offsetWidth / 2;
+ y = pos.y;
+
+ // This fails on some platforms but not others for unknown reasons
+ random_fail(doc.pt(x, y), c, "Point to right of #txt should be #content");
+ is(doc.pt(x, y + 1), c, "Point to right of #txt should be #content");
+ random_fail(doc.pt(x + 1, y), c, "Point to right of #txt should be #content");
+ is(doc.pt(x + 1, y + 1), c, "Point to right of #txt should be #content");
+
+ // hidden
+ c = $("hidden");
+ pos = getCoords(c);
+ x = pos.x, y = pos.y;
+ is(doc.pt(x, y), $("hidden-wrapper"),
+ "Hit testing should bypass hidden elements.");
+
+ // iframe nested
+ var iframe = $("our-iframe");
+ pos = getCoords(iframe);
+ x = pos.x, y = pos.y;
+ is(doc.pt(x + 20, y + 20), $("our-iframe"),
+ "Element from nested iframe returned is from calling document");
+ // iframe, doubly nested
+ is(doc.pt(x + 60, y + 60), $("our-iframe"),
+ "Element from doubly nested iframe returned is from calling document");
+
+ // scrolled iframe tests
+ $("scrolled-iframe").contentWindow.runTests();
+
+ SimpleTest.finish();
+ window.close();
+}
+
+window.onload = testPoints;
+</script>
+</body>
+</html>
+
diff --git a/dom/html/test/bug199692-scrolled.html b/dom/html/test/bug199692-scrolled.html
new file mode 100644
index 000000000..f13bf7ab1
--- /dev/null
+++ b/dom/html/test/bug199692-scrolled.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=199692
+-->
+<head>
+ <title>Scrolled page for bug 199692 tests</title>
+ <style type="text/css">
+/* Disable default margins/padding/borders so (0, 0) gets a div. */
+* { margin: 0; padding: 0; border: 0; }
+ </style>
+ <script type="application/javascript">
+function $(id) { return document.getElementById(id); }
+
+function runTests()
+{
+ var is = window.parent.is;
+
+ is(document.elementFromPoint(0, 0), $("down"),
+ "document.elementFromPoint not respecting scrolling?");
+ is(document.elementFromPoint(200, 200), null,
+ "should have returned null for a not-visible point");
+ is(document.elementFromPoint(3, -5), null,
+ "should have returned null for a not-visible point");
+}
+ </script>
+</head>
+<!-- This page is loaded in a 200px-square iframe scrolled to #down. -->
+<body>
+<div style="height: 150px; background: lightblue;">first</div>
+<div id="down" style="height: 250px; background: lightgreen;">second</div>
+</body>
+</html>
+
diff --git a/dom/html/test/bug242709_iframe.html b/dom/html/test/bug242709_iframe.html
new file mode 100644
index 000000000..1ee3320ae
--- /dev/null
+++ b/dom/html/test/bug242709_iframe.html
@@ -0,0 +1,20 @@
+<html>
+<head>
+<title></title>
+<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<script type="text/javascript">
+function submitIframeForm () {
+ document.getElementById('b').submit();
+ document.getElementById('thebutton').disabled = true;
+}
+</script>
+
+</head>
+<body onload="sendMouseEvent({type:'click'}, 'thebutton')">
+
+<form method="get" action="bug242709_load.html" id="b">
+<input type="submit" onclick="submitIframeForm()" id="thebutton">
+</form>
+
+</body>
+</html>
diff --git a/dom/html/test/bug242709_load.html b/dom/html/test/bug242709_load.html
new file mode 100644
index 000000000..c9be79b24
--- /dev/null
+++ b/dom/html/test/bug242709_load.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+<title></title>
+</head>
+
+<body onload="parent.submitted();">
+
+<span id="foo"></span>
+
+</body>
+</html>
diff --git a/dom/html/test/bug277724_iframe1.html b/dom/html/test/bug277724_iframe1.html
new file mode 100644
index 000000000..d0d881b76
--- /dev/null
+++ b/dom/html/test/bug277724_iframe1.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!-- Use an unload handler to prevent bfcache from messing with us -->
+<body onunload="parent.childUnloaded = true;">
+ <select id="select">
+ <option>aaa</option>
+ <option>bbbb</option>
+ </select>
+
+ <textarea id="textarea">
+ </textarea>
+
+ <input type="text" id="text">
+ <input type="password" id="password">
+ <input type="checkbox" id="checkbox">
+ <input type="radio" id="radio">
+ <input type="image" id="image">
+ <input type="submit" id="submit">
+ <input type="reset" id="reset">
+ <input type="button" id="button input">
+ <input type="hidden" id="hidden">
+ <input type="file" id="file">
+
+ <button type="submit" id="submit button"></button>
+ <button type="reset" id="reset button"></button>
+ <button type="button" id="button"></button>
+</body>
+</html>
diff --git a/dom/html/test/bug277724_iframe2.xhtml b/dom/html/test/bug277724_iframe2.xhtml
new file mode 100644
index 000000000..14423aa06
--- /dev/null
+++ b/dom/html/test/bug277724_iframe2.xhtml
@@ -0,0 +1,27 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!-- Use an unload handler to prevent bfcache from messing with us -->
+<body onunload="parent.childUnloaded = true;">
+ <select id="select">
+ <option>aaa</option>
+ <option>bbbb</option>
+ </select>
+
+ <textarea id="textarea">
+ </textarea>
+
+ <input type="text" id="text" />
+ <input type="password" id="password" />
+ <input type="checkbox" id="checkbox" />
+ <input type="radio" id="radio" />
+ <input type="image" id="image" />
+ <input type="submit" id="submit" />
+ <input type="reset" id="reset" />
+ <input type="button" id="button input" />
+ <input type="hidden" id="hidden" />
+ <input type="file" id="file" />
+
+ <button type="submit" id="submit button"></button>
+ <button type="reset" id="reset button"></button>
+ <button type="button" id="button"></button>
+</body>
+</html>
diff --git a/dom/html/test/bug277890_iframe.html b/dom/html/test/bug277890_iframe.html
new file mode 100644
index 000000000..890ff839e
--- /dev/null
+++ b/dom/html/test/bug277890_iframe.html
@@ -0,0 +1,20 @@
+<html>
+<head>
+<title></title>
+<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<script type="text/javascript">
+function submitIframeForm () {
+ document.getElementById('b').submit();
+ document.getElementById('thebutton').disabled = true;
+}
+</script>
+
+</head>
+<body onload="sendMouseEvent({type:'click'}, 'thebutton')">
+
+<form method="get" action="bug277890_load.html" id="b">
+<button onclick="submitIframeForm()" id="thebutton">Submit</button>
+</form>
+
+</body>
+</html>
diff --git a/dom/html/test/bug277890_load.html b/dom/html/test/bug277890_load.html
new file mode 100644
index 000000000..c9be79b24
--- /dev/null
+++ b/dom/html/test/bug277890_load.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+<title></title>
+</head>
+
+<body onload="parent.submitted();">
+
+<span id="foo"></span>
+
+</body>
+</html>
diff --git a/dom/html/test/bug340800_iframe.txt b/dom/html/test/bug340800_iframe.txt
new file mode 100644
index 000000000..369dfe744
--- /dev/null
+++ b/dom/html/test/bug340800_iframe.txt
@@ -0,0 +1,4 @@
+Line 1.
+Line 2.
+Line 3.
+Line 4.
diff --git a/dom/html/test/bug369370-popup.png b/dom/html/test/bug369370-popup.png
new file mode 100644
index 000000000..9063d1264
--- /dev/null
+++ b/dom/html/test/bug369370-popup.png
Binary files differ
diff --git a/dom/html/test/bug372098-link-target.html b/dom/html/test/bug372098-link-target.html
new file mode 100644
index 000000000..b22b8e020
--- /dev/null
+++ b/dom/html/test/bug372098-link-target.html
@@ -0,0 +1,7 @@
+<html>
+<script type="text/javascript">
+
+parent.callback(location.search.substr(1));
+
+</script>
+</html>
diff --git a/dom/html/test/bug392567.jar b/dom/html/test/bug392567.jar
new file mode 100644
index 000000000..bca06515d
--- /dev/null
+++ b/dom/html/test/bug392567.jar
Binary files differ
diff --git a/dom/html/test/bug392567.jar^headers^ b/dom/html/test/bug392567.jar^headers^
new file mode 100644
index 000000000..28b8aa0a5
--- /dev/null
+++ b/dom/html/test/bug392567.jar^headers^
@@ -0,0 +1 @@
+Content-Type: application/java-archive
diff --git a/dom/html/test/bug441930_iframe.html b/dom/html/test/bug441930_iframe.html
new file mode 100644
index 000000000..532cd5c36
--- /dev/null
+++ b/dom/html/test/bug441930_iframe.html
@@ -0,0 +1,27 @@
+<html>
+<body>
+ The content of this <code>textarea</code> should not disappear on page reload:<br />
+ <textarea>This text should not disappear on page reload!</textarea>
+ <script>
+ var ta = document.getElementsByTagName("textarea").item(0);
+ if (!parent.reloaded) {
+ parent.reloaded = true;
+ ta.disabled = true;
+ location.reload();
+ } else {
+ // Primary regression test:
+ parent.isnot(ta.value, "",
+ "Content of dynamically disabled textarea disappeared on page reload.");
+
+ // Bonus regression test: changing the textarea's defaultValue after
+ // reloading should also update the textarea's value.
+ var newDefaultValue = "new default value";
+ ta.defaultValue = newDefaultValue;
+ parent.is(ta.value, newDefaultValue,
+ "Changing the defaultValue attribute of a textarea fails to update its value attribute.");
+
+ parent.SimpleTest.finish();
+ }
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/bug445004-inner.html b/dom/html/test/bug445004-inner.html
new file mode 100644
index 000000000..b946520ea
--- /dev/null
+++ b/dom/html/test/bug445004-inner.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <base href="http://test1.example.org/tests/dom/html/test/bug445004-inner.html">
+ <script src="bug445004-inner.js"></script>
+ </head>
+ <body>
+ <iframe name="w" id="w" width="100" height="100"></iframe>
+ <iframe name="x" id="x" width="100" height="100"></iframe>
+ <iframe name="y" id="y" width="100" height="100"></iframe>
+ <iframe name="z" id="z" width="100" height="100"></iframe>
+ <img src="test1.example.org.png">
+ </body>
+</html>
diff --git a/dom/html/test/bug445004-inner.js b/dom/html/test/bug445004-inner.js
new file mode 100644
index 000000000..3675f8e69
--- /dev/null
+++ b/dom/html/test/bug445004-inner.js
@@ -0,0 +1,23 @@
+document.domain = "example.org";
+function $(str) { return document.getElementById(str); }
+function hookLoad(str) {
+ $(str).onload = function() { window.parent.parent.postMessage('end', '*'); };
+ window.parent.parent.postMessage('start', '*');
+}
+window.onload = function() {
+ hookLoad("w");
+ $("w").contentWindow.location.href = "test1.example.org.png";
+ hookLoad("x");
+ var doc = $("x").contentDocument;
+ doc.write('<img src="test1.example.org.png">');
+ doc.close();
+};
+function doIt() {
+ hookLoad("y");
+ $("y").contentWindow.location.href = "example.org.png";
+ hookLoad("z");
+ var doc = $("z").contentDocument;
+ doc.write('<img src="example.org.png">');
+ doc.close();
+}
+window.addEventListener("message", doIt, false); \ No newline at end of file
diff --git a/dom/html/test/bug445004-outer-abs.html b/dom/html/test/bug445004-outer-abs.html
new file mode 100644
index 000000000..8a93ef2b7
--- /dev/null
+++ b/dom/html/test/bug445004-outer-abs.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <base href="http://example.org/tests/dom/html/test/bug445004-outer.html">
+ <script>document.domain = "example.org"</script>
+ </head>
+ <body>
+ <iframe width="500" height="200" src="http://test1.example.org/tests/dom/html/test/bug445004-inner.html"
+ onload="window.frames[0].doIt()"></iframe>
+ </body>
+</html>
diff --git a/dom/html/test/bug445004-outer-rel.html b/dom/html/test/bug445004-outer-rel.html
new file mode 100644
index 000000000..096733889
--- /dev/null
+++ b/dom/html/test/bug445004-outer-rel.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <base href="http://example.org/tests/dom/html/test/bug445004-outer.html">
+ <script>document.domain = "example.org"</script>
+ </head>
+ <body>
+ <iframe width="500" height="200" src="bug445004-inner.html"
+ onload="window.frames[0].doIt()"></iframe>
+ </body>
+</html>
diff --git a/dom/html/test/bug445004-outer-write.html b/dom/html/test/bug445004-outer-write.html
new file mode 100644
index 000000000..be6e37b6d
--- /dev/null
+++ b/dom/html/test/bug445004-outer-write.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <base href="http://example.org/tests/dom/html/test/bug445004-outer.html">
+ <script>document.domain = "example.org"</script>
+ </head>
+ <body>
+ <iframe width="500" height="200" src="javascript:&quot;<!DOCTYPE html> <html> <script> function $(str) { return document.getElementById(str); } function hookLoad(str) { $(str).onload = function() { window.parent.parent.postMessage('end', '*'); }; window.parent.parent.postMessage('start', '*'); } window.onload = function() { hookLoad(\&quot;w\&quot;); $(\&quot;w\&quot;).contentWindow.location.href = \&quot;example.org.png\&quot;; hookLoad(\&quot;x\&quot;); var doc = $(\&quot;x\&quot;).contentDocument; doc.write('<img src=\&quot;example.org.png\&quot;>'); doc.close(); }; function doIt() { hookLoad(\&quot;y\&quot;); $(\&quot;y\&quot;).contentWindow.location.href = \&quot;example.org.png\&quot;; hookLoad(\&quot;z\&quot;); var doc = $(\&quot;z\&quot;).contentDocument; doc.write('<img src=\&quot;example.org.png\&quot;>'); doc.close(); } </script> <body> <iframe name=\&quot;w\&quot; id=\&quot;w\&quot; width=\&quot;100\&quot; height=\&quot;100\&quot;></iframe> <iframe name=\&quot;x\&quot; id=\&quot;x\&quot; width=\&quot;100\&quot; height=\&quot;100\&quot;></iframe> <iframe name=\&quot;y\&quot; id=\&quot;y\&quot; width=\&quot;100\&quot; height=\&quot;100\&quot;></iframe> <iframe name=\&quot;z\&quot; id=\&quot;z\&quot; width=\&quot;100\&quot; height=\&quot;100\&quot;></iframe><img src=\&quot;example.org.png\&quot;> </body> </html>&quot; "
+ onload="window.frames[0].doIt();"></iframe>
+ </body>
+</html>
diff --git a/dom/html/test/bug446483-iframe.html b/dom/html/test/bug446483-iframe.html
new file mode 100644
index 000000000..fe5a6cf9f
--- /dev/null
+++ b/dom/html/test/bug446483-iframe.html
@@ -0,0 +1,10 @@
+<script>
+function doe(){
+window.focus();
+window.getSelection().collapse(document.body, 0);
+}
+setTimeout(doe,50);
+
+setTimeout(function() {window.location.reload()}, 200);
+</script>
+<span contenteditable="true"></span>
diff --git a/dom/html/test/bug448564-echo.sjs b/dom/html/test/bug448564-echo.sjs
new file mode 100644
index 000000000..1eee116fd
--- /dev/null
+++ b/dom/html/test/bug448564-echo.sjs
@@ -0,0 +1,6 @@
+function handleRequest(request, response) {
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.setStatusLine(request.httpVersion, 200, "OK");
+
+ response.write(request.queryString);
+}
diff --git a/dom/html/test/bug448564-iframe-1.html b/dom/html/test/bug448564-iframe-1.html
new file mode 100644
index 000000000..4f3e79e5d
--- /dev/null
+++ b/dom/html/test/bug448564-iframe-1.html
@@ -0,0 +1,16 @@
+<html>
+<body>
+
+ <table>
+ <form action="bug448564-echo.sjs" method="GET">
+ <tr><td><input name="a" value="aval"></td></tr>
+ <input type="hidden" name="b" value="bval">
+ <input name="c" value="cval">
+ <tr><td><input name="d" value="dval" type="submit"></td></tr>
+ </form>
+ </table>
+
+ <script src="bug448564-submit.js"></script>
+
+</body>
+</html>
diff --git a/dom/html/test/bug448564-iframe-2.html b/dom/html/test/bug448564-iframe-2.html
new file mode 100644
index 000000000..dba19b37e
--- /dev/null
+++ b/dom/html/test/bug448564-iframe-2.html
@@ -0,0 +1,16 @@
+<html>
+<body>
+
+ <form action="bug448564-echo.sjs" method="GET">
+ <table>
+ <tr><td><input name="a" value="aval"></td></tr>
+ <input type="hidden" name="b" value="bval">
+ <input name="c" value="cval">
+ <tr><td><input name="d" value="dval" type="submit"></td></tr>
+ </table>
+ </form>
+
+ <script src="bug448564-submit.js"></script>
+
+</body>
+</html>
diff --git a/dom/html/test/bug448564-iframe-3.html b/dom/html/test/bug448564-iframe-3.html
new file mode 100644
index 000000000..64288ebb1
--- /dev/null
+++ b/dom/html/test/bug448564-iframe-3.html
@@ -0,0 +1,16 @@
+<html>
+<body>
+
+ <table>
+ <span><form action="bug448564-echo.sjs" method="GET">
+ <tr><td><input name="a" value="aval"></td></tr>
+ <input type="hidden" name="b" value="bval">
+ <input name="c" value="cval">
+ <tr><td><input name="d" value="dval" type="submit"></td></tr>
+ </form></span>
+ </table>
+
+ <script src="bug448564-submit.js"></script>
+
+</body>
+</html>
diff --git a/dom/html/test/bug448564-submit.js b/dom/html/test/bug448564-submit.js
new file mode 100644
index 000000000..34de44d4d
--- /dev/null
+++ b/dom/html/test/bug448564-submit.js
@@ -0,0 +1,4 @@
+var inputs = document.getElementsByTagName("input");
+for (var input, i = 0; input = inputs[i]; ++i)
+ if ("submit" == input.type)
+ input.click();
diff --git a/dom/html/test/bug499092.html b/dom/html/test/bug499092.html
new file mode 100644
index 000000000..0476fa4e7
--- /dev/null
+++ b/dom/html/test/bug499092.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<script>
+var title = document.createElementNS("http://www.w3.org/1999/xhtml", "aa:title");
+title.textContent = "HTML OK";
+document.documentElement.firstChild.appendChild(title);
+</script>
diff --git a/dom/html/test/bug499092.xml b/dom/html/test/bug499092.xml
new file mode 100644
index 000000000..eedd2c77b
--- /dev/null
+++ b/dom/html/test/bug499092.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<doc xmlns:aa="http://www.w3.org/1999/xhtml">
+<aa:title>XML OK</aa:title>
+</doc>
diff --git a/dom/html/test/bug514856_iframe.html b/dom/html/test/bug514856_iframe.html
new file mode 100644
index 000000000..2abf9e91e
--- /dev/null
+++ b/dom/html/test/bug514856_iframe.html
@@ -0,0 +1,21 @@
+<html>
+ <head>
+ <style>
+ html, body, a, img {
+ padding: 0px;
+ margin: 0px;
+ border: 0px;
+ }
+ img {
+ width: 100%;
+ height: 100%;
+ }
+ </style>
+ </head>
+ <body>
+ <a href="bug514856_iframe.html">
+ <img ismap="ismap"
+ src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IAAAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1JREFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jqch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0vr4MkhoXe0rZigAAAABJRU5ErkJggg==">
+ </a>
+ </body>
+</html>
diff --git a/dom/html/test/bug592641_img.jpg b/dom/html/test/bug592641_img.jpg
new file mode 100644
index 000000000..c9103b8b0
--- /dev/null
+++ b/dom/html/test/bug592641_img.jpg
Binary files differ
diff --git a/dom/html/test/bug649134/file_bug649134-1.sjs b/dom/html/test/bug649134/file_bug649134-1.sjs
new file mode 100644
index 000000000..890f8aa5e
--- /dev/null
+++ b/dom/html/test/bug649134/file_bug649134-1.sjs
@@ -0,0 +1,12 @@
+function handleRequest(request, response)
+{
+ response.seizePower();
+ var r = 'HTTP/1.1 200 OK\r\n' +
+ 'Content-Type: text/html\r\n' +
+ 'Link: < \014>; rel="stylesheet"\r\n' +
+ '\r\n' +
+ '<!-- selector {} body {display:none;} --><body>PASS</body>\r\n';
+ response.bodyOutputStream.write(r, r.length);
+ response.bodyOutputStream.flush();
+ response.finish();
+}
diff --git a/dom/html/test/bug649134/file_bug649134-2.sjs b/dom/html/test/bug649134/file_bug649134-2.sjs
new file mode 100644
index 000000000..7f005eda6
--- /dev/null
+++ b/dom/html/test/bug649134/file_bug649134-2.sjs
@@ -0,0 +1,12 @@
+function handleRequest(request, response)
+{
+ response.seizePower();
+ var r = 'HTTP/1.1 200 OK\r\n' +
+ 'Content-Type: text/html\r\n' +
+ 'Link: < \014>; rel="stylesheet",\r\n' +
+ '\r\n' +
+ '<!-- selector {} body {display:none;} --><body>PASS</body>\r\n';
+ response.bodyOutputStream.write(r, r.length);
+ response.bodyOutputStream.flush();
+ response.finish();
+}
diff --git a/dom/html/test/bug649134/index.html b/dom/html/test/bug649134/index.html
new file mode 100644
index 000000000..2f3973704
--- /dev/null
+++ b/dom/html/test/bug649134/index.html
@@ -0,0 +1,3 @@
+body {
+ display:none;
+}
diff --git a/dom/html/test/chrome.ini b/dom/html/test/chrome.ini
new file mode 100644
index 000000000..fd8009690
--- /dev/null
+++ b/dom/html/test/chrome.ini
@@ -0,0 +1,10 @@
+[DEFAULT]
+support-files =
+ file_anchor_ping.html
+ wakelock.ogg
+ wakelock.ogv
+
+[test_anchor_ping.html]
+skip-if = os == 'android'
+[test_audio_wakelock.html]
+[test_video_wakelock.html]
diff --git a/dom/html/test/dummy_page.html b/dom/html/test/dummy_page.html
new file mode 100644
index 000000000..fd238954c
--- /dev/null
+++ b/dom/html/test/dummy_page.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<title>Dummy test page</title>
+<meta charset="utf-8"/>
+</head>
+<body>
+<p>Dummy test page</p>
+</body>
+</html>
diff --git a/dom/html/test/file_anchor_ping.html b/dom/html/test/file_anchor_ping.html
new file mode 100644
index 000000000..3b9717263
--- /dev/null
+++ b/dom/html/test/file_anchor_ping.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta charset="utf-8">
+ <title>file_anchor_ping.html</title>
+ </head>
+ <body onload="document.body.firstElementChild.click()">
+ <a href="/">click me</a>
+ <script>
+ document.body.firstElementChild.ping = window.location.search.slice(1);
+ </script>
+ </body>
+</html>
diff --git a/dom/html/test/file_bug1108547-1.html b/dom/html/test/file_bug1108547-1.html
new file mode 100644
index 000000000..efc0eae49
--- /dev/null
+++ b/dom/html/test/file_bug1108547-1.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<script>
+document.cookie = "foo=bar";
+</script>
diff --git a/dom/html/test/file_bug1108547-2.html b/dom/html/test/file_bug1108547-2.html
new file mode 100644
index 000000000..af06c8c42
--- /dev/null
+++ b/dom/html/test/file_bug1108547-2.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<body onload="document.querySelector('form').submit();">
+<form action="javascript:opener.document.getElementById('result').textContent = document.cookie;" target="_blank">
+</form>
+<div id="result">not tested yet</div>
+</body>
diff --git a/dom/html/test/file_bug1108547-3.html b/dom/html/test/file_bug1108547-3.html
new file mode 100644
index 000000000..d99a2d355
--- /dev/null
+++ b/dom/html/test/file_bug1108547-3.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<body onload="document.querySelector('a').click();">
+<a href="javascript:opener.document.getElementById('result').textContent = document.cookie;" target="_blank">test</a>
+<div id="result">not tested yet</div>
+</body>
diff --git a/dom/html/test/file_bug1166138_1x.png b/dom/html/test/file_bug1166138_1x.png
new file mode 100644
index 000000000..df421453c
--- /dev/null
+++ b/dom/html/test/file_bug1166138_1x.png
Binary files differ
diff --git a/dom/html/test/file_bug1166138_2x.png b/dom/html/test/file_bug1166138_2x.png
new file mode 100644
index 000000000..6f76d4438
--- /dev/null
+++ b/dom/html/test/file_bug1166138_2x.png
Binary files differ
diff --git a/dom/html/test/file_bug1166138_def.png b/dom/html/test/file_bug1166138_def.png
new file mode 100644
index 000000000..144a2f0b9
--- /dev/null
+++ b/dom/html/test/file_bug1166138_def.png
Binary files differ
diff --git a/dom/html/test/file_bug1260704.png b/dom/html/test/file_bug1260704.png
new file mode 100644
index 000000000..df421453c
--- /dev/null
+++ b/dom/html/test/file_bug1260704.png
Binary files differ
diff --git a/dom/html/test/file_bug209275_1.html b/dom/html/test/file_bug209275_1.html
new file mode 100644
index 000000000..3f7233876
--- /dev/null
+++ b/dom/html/test/file_bug209275_1.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <base href="http://example.org" />
+</head>
+<body onload="load();">
+Initial state
+
+<script>
+function load() {
+ // Nuke and rebuild the page.
+ document.removeChild(document.documentElement);
+ var html = document.createElement("html");
+ var body = document.createElement("body");
+ html.appendChild(body);
+ var link = document.createElement("a");
+ link.href = "#";
+ link.id = "link";
+ body.appendChild(link);
+ document.appendChild(html);
+
+ // Tell our parent to have a look at us.
+ parent.gGen.next();
+}
+</script>
+
+</body>
+</html>
diff --git a/dom/html/test/file_bug209275_2.html b/dom/html/test/file_bug209275_2.html
new file mode 100644
index 000000000..36e9ff467
--- /dev/null
+++ b/dom/html/test/file_bug209275_2.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <base href="http://example.com" />
+</head>
+<body onload="load();">
+Page 2 initial state
+
+<script>
+function load() {
+ // Nuke and rebuild the page.
+ document.removeChild(document.documentElement);
+ html = document.createElement("html");
+ html.innerHTML = "<body><a href='/' id='link'>B</a></body>"
+ document.appendChild(html);
+
+ // Tell our parent to have a look at us
+ parent.gGen.next();
+}
+</script>
+
+</body>
+</html>
diff --git a/dom/html/test/file_bug209275_3.html b/dom/html/test/file_bug209275_3.html
new file mode 100644
index 000000000..254411590
--- /dev/null
+++ b/dom/html/test/file_bug209275_3.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <base href="http://example.org" />
+</head>
+<body onload="load();">
+Initial state
+
+<script>
+function load() {
+ // Nuke and rebuild the page. If document.open() clears the <base> properly,
+ // our new <base> will take precedence and the test will pass.
+ document.open();
+ document.write("<html><base href='http://mochi.test:8888' /><body>" +
+ "<a id='link' href='/'>A</a></body></html>");
+
+ // Tell our parent to have a look at us.
+ parent.gGen.next();
+}
+</script>
+
+</body>
+</html>
diff --git a/dom/html/test/file_bug297761.html b/dom/html/test/file_bug297761.html
new file mode 100644
index 000000000..5e861a00f
--- /dev/null
+++ b/dom/html/test/file_bug297761.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <base href="http://www.mozilla.org/">
+ </head>
+ <body>
+ <form action="">
+ <input type='submit' formaction="">
+ <button type='submit' formaction=""></button>
+ <input id='i' type='image' formaction="">
+ </form>
+ </body>
+</html>
diff --git a/dom/html/test/file_bug417760.png b/dom/html/test/file_bug417760.png
new file mode 100644
index 000000000..743292dc6
--- /dev/null
+++ b/dom/html/test/file_bug417760.png
Binary files differ
diff --git a/dom/html/test/file_bug649778.html b/dom/html/test/file_bug649778.html
new file mode 100644
index 000000000..48a9870e7
--- /dev/null
+++ b/dom/html/test/file_bug649778.html
@@ -0,0 +1,11 @@
+<html>
+<script>
+function test() {
+ document.open();
+ document.write('<html><body>WYCIWYG DOCUMENT</body></html>');
+ document.close();
+}
+</script>
+<body onload="setTimeout(test, 0);">
+</body>
+</html>
diff --git a/dom/html/test/file_bug649778.html^headers^ b/dom/html/test/file_bug649778.html^headers^
new file mode 100644
index 000000000..4030ea1d3
--- /dev/null
+++ b/dom/html/test/file_bug649778.html^headers^
@@ -0,0 +1 @@
+Cache-Control: no-store
diff --git a/dom/html/test/file_bug871161-1.html b/dom/html/test/file_bug871161-1.html
new file mode 100644
index 000000000..16015f0c4
--- /dev/null
+++ b/dom/html/test/file_bug871161-1.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=windows-1251>
+<title>Page with non-default charset</title>
+<script>
+function run() {
+ document.forms[0].submit();
+}
+</script>
+</head>
+<body onload="run();">
+<form method=post action="http://example.org/tests/dom/html/test/file_bug871161-2.html"></form>
+</body>
+</html>
+
diff --git a/dom/html/test/file_bug871161-2.html b/dom/html/test/file_bug871161-2.html
new file mode 100644
index 000000000..18cf825b2
--- /dev/null
+++ b/dom/html/test/file_bug871161-2.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Page without declared charset</title>
+<script>
+function done() {
+ window.opener.postMessage(document.characterSet, "*");
+}
+</script>
+</head>
+<body onload="done();">
+</body>
+</html>
+
diff --git a/dom/html/test/file_bug893537.html b/dom/html/test/file_bug893537.html
new file mode 100644
index 000000000..1dcb454ff
--- /dev/null
+++ b/dom/html/test/file_bug893537.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=893537
+-->
+<body>
+<iframe id="iframe" src="data:text/html;charset=US-ASCII,Goodbye World" srcdoc="Hello World"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_content_contextmenu.html b/dom/html/test/file_content_contextmenu.html
new file mode 100644
index 000000000..4d6874d2f
--- /dev/null
+++ b/dom/html/test/file_content_contextmenu.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title></title>
+ <style>
+ body {
+ margin: 0;
+ width: 100vw;
+ height: 100vh;
+ }
+ </style>
+</head>
+<body contextmenu="testmenu">
+ <menu type="context" id="testmenu">
+ <menuitem label="Test Context Menu Click" id="menuitem"></menuitem>
+ <hr>
+ </menu>
+</body>
+</html>
diff --git a/dom/html/test/file_cookiemanager.js b/dom/html/test/file_cookiemanager.js
new file mode 100644
index 000000000..98f356534
--- /dev/null
+++ b/dom/html/test/file_cookiemanager.js
@@ -0,0 +1,20 @@
+let { classes: Cc, interfaces: Ci } = Components;
+addMessageListener("getCookieFromManager", ({ host, path }) => {
+ let cm = Cc["@mozilla.org/cookiemanager;1"]
+ .getService(Ci.nsICookieManager);
+ let values = [];
+ path = path.substring(0, path.lastIndexOf("/") + 1);
+ let e = cm.enumerator;
+ while (e.hasMoreElements()) {
+ let cookie = e.getNext().QueryInterface(Ci.nsICookie);
+ if (!cookie) {
+ break;
+ }
+ if (host != cookie.host || path != cookie.path) {
+ continue;
+ }
+ values.push(cookie.name + "=" + cookie.value);
+ }
+
+ sendAsyncMessage("getCookieFromManager:return", { cookie: values.join("; ") });
+});
diff --git a/dom/html/test/file_formSubmission_img.jpg b/dom/html/test/file_formSubmission_img.jpg
new file mode 100644
index 000000000..dcd99b967
--- /dev/null
+++ b/dom/html/test/file_formSubmission_img.jpg
Binary files differ
diff --git a/dom/html/test/file_formSubmission_text.txt b/dom/html/test/file_formSubmission_text.txt
new file mode 100644
index 000000000..a496efee8
--- /dev/null
+++ b/dom/html/test/file_formSubmission_text.txt
@@ -0,0 +1 @@
+This is a text file
diff --git a/dom/html/test/file_fullscreen-api-keys.html b/dom/html/test/file_fullscreen-api-keys.html
new file mode 100644
index 000000000..33a68d03e
--- /dev/null
+++ b/dom/html/test/file_fullscreen-api-keys.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+</head>
+<body>
+<script>
+window.addEventListener("Test:DispatchKeyEvents", aEvent => {
+ var keyCode = KeyEvent["DOM_" + aEvent.detail.code];
+
+ document.body.focus();
+ var evt = document.createEvent("KeyboardEvent");
+ evt.initKeyEvent("keydown", true, true, window,
+ false, false, false, false,
+ keyCode, 0);
+ document.body.dispatchEvent(evt);
+
+ evt = document.createEvent("KeyboardEvent");
+ evt.initKeyEvent("keypress", true, true, window,
+ false, false, false, false,
+ keyCode, 0);
+ document.body.dispatchEvent(evt);
+
+ evt = document.createEvent("KeyboardEvent");
+ evt.initKeyEvent("keyup", true, true, window,
+ false, false, false, false,
+ keyCode, 0);
+ document.body.dispatchEvent(evt);
+});
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-api.html b/dom/html/test/file_fullscreen-api.html
new file mode 100644
index 000000000..89162058e
--- /dev/null
+++ b/dom/html/test/file_fullscreen-api.html
@@ -0,0 +1,317 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=545812
+
+Test DOM full-screen API.
+
+-->
+<head>
+ <title>Test for Bug 545812</title>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+ <style>
+ body {
+ background-color: black;
+ }
+ </style>
+</head>
+<body>
+<script type="application/javascript">
+
+/** Test for Bug 545812 **/
+
+function ok(condition, msg) {
+ opener.ok(condition, "[fullscreen] " + msg);
+}
+
+function is(a, b, msg) {
+ opener.is(a, b, "[fullscreen] " + msg);
+}
+
+/*
+<html>
+ <body onload='document.body.requestFullscreen();'>
+ <iframe id='inner-frame'></iframe>
+ </body>
+</html>
+*/
+var iframeContents = "data:text/html;charset=utf-8,<html><body onload%3D'parent.SimpleTest.waitForFocus(function(){document.body.requestFullscreen();});'><iframe id%3D'inner-frame'><%2Fiframe><%2Fbody><%2Fhtml>";
+
+var iframe = null;
+var outOfDocElement = null;
+var inDocElement = null;
+var container = null;
+var button = null;
+
+
+function sendMouseClick(element) {
+ synthesizeMouseAtCenter(element, {});
+}
+
+function fullScreenElement() {
+ return document.getElementById('full-screen-element');
+}
+
+function enter1(event) {
+ is(event.target, document, "Event target should be full-screen document #1");
+ ok(document.fullscreen, "Document should be in fullscreen");
+ is(document.fullscreenElement, fullScreenElement(),
+ "Full-screen element should be div element.");
+ ok(document.fullscreenElement.matches(":fullscreen"),
+ "FSE should match :fullscreen");
+ var fse = fullScreenElement();
+ addFullscreenChangeContinuation("exit", exit1);
+ fse.parentNode.removeChild(fse);
+ is(document.fullscreenElement, null,
+ "Full-screen element should be null after removing.");
+ document.body.appendChild(fse);
+ is(document.fullscreenElement, null,
+ "Full-screen element should still be null after re-adding former FSE.");
+}
+
+function exit1(event) {
+ is(event.target, document, "Event target should be full-screen document #2");
+ ok(!document.fullscreen, "Document should not be in fullscreen");
+ is(document.fullscreenElement, null, "Full-screen element should be null.");
+ iframe = document.createElement("iframe");
+ iframe.allowFullscreen = true;
+ addFullscreenChangeContinuation("enter", enter2);
+ document.body.appendChild(iframe);
+ iframe.src = iframeContents;
+}
+
+function enter2(event) {
+ is(event.target, document, "Event target should be full-screen document #3");
+ is(document.fullscreenElement, iframe,
+ "Full-screen element should be iframe element.");
+ is(iframe.contentDocument.fullscreenElement, iframe.contentDocument.body,
+ "Full-screen element in subframe should be body");
+
+ // The iframe's body is full-screen. Cancel full-screen in the subdocument to return
+ // the full-screen element to the previous full-screen element. This causes
+ // a fullscreenchange event.
+ addFullscreenChangeContinuation("exit", exit2);
+ document.exitFullscreen();
+}
+
+function exit2(event) {
+ is(document.fullscreenElement, null,
+ "Full-screen element should have rolled back.");
+ is(iframe.contentDocument.fullscreenElement, null,
+ "Full-screen element in subframe should be null");
+
+ addFullscreenChangeContinuation("enter", enter3);
+ fullScreenElement().requestFullscreen();
+}
+
+function enter3(event) {
+ is(event.target, document, "Event target should be full-screen document #3");
+ is(document.fullscreenElement, fullScreenElement(),
+ "Full-screen element should be div.");
+
+ // Transplant the FSE into subdoc. Should exit full-screen.
+ addFullscreenChangeContinuation("exit", exit3);
+ var _innerFrame = iframe.contentDocument.getElementById("inner-frame");
+ var fse = fullScreenElement();
+ _innerFrame.contentDocument.body.appendChild(fse);
+ is(document.fullscreenElement, null,
+ "Full-screen element transplanted, should be null.");
+ is(iframe.contentDocument.fullscreenElement, null,
+ "Full-screen element in outer frame should be null.");
+ is(_innerFrame.contentDocument.fullscreenElement, null,
+ "Full-screen element in inner frame should be null.");
+
+ document.body.appendChild(fse);
+}
+
+function exit3(event) {
+ is(event.target, document, "Event target should be full-screen document #4");
+ is(document.fullscreenElement, null, "Full-screen element should be null.");
+ document.body.removeChild(iframe);
+ iframe = null;
+
+ // Do a request out of document. It should be denied.
+ // Continue test in the following fullscreenerror handler.
+ outOfDocElement = document.createElement("div");
+ addFullscreenErrorContinuation(error1);
+ outOfDocElement.requestFullscreen();
+}
+
+function error1(event) {
+ ok(!document.fullscreenElement,
+ "Requests for full-screen from not-in-doc elements should fail.");
+ container = document.createElement("div");
+ inDocElement = document.createElement("div");
+ container.appendChild(inDocElement);
+ fullScreenElement().appendChild(container);
+
+ addFullscreenChangeContinuation("enter", enter4);
+ inDocElement.requestFullscreen();
+}
+
+function enter4(event) {
+ is(event.target, document, "Event target should be full-screen document #5");
+ is(document.fullscreenElement, inDocElement, "FSE should be inDocElement.");
+
+ // Remove full-screen ancestor element from document, verify it stops being reported as current FSE.
+ addFullscreenChangeContinuation("exit", exit_to_arg_test_1);
+ container.parentNode.removeChild(container);
+ is(document.fullscreenElement, null,
+ "Should not have a full-screen element again.");
+}
+
+function exit_to_arg_test_1(event) {
+ ok(!document.fullscreenElement,
+ "Should have left full-screen mode (third time).");
+ addFullscreenChangeContinuation("enter", enter_from_arg_test_1);
+ var threw = false;
+ try {
+ fullScreenElement().requestFullscreen(123);
+ } catch (e) {
+ threw = true;
+ // trigger normal fullscreen so that we continue
+ fullScreenElement().requestFullscreen();
+ }
+ ok(!threw, "requestFullscreen with bogus arg (123) shouldn't throw exception");
+}
+
+function enter_from_arg_test_1(event) {
+ ok(document.fullscreenElement,
+ "Should have entered full-screen after calling with bogus (ignored) argument (fourth time)");
+ addFullscreenChangeContinuation("exit", exit_to_arg_test_2);
+ document.exitFullscreen();
+}
+
+function exit_to_arg_test_2(event) {
+ ok(!document.fullscreenElement,
+ "Should have left full-screen mode (fourth time).");
+ addFullscreenChangeContinuation("enter", enter_from_arg_test_2);
+ var threw = false;
+ try {
+ fullScreenElement().requestFullscreen({ vrDisplay: null });
+ } catch (e) {
+ threw = true;
+ // trigger normal fullscreen so that we continue
+ fullScreenElement().requestFullscreen();
+ }
+ ok(!threw, "requestFullscreen with { vrDisplay: null } shouldn't throw exception");
+}
+
+function enter_from_arg_test_2(event) {
+ ok(document.fullscreenElement,
+ "Should have entered full-screen after calling with vrDisplay null argument (fifth time)");
+ addFullscreenChangeContinuation("exit", exit4);
+ document.exitFullscreen();
+}
+
+function exit4(event) {
+ ok(!document.fullscreenElement,
+ "Should be back in non-full-screen mode (fifth time)");
+ SpecialPowers.pushPrefEnv({"set":[["full-screen-api.allow-trusted-requests-only", true]]}, function() {
+ addFullscreenErrorContinuation(error2);
+ fullScreenElement().requestFullscreen();
+ });
+}
+
+function error2(event) {
+ ok(!document.fullscreenElement,
+ "Should still be in normal mode, because calling context isn't trusted.");
+ button = document.createElement("button");
+ button.onclick = function(){fullScreenElement().requestFullscreen();}
+ fullScreenElement().appendChild(button);
+ addFullscreenChangeContinuation("enter", enter5);
+ sendMouseClick(button);
+}
+
+function enter5(event) {
+ ok(document.fullscreenElement, "Moved to full-screen after mouse click");
+ addFullscreenChangeContinuation("exit", exit5);
+ document.exitFullscreen();
+}
+
+function exit5(event) {
+ ok(!document.fullscreenElement,
+ "Should have left full-screen mode (last time).");
+ SpecialPowers.pushPrefEnv({
+ "set":[["full-screen-api.allow-trusted-requests-only", false],
+ ["full-screen-api.enabled", false]]}, function() {
+ is(document.fullscreenEnabled, false, "document.fullscreenEnabled should be false if full-screen-api.enabled is false");
+ addFullscreenErrorContinuation(error3);
+ fullScreenElement().requestFullscreen();
+ });
+}
+
+function error3(event) {
+ ok(!document.fullscreenElement,
+ "Should still be in normal mode, because pref is not enabled.");
+
+ SpecialPowers.pushPrefEnv({"set":[["full-screen-api.enabled", true]]}, function() {
+ is(document.fullscreenEnabled, true, "document.fullscreenEnabled should be true if full-screen-api.enabled is true");
+ opener.nextTest();
+ });
+}
+
+function begin() {
+ testNamespaces(() => {
+ addFullscreenChangeContinuation("enter", enter1);
+ fullScreenElement().requestFullscreen();
+ });
+}
+
+function testNamespaces(followupTestFn) {
+ let tests = [
+ {allowed: false, name: "element", ns: "http://www.w3.org/XML/1998/namespace"},
+ {allowed: false, name: "element", ns: "http://www.w3.org/1999/xlink"},
+ {allowed: false, name: "element", ns: "http://www.w3.org/2000/svg"},
+ {allowed: false, name: "element", ns: "http://www.w3.org/1998/Math/MathML"},
+ {allowed: false, name: "mathml", ns: "unknown"},
+ {allowed: false, name: "svg", ns: "unknown"},
+ {allowed: true, name: "element", ns: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"},
+ {allowed: true, name: "element", ns: "http://www.w3.org/1999/xhtml"},
+ {allowed: true, name: "svg", ns: "http://www.w3.org/1999/xhtml"},
+ {allowed: true, name: "math", ns: "http://www.w3.org/1999/xhtml"},
+ {allowed: true, name: "svg", ns: "http://www.w3.org/2000/svg"},
+ {allowed: true, name: "math", ns: "http://www.w3.org/1998/Math/MathML"},
+ {allowed: true, name: "element"},
+ ];
+
+ function runNextNamespaceTest() {
+ let test = tests.shift();
+ if (!test) {
+ followupTestFn();
+ return;
+ }
+
+ let elem = test.ns ? document.createElementNS(test.ns, test.name) :
+ document.createElement(test.name);
+ document.body.appendChild(elem);
+
+ if (test.allowed) {
+ addFullscreenChangeContinuation("enter", () => {
+ ok(document.fullscreen, "Document should be in fullscreen");
+ is(document.fullscreenElement, elem,
+ `Element named '${test.name}' in this namespace should be allowed: ${test.ns}`);
+ addFullscreenChangeContinuation("exit", runNextNamespaceTest);
+ document.body.removeChild(elem);
+ });
+ } else {
+ addFullscreenErrorContinuation(() => {
+ ok(!document.fullscreenElement,
+ `Element named '${test.name}' in this namespace should not be allowed: ${test.ns}`);
+ document.body.removeChild(elem);
+ runNextNamespaceTest();
+ });
+ }
+
+ elem.requestFullscreen();
+ }
+
+ runNextNamespaceTest();
+}
+</script>
+</pre>
+<div id="full-screen-element"></div>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-backdrop.html b/dom/html/test/file_fullscreen-backdrop.html
new file mode 100644
index 000000000..d3d4cc446
--- /dev/null
+++ b/dom/html/test/file_fullscreen-backdrop.html
@@ -0,0 +1,107 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Test for Bug 1064843</title>
+ <style id="style"></style>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="text/javascript" src="file_fullscreen-utils.js"></script>
+ <style>
+ html {
+ overflow: hidden;
+ }
+ #placeholder {
+ height: 1000vh;
+ }
+ </style>
+</head>
+<body>
+<div id="fullscreen"></div>
+<div id="placeholder"></div>
+<script>
+
+const gStyle = document.getElementById("style");
+const gFullscreen = document.getElementById("fullscreen");
+
+function is(a, b, msg) {
+ opener.is(a, b, "[backdrop] " + msg);
+}
+
+function isnot(a, b, msg) {
+ opener.isnot(a, b, "[backdrop] " + msg);
+}
+
+function ok(cond, msg) {
+ opener.ok(cond, "[backdrop] " + msg);
+}
+
+function info(msg) {
+ opener.info("[backdrop] " + msg);
+}
+
+function synthesizeMouseAtWindowCenter() {
+ synthesizeMouseAtPoint(innerWidth / 2, innerHeight / 2, {});
+}
+
+const gFullscreenElementBackground = getComputedStyle(gFullscreen).background;
+
+function begin() {
+ info("The default background of window should be white");
+ assertWindowPureColor(window, "white");
+ addFullscreenChangeContinuation("enter", enterFullscreen);
+ gFullscreen.requestFullscreen();
+}
+
+function setBackdropStyle(style) {
+ gStyle.textContent = `#fullscreen::backdrop { ${style} }`;
+}
+
+function enterFullscreen() {
+ is(getComputedStyle(gFullscreen).background, gFullscreenElementBackground,
+ "Computed background of #fullscreen shouldn't be changed");
+
+ info("The default background of backdrop for fullscreen is black");
+ assertWindowPureColor(window, "black");
+
+ setBackdropStyle("background: green");
+ info("The background color of backdrop should be changed to green");
+ assertWindowPureColor(window, "green");
+
+ gFullscreen.style.background = "blue";
+ info("The blue fullscreen element should cover the backdrop");
+ assertWindowPureColor(window, "blue");
+
+ gFullscreen.style.background = "";
+ setBackdropStyle("display: none");
+ info("The white body should be shown when the backdrop is hidden");
+ assertWindowPureColor(window, "white");
+
+ setBackdropStyle("");
+ info("Content should return to black because we restore the backdrop");
+ assertWindowPureColor(window, "black");
+
+ gFullscreen.style.display = "none";
+ info("The backdrop should disappear with the fullscreen element");
+ assertWindowPureColor(window, "white");
+
+ gFullscreen.style.display = "";
+ setBackdropStyle("position: absolute");
+ info("Changing position shouldn't immediately affect the view");
+ assertWindowPureColor(window, "black");
+
+ window.scroll(0, screen.height);
+ info("Scrolled up the absolutely-positioned element");
+ assertWindowPureColor(window, "white");
+
+ addFullscreenChangeContinuation("exit", exitFullscreen);
+ document.exitFullscreen();
+}
+
+function exitFullscreen() {
+ opener.nextTest();
+}
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-denied-inner.html b/dom/html/test/file_fullscreen-denied-inner.html
new file mode 100644
index 000000000..6b5916b2e
--- /dev/null
+++ b/dom/html/test/file_fullscreen-denied-inner.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+</head>
+<body onload="doRequestFullscreen()">
+<script>
+function doRequestFullscreen() {
+ function handler(evt) {
+ document.removeEventListener("fullscreenchange", handler);
+ document.removeEventListener("fullscreenerror", handler);
+ parent.is(evt.type, "fullscreenerror", "Request from " +
+ `document inside ${parent.testTargetName} should be denied`);
+ parent.continueTest();
+ }
+ parent.ok(!document.fullscreenEnabled, "Fullscreen " +
+ `should not be enabled in ${parent.testTargetName}`);
+ document.addEventListener("fullscreenchange", handler);
+ document.addEventListener("fullscreenerror", handler);
+ document.documentElement.requestFullscreen();
+}
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-denied.html b/dom/html/test/file_fullscreen-denied.html
new file mode 100644
index 000000000..322723083
--- /dev/null
+++ b/dom/html/test/file_fullscreen-denied.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=545812
+
+Test DOM fullscreen API.
+
+-->
+<head>
+ <title>Test for Bug 545812</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+ <style>
+ body {
+ background-color: black;
+ }
+ </style>
+</head>
+<body>
+
+<script type="application/javascript">
+
+/** Test for Bug 545812 **/
+
+function ok(condition, msg) {
+ opener.ok(condition, "[denied] " + msg);
+}
+
+function is(a, b, msg) {
+ opener.is(a, b, "[denied] " + msg);
+}
+
+const INNER_FILE = "file_fullscreen-denied-inner.html";
+function setupForInnerTest(targetName, callback) {
+ window.testTargetName = targetName;
+ window.continueTest = () => {
+ delete window.testTargetName;
+ delete window.continueTest;
+ callback();
+ };
+}
+
+function begin() {
+ document.addEventListener("fullscreenchange", () => {
+ ok(false, "Should never receive " +
+ "a fullscreenchange event in the main window.");
+ });
+ SimpleTest.executeSoon(testIFrameWithoutAllowFullscreen);
+}
+
+function testIFrameWithoutAllowFullscreen() {
+ // Create an iframe without an allowfullscreen attribute, whose
+ // contents request fullscreen. The request should be denied, and
+ // we should not receive a fullscreenchange event in this document.
+ var iframe = document.createElement("iframe");
+ iframe.src = INNER_FILE;
+ setupForInnerTest("an iframe without allowfullscreen", () => {
+ document.body.removeChild(iframe);
+ SimpleTest.executeSoon(testFrameElement);
+ });
+ document.body.appendChild(iframe);
+}
+
+function testFrameElement() {
+ var frameset = document.createElement("frameset");
+ var frame = document.createElement("frame");
+ frame.src = INNER_FILE;
+ frameset.appendChild(frame);
+ setupForInnerTest("a frame element", () => {
+ document.documentElement.removeChild(frameset);
+ SimpleTest.executeSoon(testObjectElement);
+ });
+ document.documentElement.appendChild(frameset);
+}
+
+function testObjectElement() {
+ var objectElem = document.createElement("object");
+ objectElem.data = INNER_FILE;
+ setupForInnerTest("an object element", () => {
+ document.body.removeChild(objectElem);
+ // In the following tests we want to test trust context requirement
+ // of fullscreen request, so temporary re-enable this pref.
+ SpecialPowers.pushPrefEnv({
+ "set":[["full-screen-api.allow-trusted-requests-only", true]]
+ }, testNonTrustContext);
+ });
+ document.body.appendChild(objectElem);
+}
+
+function testNonTrustContext() {
+ addFullscreenErrorContinuation(() => {
+ ok(!document.fullscreenElement,
+ "Should not grant request in non-trust context.");
+ SimpleTest.executeSoon(testLongRunningEventHandler);
+ });
+ document.documentElement.requestFullscreen();
+}
+
+function testLongRunningEventHandler() {
+ function longRunningHandler() {
+ window.removeEventListener("keypress", longRunningHandler);
+ // Busy loop until 2s has passed. We should then be past the one
+ // second threshold, and so our request for fullscreen should be
+ // rejected.
+ var end = (new Date()).getTime() + 2000;
+ while ((new Date()).getTime() < end) {
+ ; // Wait...
+ }
+ document.documentElement.requestFullscreen();
+ }
+ addFullscreenErrorContinuation(() => {
+ ok(!document.fullscreenElement,
+ "Should not grant request in long-running event handler.");
+ // Restore the pref environment we changed before
+ // entering testNonTrustContext.
+ SpecialPowers.popPrefEnv(finish);
+ });
+ window.addEventListener("keypress", longRunningHandler);
+ synthesizeKey("VK_A", {});
+}
+
+function finish() {
+ opener.nextTest();
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-esc-exit-inner.html b/dom/html/test/file_fullscreen-esc-exit-inner.html
new file mode 100644
index 000000000..08744d644
--- /dev/null
+++ b/dom/html/test/file_fullscreen-esc-exit-inner.html
@@ -0,0 +1,58 @@
+ <!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=700764
+
+Verify that an ESC key press in a subdoc of a full-screen doc causes us to
+exit DOM full-screen mode.
+
+-->
+<head>
+ <title>Test for Bug 700764</title>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <style>
+ body:not(:fullscreen) {
+ background-color: blue;
+ }
+ </style>
+</head>
+<body>
+
+<script type="application/javascript">
+
+/** Test for Bug 700764 **/
+
+function ok(condition, msg) {
+ parent.ok(condition, msg);
+}
+
+function is(a, b, msg) {
+ parent.is(a, b, msg);
+}
+
+var escKeyReceived = false;
+var escKeySent = false;
+
+function keyHandler(event) {
+ if (escKeyReceived == SpecialPowers.Ci.nsIDOMKeyEvent.DOM_VK_ESC) {
+ escKeyReceived = true;
+ }
+}
+
+window.addEventListener("keydown", keyHandler, true);
+window.addEventListener("keyup", keyHandler, true);
+window.addEventListener("keypress", keyHandler, true);
+
+function startTest() {
+ ok(!document.fullscreenElement, "Subdoc should not be in full-screen mode");
+ ok(parent.document.fullscreenElement, "Parent should be in full-screen mode");
+ escKeySent = true;
+ window.focus();
+ synthesizeKey("VK_ESCAPE", {});
+}
+
+</script>
+</pre>
+<p>Inner frame</p>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-esc-exit.html b/dom/html/test/file_fullscreen-esc-exit.html
new file mode 100644
index 000000000..beb52f926
--- /dev/null
+++ b/dom/html/test/file_fullscreen-esc-exit.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=700764
+
+Verify that an ESC key press in a subdoc of a full-screen doc causes us to
+exit DOM full-screen mode.
+
+-->
+<head>
+ <title>Test for Bug 700764</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+ <style>
+ body:fullscreen, div:fullscreen {
+ background-color: red;
+ }
+ </style>
+</head>
+<body>
+
+<script type="application/javascript">
+
+function ok(condition, msg) {
+ opener.ok(condition, "[esc-exit] " + msg);
+}
+
+function is(a, b, msg) {
+ opener.is(a, b, "[esc-exit] " + msg);
+}
+
+function finish() {
+ opener.nextTest();
+}
+
+function fullscreenchange1(event) {
+ is(document.fullscreenElement, document.body, "FSE should be doc");
+ addFullscreenChangeContinuation("exit", fullscreenchange2);
+ ok(!document.getElementById("subdoc").contentWindow.escKeySent, "Should not yet have sent ESC key press.");
+ document.getElementById("subdoc").contentWindow.startTest();
+}
+
+function fullscreenchange2(event) {
+ ok(document.getElementById("subdoc").contentWindow.escKeySent, "Should have sent ESC key press.");
+ ok(!document.getElementById("subdoc").contentWindow.escKeyReceived, "ESC key press to exit should not be delivered.");
+ ok(!document.fullscreenElement, "Should have left full-screen mode on ESC key press");
+ finish();
+}
+
+function begin() {
+ addFullscreenChangeContinuation("enter", fullscreenchange1);
+ document.body.requestFullscreen();
+}
+
+</script>
+
+<!-- This subframe conducts the test. -->
+<iframe id="subdoc" src="file_fullscreen-esc-exit-inner.html"></iframe>
+
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-hidden.html b/dom/html/test/file_fullscreen-hidden.html
new file mode 100644
index 000000000..b458a1714
--- /dev/null
+++ b/dom/html/test/file_fullscreen-hidden.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=697636
+-->
+<head>
+ <title>Test for Bug 697636</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<iframe id="f" src="data:text/html,<body text=green>1" allowfullscreen></iframe>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=697636">Mozilla Bug 697636</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 697636 **/
+
+var frameWin;
+var e1;
+
+function begin()
+{
+ frameWin = document.getElementById("f").contentWindow;
+ e1 = frameWin.document.documentElement;
+ frameWin.location = "data:text/html,<body text=blue onload='parent.b2()'>2";
+}
+
+function b2()
+{
+ try {
+ e1.requestFullscreen();
+ } catch(e) {
+ opener.ok(false, "[hidden] Should not enter full-screen");
+ }
+ setTimeout(done, 0);
+}
+
+function done() {
+ opener.ok(!document.fullscreenElement, "[hidden] Should not have entered full-screen mode in hidden document.");
+ opener.ok(!e1.ownerDocument.fullscreenElement, "[hidden] Requesting owner should not have entered full-screen mode.");
+ opener.nextTest();
+}
+
+</script>
+</pre>
+</body>
+
+</html>
diff --git a/dom/html/test/file_fullscreen-lenient-setters.html b/dom/html/test/file_fullscreen-lenient-setters.html
new file mode 100644
index 000000000..e8df91502
--- /dev/null
+++ b/dom/html/test/file_fullscreen-lenient-setters.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <title>Test for Bug 1268798</title>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<script>
+"use strict";
+
+function ok(condition, msg) {
+ opener.ok(condition, "[lenient-setters] " + msg);
+}
+
+function is(a, b, msg) {
+ opener.is(a, b, "[lenient-setters] " + msg);
+}
+
+function info(msg) {
+ opener.info("[lenient-setters] " + msg);
+}
+
+let unattachedDiv = document.createElement("div");
+
+function begin() {
+ var originalValue = document.fullscreen;
+ try {
+ document.fullscreen = !document.fullscreen;
+ is(document.fullscreen, originalValue,
+ "fullscreen should not be changed");
+ } catch (e) {
+ ok(false, "Setting fullscreen should not throw");
+ }
+
+ var originalElem = document.fullscreenElement;
+ try {
+ document.fullscreenElement = unattachedDiv;
+ document.fullscreenElement = [];
+ is(document.fullscreenElement, originalElem,
+ "fullscreenElement should not be changed");
+ } catch (e) {
+ ok(false, "Setting fullscreenElement should not throw");
+ }
+
+ var originalEnabled = document.fullscreenEnabled;
+ try {
+ document.fullscreenEnabled = !originalEnabled;
+ is(document.fullscreenEnabled, originalEnabled,
+ "fullscreenEnabled should not be changed");
+ } catch (e) {
+ ok(false, "Setting fullscreenEnabled should not throw");
+ }
+
+ opener.nextTest();
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-multiple-inner.html b/dom/html/test/file_fullscreen-multiple-inner.html
new file mode 100644
index 000000000..8390cffec
--- /dev/null
+++ b/dom/html/test/file_fullscreen-multiple-inner.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 724554</title>
+ <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+</head>
+<body>
+
+<script type="application/javascript">
+
+
+/** Test for Bug 545812 **/
+function begin(id) {
+ addFullscreenErrorContinuation(function() {
+ opener.ok(false, "Fullscreen denied " + id);
+ });
+ addFullscreenChangeContinuation("enter",
+ function() {
+ opener.enteredFullscreen(id);
+ });
+ document.body.requestFullscreen();
+}
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-multiple.html b/dom/html/test/file_fullscreen-multiple.html
new file mode 100644
index 000000000..1a457b361
--- /dev/null
+++ b/dom/html/test/file_fullscreen-multiple.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=724554
+
+Test that multiple windows can be fullscreen at the same time.
+
+Open one window, focus it and enter fullscreen, then open another, focus
+it and enter fullscreen, and check that both are still fullscreen.
+
+-->
+<head>
+ <title>Test for Bug 724554</title>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+</head>
+<body>
+
+<script type="application/javascript">
+
+/** Test for Bug 545812 **/
+
+function ok(condition, msg) {
+ opener.ok(condition, "[multiple] " + msg);
+}
+
+function is(a, b, msg) {
+ opener.is(a, b, "[multiple] " + msg);
+}
+
+var window1, window2;
+
+function openWindow(id) {
+ var w = window.open("file_fullscreen-multiple-inner.html", "", "width=500,height=500");
+ w.addEventListener("load", function onload() {
+ w.focus();
+ SimpleTest.waitForFocus(function(){w.begin(id)}, w);
+ });
+ return w;
+}
+
+function begin() {
+ window1 = openWindow("one");
+}
+
+function enteredFullscreen(id) {
+ if (id == "one") {
+ window2 = openWindow("two");
+ } else if (id == "two") {
+ ok(window1.document.fullscreenElement &&
+ window2.document.fullscreenElement,
+ "Both windows should be fullscreen concurrently");
+ window1.close();
+ window2.close();
+ opener.nextTest();
+ }
+}
+
+</script>
+</pre>
+<div id="full-screen-element"></div>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-navigation.html b/dom/html/test/file_fullscreen-navigation.html
new file mode 100644
index 000000000..00a4ed4e1
--- /dev/null
+++ b/dom/html/test/file_fullscreen-navigation.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=685402
+-->
+<head>
+ <title>Test for Bug 685402</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body style="background-color: gray;">
+
+<iframe id="f" src="data:text/html,<body text=green>1" allowfullscreen></iframe>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685402">Mozilla Bug 685402</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 685402 **/
+
+var frameWin;
+var e1;
+var prevEnabled;
+var prevTrusted;
+
+function begin()
+{
+ frameWin = document.getElementById("f").contentWindow;
+ e1 = frameWin.document.body;
+ document.addEventListener("fullscreenchange", function onfullscreen() {
+ document.removeEventListener("fullscreenchange", onfullscreen, false);
+ opener.ok(document.fullscreenElement, "[navigation] Request should be granted");
+ frameWin.location = "data:text/html,<body text=blue onload='parent.b2()'>2";
+ }, false);
+
+ e1.requestFullscreen();
+}
+
+function b2()
+{
+ opener.ok(!document.fullscreenElement, "[navigation] Should have left full-screen due to navigation.");
+ opener.nextTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-nested.html b/dom/html/test/file_fullscreen-nested.html
new file mode 100644
index 000000000..60989cd1c
--- /dev/null
+++ b/dom/html/test/file_fullscreen-nested.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 1187801</title>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+</head>
+<body>
+<iframe src="about:blank" allowfullscreen></iframe>
+<script type="text/javascript">
+
+/** Test for Bug 1187801 **/
+
+function info(msg) {
+ opener.info("[nested] " + msg);
+}
+
+function ok(condition, msg) {
+ opener.ok(condition, "[nested] " + msg);
+}
+
+function is(a, b, msg) {
+ opener.is(a, b, "[nested] " + msg);
+}
+
+var gInnerDoc;
+var gTestSteps;
+var gTestIndex = 0;
+
+function begin() {
+ var root = document.documentElement;
+ var iframe = document.querySelector("iframe");
+ var innerDoc = gInnerDoc = iframe.contentDocument;
+ var innerRoot = innerDoc.documentElement;
+
+ // The format of each test step is:
+ // [[action, target], [fsOuter, fsInner]] where:
+ // * "action" is either "enter" or "exit", means whether we want to
+ // enter or exit fullscreen in this step.
+ // * "target" is where we apply this action. For "enter" action, it
+ // is the element we want to call requestFullscreen() on, and for
+ // "exit", it is the document we want to call exitFullscreen() on.
+ // * "fsOuter" and "fsInner" are the expected fullscreen elements of
+ // the outer and inner document respectively after executing the
+ // action in this step.
+ gTestSteps = [
+ // innerRoot
+ [["enter", innerRoot], [iframe, innerRoot]],
+ [[ "exit", innerDoc], [ null, null]],
+ [["enter", innerRoot], [iframe, innerRoot]],
+ [[ "exit", document], [ null, null]],
+ // root, innerRoot
+ [["enter", root], [ root, null]],
+ [["enter", innerRoot], [iframe, innerRoot]],
+ [[ "exit", innerDoc], [ root, null]],
+ [[ "exit", document], [ null, null]],
+ [["enter", root], [ root, null]],
+ [["enter", innerRoot], [iframe, innerRoot]],
+ [[ "exit", document], [ root, null]],
+ [[ "exit", document], [ null, null]],
+ // iframe, innerRoot
+ [["enter", iframe], [iframe, null]],
+ [["enter", innerRoot], [iframe, innerRoot]],
+ [[ "exit", innerDoc], [iframe, null]],
+ [[ "exit", document], [ null, null]],
+ [["enter", iframe], [iframe, null]],
+ [["enter", innerRoot], [iframe, innerRoot]],
+ [[ "exit", document], [ null, null]],
+ // root, iframe, innerRoot
+ [["enter", root], [ root, null]],
+ [["enter", iframe], [iframe, null]],
+ [["enter", innerRoot], [iframe, innerRoot]],
+ [[ "exit", innerDoc], [iframe, null]],
+ [[ "exit", document], [ root, null]],
+ [[ "exit", document], [ null, null]],
+ [["enter", root], [ root, null]],
+ [["enter", iframe], [iframe, null]],
+ [["enter", innerRoot], [iframe, innerRoot]],
+ [[ "exit", document], [ root, null]],
+ [[ "exit", document], [ null, null]],
+ ];
+
+ nextStep();
+}
+
+function nextStep() {
+ if (gTestIndex == gTestSteps.length) {
+ opener.nextTest();
+ return;
+ }
+
+ var index = gTestIndex;
+ var [[action, target], [fsOuter, fsInner]] = gTestSteps[gTestIndex++];
+
+ function checkAndNext() {
+ is(document.fullscreenElement, fsOuter,
+ `Fullscreen element of outer doc should match after step ${index}`);
+ is(gInnerDoc.fullscreenElement, fsInner,
+ `Fullscreen element of inner doc should match after step ${index}`);
+ nextStep();
+ }
+
+ info(`Executing step ${index}: ${action} on ${target}...`);
+ if (action == "enter") {
+ // For "enter" action, the target is the element
+ var doc = target.ownerDocument;
+ addFullscreenChangeContinuation("enter", checkAndNext, doc);
+ target.requestFullscreen();
+ } else if (action == "exit") {
+ // For "exit" action, the target is the document
+ addFullscreenChangeContinuation("exit", checkAndNext, target);
+ target.exitFullscreen();
+ } else {
+ ok(false, `Unknown action ${action}`);
+ }
+}
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-plugins.html b/dom/html/test/file_fullscreen-plugins.html
new file mode 100644
index 000000000..f28fbede9
--- /dev/null
+++ b/dom/html/test/file_fullscreen-plugins.html
@@ -0,0 +1,160 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=545812
+
+Test plugins with DOM full-screen API:
+* Presence of plugins has no effect on request for full-screen on MacOS.
+* Request for full-screen is denied when windowed plugin in current doc is present.
+* Request for full-screen is denied when windowed plugin in subdocument is present.
+* Request for full-screen is not denied when the only plugin present is windowless.
+* Adding an existing (out-of-doc) windowed plugin to a full-screen document causes document to exit full-screen.
+* Create windowed plugin and adding it to full-screen document caused exit from full-screen.
+
+-->
+<head>
+ <title>Test for Bug 545812</title>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="plugin-utils.js"></script>
+ <script type="application/javascript">
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ </script>
+ <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+ <style>
+ body:fullscreen, div:fullscreen {
+ background-color: red;
+ }
+ </style>
+</head>
+<body>
+
+
+<!-- Windowed plugin, focusing should revoke full-screen. -->
+<embed id="windowed-plugin" type="application/x-test" style="width:200px;height:100px;" wmode="window"></embed>
+
+<!-- Windowless plugin, focusing should not revoke full-screen. -->
+<embed id="windowless-plugin" type="application/x-test" style="width:200px;height:100px;"></embed>
+
+
+<!-- iframe contents:
+
+<html><body><embed id='windowed-plugin' type='application/x-test' style='width:200px;height:100px;' wmode='window'></embed></body></html>
+
+-->
+
+<iframe id="subdoc-plugin" src="data:text/html;charset=utf-8,<html><body><embed id%3D'windowed-plugin' type%3D'application%2Fx-test' style%3D'width%3A200px%3Bheight%3A100px%3B' wmode%3D'window'><%2Fembed><%2Fbody><%2Fhtml>%0D%0A"></iframe>
+
+<script type="application/javascript">
+
+/** Test for Bug 545812 **/
+
+function ok(condition, msg) {
+ opener.ok(condition, "[plugins] " + msg);
+}
+
+function is(a, b, msg) {
+ opener.is(a, b, "[plugins] " + msg);
+}
+
+function e(id) {
+ return document.getElementById(id);
+}
+
+function removeElement(e) {
+ e.parentNode.removeChild(e);
+}
+
+const isMacOs = navigator.appVersion.indexOf("Macintosh") != -1;
+
+var windowedPlugin = null;
+
+function begin() {
+ // Delay test startup long enough for the windowed plugin in the subframe to
+ // start up and create its window.
+ opener.SimpleTest.executeSoon(function() {
+ opener.SimpleTest.executeSoon(function() {
+ startTest();
+ })
+ });
+}
+
+function startTest() {
+ ok(!document.fullscreenElement, "Should not be in full-screen mode initially");
+ document.body.requestFullscreen();
+
+ // Focus the windowed plugin. On MacOS we should still enter full-screen mode,
+ // on windows the pending request for full-screen should be denied.
+ e("windowed-plugin").focus();
+
+ if (isMacOs) {
+ // Running on MacOS, all plugins are effectively windowless, request for full-screen should be granted.
+ // Continue test in the (mac-specific) "fullscreenchange" handler.
+ addFullscreenChangeContinuation("enter", macFullScreenChange1);
+ } else {
+ // Non-MacOS, request should be denied, carry on the test after receiving error event.
+ addFullscreenErrorContinuation(nonMacTest);
+ }
+}
+
+function nonMacTest() {
+ ok(!document.fullscreenElement, "Request for full-screen with focused windowed plugin should be denied.");
+
+ // Focus a regular html element, and re-request full-screen, request should be granted.
+ e("windowless-plugin").focus();
+ addFullscreenChangeContinuation("enter", nonMacTest2);
+ document.body.requestFullscreen();
+}
+
+function nonMacTest2() {
+ ok(document.fullscreenElement, "Request for full-screen with non-plugin focused should be granted.");
+ // Focus a windowed plugin, full-screen should be revoked.
+ addFullscreenChangeContinuation("exit", nonMacTest3);
+ e("windowed-plugin").focus();
+}
+
+function nonMacTest3() {
+ ok(!document.fullscreenElement, "Full-screen should have been revoked when windowed-plugin was focused.");
+ // Remove windowed plugins before closing the window
+ // to work around bug 1237853.
+ removeElement(e("windowed-plugin"));
+ removeElement(e("subdoc-plugin").contentDocument.getElementById("windowed-plugin"));
+ opener.nextTest();
+}
+
+var fullScreenChangeCount = 0;
+
+function createWindowedPlugin() {
+ var p = document.createElement("embed");
+ p.setAttribute("type", "application/x-test");
+ p.setAttribute("wmode", "window");
+ return p;
+}
+
+function macFullScreenChange1(event) {
+ ok(document.fullscreenElement, "Requests for full-screen with focused windowed plugins should be granted on MacOS");
+
+ // Create a new windowed plugin, and add that to the document. Should *not* exit full-screen mode on MacOS.
+ windowedPlugin = createWindowedPlugin();
+ document.body.appendChild(windowedPlugin);
+
+ // Focus windowed plugin. Should not exit full-screen mode on MacOS.
+ windowedPlugin.focus();
+
+ setTimeout(
+ function() {
+ ok(document.fullscreenElement, "Adding & focusing a windowed plugin to document should not cause full-screen to exit on MacOS.");
+ addFullscreenChangeContinuation("exit", macFullScreenChange2);
+ document.exitFullscreen();
+ }, 0);
+}
+
+function macFullScreenChange2(event) {
+ ok(!document.fullscreenElement, "Should have left full-screen mode after calling document.exitFullscreen().");
+ opener.nextTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-prefixed.html b/dom/html/test/file_fullscreen-prefixed.html
new file mode 100644
index 000000000..5f3d60196
--- /dev/null
+++ b/dom/html/test/file_fullscreen-prefixed.html
@@ -0,0 +1,153 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <title>Test for Bug 743198</title>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+ <div id="fullscreen"></div>
+<script>
+
+function ok(condition, msg) {
+ opener.ok(condition, "[prefixed] " + msg);
+}
+
+function is(a, b, msg) {
+ opener.is(a, b, "[prefixed] " + msg);
+}
+
+function info(msg) {
+ opener.info("[prefixed] " + msg);
+}
+
+SimpleTest.requestFlakyTimeout(
+ "need to wait for a while to confirm no unexpected event is dispatched");
+
+let div = document.getElementById("fullscreen");
+let unattachedDiv = document.createElement('div');
+
+const NO_EVENT_HANDLER = 0;
+const PREFIXED_EVENT_ONLY = 1;
+const PREFIXED_AND_UNPREFIXED_EVENT = 2;
+
+class TestCase {
+ constructor(num, handlersOnWindow, handlersOnDocument) {
+ this.number = num;
+ this.handlersType = new Map([[window, handlersOnWindow],
+ [document, handlersOnDocument]]);
+ }
+
+ static checkState(inFullscreen, msg) {
+ var emptyOrNot = inFullscreen ? "" : "not ";
+ info(`Check fullscreen state ${msg}`);
+ is(document.mozFullScreen, inFullscreen,
+ `Should ${emptyOrNot}be in fullscreen`);
+ is(document.fullscreenElement, inFullscreen ? div : null,
+ `Fullscreen element should be ${inFullscreen ? "div" : "null"}`);
+ is(document.mozFullScreenElement, document.fullscreenElement,
+ "document.mozFullScreenElement should be identical to fullscreenElement");
+ is(div.matches(":fullscreen"), inFullscreen,
+ `Fullscreen element should ${emptyOrNot}match :fullscreen pseudo class`);
+ is(div.matches(":-moz-full-screen"), inFullscreen,
+ `Fullscreen element should ${emptyOrNot}match :-moz-full-screen pseudo class`);
+ }
+
+ changeListeners(action, eventType, handler) {
+ let method = `${action}EventListener`;
+ for (let [target, type] of this.handlersType.entries()) {
+ if (type == PREFIXED_EVENT_ONLY) {
+ target[method](`moz${eventType}`, handler);
+ } else if (type == PREFIXED_AND_UNPREFIXED_EVENT) {
+ target[method](eventType, handler);
+ target[method](`moz${eventType}`, handler);
+ } else if (type != NO_EVENT_HANDLER) {
+ ok(false, `Unknown handlers type ${type}`);
+ }
+ }
+ }
+
+ doTest(actionCallback, eventType, inFullscreen, msg) {
+ return new Promise(resolve => {
+ let timeout = 0;
+ let expectEvent = new Map();
+ for (let [target, type] of this.handlersType) {
+ expectEvent.set(target, this.handlersType != NO_EVENT_HANDLER);
+ }
+ let handleEvent = evt => {
+ let target = evt.currentTarget;
+ let type = this.handlersType.get(target);
+ if (type == PREFIXED_EVENT_ONLY) {
+ is(evt.type, `moz${eventType}`,
+ `Should get prefixed event on ${target}`);
+ } else if (type == PREFIXED_AND_UNPREFIXED_EVENT) {
+ is(evt.type, eventType,
+ `Should only get unprefixed event on ${target}`);
+ } else {
+ ok(false, `No event should be triggered on ${target}`);
+ }
+ // Ensure we receive each event exactly once.
+ if (expectEvent.get(target)) {
+ expectEvent.set(target, false);
+ } else {
+ ok(false, `Got an unexpected ${evt.type} event on ${target}`);
+ }
+ if (!timeout) {
+ timeout = setTimeout(() => {
+ this.changeListeners("remove", eventType, handleEvent);
+ TestCase.checkState(inFullscreen,
+ `${msg} in test case ${this.number}`);
+ resolve();
+ });
+ }
+ };
+ this.changeListeners("add", eventType, handleEvent);
+ actionCallback();
+ });
+ }
+
+ test() {
+ return new Promise(resolve => {
+ Promise.resolve().then(() => {
+ return this.doTest(() => div.mozRequestFullScreen(),
+ "fullscreenchange", true, "after request");
+ }).then(() => {
+ return this.doTest(() => document.mozCancelFullScreen(),
+ "fullscreenchange", false, "after exit");
+ }).then(() => {
+ return this.doTest(() => unattachedDiv.mozRequestFullScreen(),
+ "fullscreenerror", false, "after failed request");
+ }).then(resolve);
+ });
+ }
+}
+
+let gTestcases = [
+ new TestCase(1, PREFIXED_EVENT_ONLY, NO_EVENT_HANDLER),
+ new TestCase(2, PREFIXED_AND_UNPREFIXED_EVENT, NO_EVENT_HANDLER),
+ new TestCase(3, NO_EVENT_HANDLER, PREFIXED_EVENT_ONLY),
+ new TestCase(4, PREFIXED_EVENT_ONLY, PREFIXED_EVENT_ONLY),
+ new TestCase(5, PREFIXED_AND_UNPREFIXED_EVENT, PREFIXED_EVENT_ONLY),
+ new TestCase(6, NO_EVENT_HANDLER, PREFIXED_AND_UNPREFIXED_EVENT),
+ new TestCase(7, PREFIXED_EVENT_ONLY, PREFIXED_AND_UNPREFIXED_EVENT),
+ new TestCase(8, PREFIXED_AND_UNPREFIXED_EVENT, PREFIXED_AND_UNPREFIXED_EVENT),
+ ];
+
+function begin() {
+ TestCase.checkState(false, "at the beginning");
+ runNextTestCase();
+}
+
+function runNextTestCase() {
+ let testcase = gTestcases.shift();
+ if (!testcase) {
+ opener.nextTest();
+ return;
+ }
+ testcase.test().then(runNextTestCase);
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-rollback.html b/dom/html/test/file_fullscreen-rollback.html
new file mode 100644
index 000000000..605a917aa
--- /dev/null
+++ b/dom/html/test/file_fullscreen-rollback.html
@@ -0,0 +1,128 @@
+ <!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=700764
+
+Verifies that cancelFullScreen() rolls back to have the previous full-screen
+element full-screen.
+
+Tests:
+* Request full-screen in doc.
+* Request full-screen in doc on element not descended from full-screen element. Request should be denied.
+* Request full-screen in subdoc.
+* Cancel full-screen in subdoc, doc should be full-screen.
+* Request full-screen in subdoc.
+* Removing FSE should fully-exit full-screen.
+
+
+-->
+<head>
+ <title>Test for Bug 700764</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+</head>
+<body>
+
+<div id="fse">
+ <div id="fse-inner">
+ <iframe id="subdoc" allowfullscreen src="data:text/html,<html><body bgcolor='black'></body></html>"></iframe>
+ </div>
+</div>
+
+<div id="non-fse"></div>
+
+<script type="application/javascript">
+
+/** Test for Bug 700764 **/
+
+function ok(condition, msg) {
+ opener.ok(condition, "[rollback] " + msg);
+ if (!condition) {
+ opener.finish();
+ }
+}
+
+function is(a, b, msg) {
+ opener.is(a, b, "[rollback] " + msg);
+ if (a != b) {
+ opener.finish();
+ }
+}
+
+function enterFullscreen(element, callback) {
+ addFullscreenChangeContinuation("enter", callback);
+ element.focus();
+ element.requestFullscreen();
+}
+
+function revertFullscreen(doc, callback) {
+ ok(doc.fullscreenElement != null, "Should only exit fullscreen on a fullscreen doc");
+ addFullscreenChangeContinuation("exit", callback, doc);
+ doc.exitFullscreen();
+}
+
+function e(id) {
+ return document.getElementById(id);
+}
+
+function requestFullscreen(element) {
+ element.focus();
+ element.requestFullscreen();
+}
+
+function begin() {
+ enterFullscreen(e("fse"), change1);
+}
+
+function change1() {
+ is(document.fullscreenElement, e("fse"), "Body should be FSE");
+ // Request full-screen from element not descendent from current FSE.
+ addFullscreenErrorContinuation(error1);
+ requestFullscreen(e("non-fse"));
+}
+
+function error1() {
+ is(document.fullscreenElement, e("fse"), "FSE should not change");
+ var iframe = e("subdoc");
+ enterFullscreen(iframe.contentDocument.body, change2);
+}
+
+function change2() {
+ var iframe = e("subdoc");
+ is(document.fullscreenElement, iframe, "Subdoc container should be FSE.");
+ is(iframe.contentDocument.fullscreenElement, iframe.contentDocument.body, "Subdoc body should be FSE in subdoc");
+ revertFullscreen(document, change3);
+}
+
+function change3() {
+ is(document.fullscreenElement, e("fse"), "FSE should rollback to FSE.");
+ revertFullscreen(document, change4);
+}
+
+function change4() {
+ is(document.fullscreenElement, null, "Should have left full-screen entirely");
+ enterFullscreen(e("fse"), change5);
+}
+
+function change5() {
+ is(document.fullscreenElement, e("fse"), "FSE should be e('fse')");
+ enterFullscreen(e("fse-inner"), change6);
+}
+
+function change6() {
+ addFullscreenChangeContinuation("exit", change7);
+ var element = e('fse-inner');
+ is(document.fullscreenElement, element, "FSE should be e('fse-inner')");
+ element.parentNode.removeChild(element);
+}
+
+function change7() {
+ is(document.fullscreenElement, null, "Should have fully exited full-screen mode when removed FSE from doc");
+ opener.nextTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-scrollbar.html b/dom/html/test/file_fullscreen-scrollbar.html
new file mode 100644
index 000000000..76a090681
--- /dev/null
+++ b/dom/html/test/file_fullscreen-scrollbar.html
@@ -0,0 +1,126 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Test for Bug 1201798</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="file_fullscreen-utils.js"></script>
+ <style>
+ html, body, #measure {
+ width: 100%; height: 100%;
+ }
+ #ref-outer { width: 100px; height: 100px; overflow: scroll; }
+ #ref-inner { width: 100%; height: 100%; }
+ </style>
+</head>
+<body>
+<div id="measure"></div>
+<div style="height: 1000vh; width: 1000vw"></div>
+<div id="ref-outer">
+ <div id="ref-inner"></div>
+</div>
+<div id="fullscreen"></div>
+<script type="text/javascript">
+
+/** Test for Bug 1201798 */
+
+var info = msg => opener.info("[scrollbar] " + msg);
+var ok = (cond, msg) => opener.ok(cond, "[scrollbar] " + msg);
+var is = (a, b, msg) => opener.is(a, b, "[scrollbar] " + msg);
+
+var gVerticalScrollbarWidth, gHorizontalScrollbarWidth;
+var gMeasureDiv = document.getElementById("measure");
+var gFullscreenDiv = document.getElementById("fullscreen");
+
+function getMeasureRect() {
+ return gMeasureDiv.getBoundingClientRect();
+}
+
+function triggerFrameReconstruction() {
+ info("Triggering a force frame reconstruction");
+ var docElem = document.documentElement;
+ var wm = window.getComputedStyle(docElem).writingMode;
+ if (wm == "horizontal-tb") {
+ docElem.style.writingMode = "vertical-rl";
+ } else {
+ docElem.style.writingMode = "horizontal-tb";
+ }
+ docElem.getBoundingClientRect();
+}
+
+function assertHasScrollbars(elem) {
+ var rect = getMeasureRect();
+ is(rect.width, screen.width - gVerticalScrollbarWidth,
+ `Should have vertical scrollbar when ${elem} is in fullscreen`);
+ is(rect.height, screen.height - gHorizontalScrollbarWidth,
+ `Should have horizontal scrollbar when ${elem} is in fullscreen`);
+}
+
+function assertHasNoScrollbars(elem) {
+ var rect = getMeasureRect();
+ is(rect.width, screen.width,
+ `Should not have vertical scrollbar when ${elem} is in fullscreen`);
+ is(rect.height, screen.height,
+ `Should not have horizontal scrollbar when ${elem} is in fullscreen`);
+}
+
+function checkScrollbars(elem, shouldHaveScrollbars) {
+ is(elem, document.fullscreenElement,
+ "Should only check the current fullscreen element");
+ var assertFunc = shouldHaveScrollbars ?
+ assertHasScrollbars : assertHasNoScrollbars;
+ assertFunc(elem);
+ triggerFrameReconstruction();
+ assertFunc(elem);
+}
+
+function begin() {
+ if (window.matchMedia("(-moz-overlay-scrollbar").matches) {
+ // If overlay scrollbar is enabled, the scrollbar is not measurable,
+ // so we skip this test in that case.
+ info("Skip this test because of overlay scrollbar");
+ opener.nextTest();
+ return;
+ }
+
+ var rectOuter = document.getElementById("ref-outer").getBoundingClientRect();
+ var rectInner = document.getElementById("ref-inner").getBoundingClientRect();
+ gVerticalScrollbarWidth = rectOuter.width - rectInner.width;
+ gHorizontalScrollbarWidth = rectOuter.height - rectInner.height;
+ ok(gVerticalScrollbarWidth != 0, "Should have vertical scrollbar");
+ ok(gHorizontalScrollbarWidth != 0, "Should have horizontal scrollbar");
+
+ info("Entering fullscreen on root");
+ addFullscreenChangeContinuation("enter", enteredFullscreenOnRoot);
+ document.documentElement.requestFullscreen();
+}
+
+function enteredFullscreenOnRoot() {
+ checkScrollbars(document.documentElement, true);
+ info("Entering fullscreen on div");
+ addFullscreenChangeContinuation("enter", enteredFullscreenOnDiv);
+ gFullscreenDiv.requestFullscreen();
+}
+
+function enteredFullscreenOnDiv() {
+ checkScrollbars(gFullscreenDiv, false);
+ info("Exiting fullscreen on div");
+ addFullscreenChangeContinuation("exit", exitedFullscreenOnDiv);
+ document.exitFullscreen();
+}
+
+function exitedFullscreenOnDiv() {
+ checkScrollbars(document.documentElement, true);
+ info("Exiting fullscreen on root");
+ addFullscreenChangeContinuation("exit", exitedFullscreenOnRoot);
+ document.exitFullscreen();
+}
+
+function exitedFullscreenOnRoot() {
+ opener.nextTest();
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-selector.html b/dom/html/test/file_fullscreen-selector.html
new file mode 100644
index 000000000..9aceb659e
--- /dev/null
+++ b/dom/html/test/file_fullscreen-selector.html
@@ -0,0 +1,178 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 1199522</title>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="file_fullscreen-utils.js"></script>
+ <style>
+ div {
+ position: fixed;
+ top: 20px; height: 50px;
+ opacity: 0.3;
+ border: 5px solid black;
+ box-sizing: border-box;
+ }
+ #fullscreen0 {
+ left: 50px; width: 50px;
+ background: #ff0000;
+ border-color: #800000;
+ }
+ #fullscreen1 {
+ left: 100px; width: 50px;
+ background: #00ff00;
+ border-color: #008000;
+ }
+ #fullscreen2 {
+ left: 150px; width: 50px;
+ background: #0000ff;
+ border-color: #000080;
+ }
+ </style>
+</head>
+<body>
+<script type="application/javascript">
+
+/** Test for Bug 1199522 **/
+
+function info(msg) {
+ opener.info("[selector] " + msg);
+}
+
+function ok(condition, msg) {
+ opener.ok(condition, "[selector] " + msg);
+}
+
+function is(a, b, msg) {
+ opener.is(a, b, "[selector] " + msg);
+}
+
+function rectEquals(rect1, rect2) {
+ return rect1.x == rect2.x && rect1.y == rect2.y &&
+ rect1.width == rect2.width && rect1.height == rect2.height;
+}
+
+function getViewportRect() {
+ return new DOMRect(0, 0, window.innerWidth, window.innerHeight);
+}
+
+var fullscreenElems = [];
+
+function checkFullscreenState(elem, hasState, viewportRect) {
+ var id = elem.id;
+ var rect = elem.getBoundingClientRect();
+ if (hasState) {
+ ok(elem.matches(":fullscreen"),
+ `${id} should match selector ":fullscreen"`);
+ ok(rectEquals(rect, viewportRect),
+ `The bounding rect of ${id} should match the viewport`);
+ } else {
+ ok(!elem.matches(":fullscreen"),
+ `${id} should not match selector ":fullscreen"`);
+ ok(rectEquals(rect, elem.initialRect),
+ `The bounding rect of ${id} should match its initial state`);
+ }
+}
+
+function checkFullscreenStates(states) {
+ var viewportRect = getViewportRect();
+ fullscreenElems.forEach((elem, index) => {
+ checkFullscreenState(elem, states[index], viewportRect);
+ });
+}
+
+function begin() {
+ fullscreenElems.push(document.getElementById('fullscreen0'));
+ fullscreenElems.push(document.getElementById('fullscreen1'));
+ fullscreenElems.push(document.getElementById('fullscreen2'));
+
+ var viewportRect = getViewportRect();
+ for (var elem of fullscreenElems) {
+ var rect = elem.getBoundingClientRect();
+ var id = elem.id;
+ elem.initialRect = rect;
+ ok(!elem.matches(":fullscreen"),
+ `${id} should not match selector ":fullscreen"`);
+ ok(!rectEquals(elem.initialRect, viewportRect),
+ `The initial bounding rect of ${id} should not match the viewport`);
+ }
+
+ info("Entering fullscreen on fullscreen0");
+ addFullscreenChangeContinuation("enter", enter0);
+ fullscreenElems[0].requestFullscreen();
+}
+
+function enter0() {
+ checkFullscreenStates([true, false, false]);
+ info("Entering fullscreen on fullscreen1");
+ addFullscreenChangeContinuation("enter", enter1);
+ fullscreenElems[1].requestFullscreen();
+}
+
+function enter1() {
+ checkFullscreenStates([true, true, false]);
+ info("Entering fullscreen on fullscreen2");
+ addFullscreenChangeContinuation("enter", enter2);
+ fullscreenElems[2].requestFullscreen();
+}
+
+function enter2() {
+ checkFullscreenStates([true, true, true]);
+ info("Leaving fullscreen on fullscreen2");
+ addFullscreenChangeContinuation("exit", exit2);
+ document.exitFullscreen();
+}
+
+function exit2() {
+ checkFullscreenStates([true, true, false]);
+ info("Leaving fullscreen on fullscreen1");
+ addFullscreenChangeContinuation("exit", exit1);
+ document.exitFullscreen();
+}
+
+function exit1() {
+ checkFullscreenStates([true, false, false]);
+ info("Leaving fullscreen on fullscreen0");
+ addFullscreenChangeContinuation("exit", exit0);
+ document.exitFullscreen();
+}
+
+function exit0() {
+ checkFullscreenStates([false, false, false]);
+
+ info("Entering fullscreen on all elements");
+ var count = 0;
+ function listener() {
+ if (++count == 3) {
+ document.removeEventListener("fullscreenchange", listener);
+ enterAll();
+ }
+ }
+ document.addEventListener("fullscreenchange", listener);
+ fullscreenElems[0].requestFullscreen();
+ fullscreenElems[1].requestFullscreen();
+ fullscreenElems[2].requestFullscreen();
+}
+
+function enterAll() {
+ checkFullscreenStates([true, true, true]);
+ info("Fully-exiting fullscreen");
+ addFullscreenChangeContinuation("exit", exitAll);
+ synthesizeKey("VK_ESCAPE", {});
+}
+
+function exitAll() {
+ checkFullscreenStates([false, false, false]);
+ opener.nextTest();
+}
+
+</script>
+</pre>
+<div id="fullscreen0">
+ <div id="fullscreen1">
+ <div id="fullscreen2">
+ </div>
+ </div>
+</div>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-svg-element.html b/dom/html/test/file_fullscreen-svg-element.html
new file mode 100644
index 000000000..dd0f3b593
--- /dev/null
+++ b/dom/html/test/file_fullscreen-svg-element.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+ <!--
+ https://bugzilla.mozilla.org/show_bug.cgi?id=735031
+ Bug 735031 - Fullscreen API implementation assumes an HTML Element
+ -->
+ <head>
+ <title>Bug 735031</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js">
+ </script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js">
+ </script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ </head>
+ <body>
+ <a target="_blank"
+ href="https://bugzilla.mozilla.org/show_bug.cgi?id=73503">
+ Mozilla Bug 735031</a>
+
+ <svg id="svg-elem" width="100" height="100" viewbox="0 0 100 100">
+ <rect x="10" y="10" width="50" height="50"
+ fill="black" stroke="blue" stroke-width="2"/>
+ </svg>
+
+ <pre id="test">
+ <script type="application/javascript">
+ /*
+ * Test for Bug 735031
+ * Test locking non-html element.
+ */
+ function begin() {
+ var elem = document.getElementById("svg-elem")
+ , elemWasLocked = false;
+
+ document.addEventListener("fullscreenchange", function (e) {
+ if (document.fullscreenElement === elem) {
+ elemWasLocked = true;
+ document.exitFullscreen();
+ } else {
+ opener.ok(elemWasLocked, "Expected SVG elem to become locked.");
+ opener.nextTest();
+ }
+ }, false);
+ elem.requestFullscreen();
+ }
+ </script>
+ </pre>
+ </body>
+</html>
diff --git a/dom/html/test/file_fullscreen-top-layer.html b/dom/html/test/file_fullscreen-top-layer.html
new file mode 100644
index 000000000..fe3d2cf9e
--- /dev/null
+++ b/dom/html/test/file_fullscreen-top-layer.html
@@ -0,0 +1,160 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <title>Test for Bug 1126230</title>
+ <style>
+ #back {
+ position: fixed !important;
+ z-index: 2147483647 !important;
+ top: 0 !important; left: 0 !important;
+ right: 0 !important; bottom: 0 !important;
+ width: 100% !important; height: 100% !important;
+ }
+ #parent {
+ position: fixed;
+ z-index: -2147483748;
+ width: 0; height: 0;
+ overflow: hidden;
+ opacity: 0;
+ mask: url(#mask);
+ clip: rect(0, 0, 0, 0);
+ clip-path: url(#clipPath);
+ filter: opacity(0%);
+ will-change: transform;
+ perspective: 10px;
+ transform: scale(0);
+ }
+ /* The following styles are copied from ua.css to ensure that
+ * no other style change may trigger frame reconstruction */
+ :root {
+ overflow: hidden !important;
+ }
+ .two #fullscreen {
+ position: fixed !important;
+ top: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
+ z-index: 2147483647 !important;
+ width: 100% !important;
+ height: 100% !important;
+ margin: 0 !important;
+ min-width: 0 !important;
+ max-width: none !important;
+ min-height: 0 !important;
+ max-height: none !important;
+ box-sizing: border-box !important;
+ }
+ </style>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <script type="text/javascript" src="file_fullscreen-utils.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1126230">Mozilla Bug 1126230</a>
+<div id="parent">
+ <div id="fullscreen" style="background-color: green"></div>
+</div>
+<div id="back" style="background-color: red"></div>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
+ <defs>
+ <clipPath id="clipPath"></clipPath>
+ <mask id="mask"></mask>
+ </defs>
+</svg>
+<script>
+const gParentProperties = [
+ "position", "zIndex", "overflow",
+ "opacity", "mask", "clip", "clipPath",
+ "filter", "willChange", "transform"
+];
+
+var gInitialVals = {};
+
+const gParent = document.getElementById("parent");
+const gFullscreen = document.getElementById("fullscreen");
+const gBack = document.getElementById("back");
+
+function is(a, b, msg) {
+ opener.is(a, b, "[top-layer] " + msg);
+}
+
+function isnot(a, b, msg) {
+ opener.isnot(a, b, "[top-layer] " + msg);
+}
+
+function ok(cond, msg) {
+ opener.ok(cond, "[top-layer] " + msg);
+}
+
+function synthesizeMouseAtWindowCenter() {
+ synthesizeMouseAtPoint(innerWidth / 2, innerHeight / 2, {});
+}
+
+
+var tests = ["one", "two"];
+
+function begin() {
+ // record initial computed style of #parent
+ const style = getComputedStyle(gParent);
+ for (var prop of gParentProperties) {
+ gInitialVals[prop] = style[prop];
+ }
+
+ nextTest();
+}
+
+function nextTest() {
+ document.body.className = tests.shift();
+ // trigger a reflow to ensure the state of frames before fullscreen
+ gFullscreen.getBoundingClientRect();
+
+ ok(!document.fullscreenElement, "Shouldn't be in fullscreen");
+ // check window snapshot
+ assertWindowPureColor(window, "red");
+ // simulate click
+ window.addEventListener("click", firstClick);
+ synthesizeMouseAtWindowCenter();
+}
+
+function firstClick(evt) {
+ window.removeEventListener("click", firstClick);
+ is(evt.target, gBack, "Click target should be #back before fullscreen");
+ addFullscreenChangeContinuation("enter", enterFullscreen);
+ gFullscreen.requestFullscreen();
+}
+
+function enterFullscreen() {
+ ok(document.fullscreenElement, "Should now be in fullscreen");
+ // check window snapshot
+ assertWindowPureColor(window, "green");
+ // check computed style of #parent
+ const style = getComputedStyle(gParent);
+ for (var prop of gParentProperties) {
+ is(style[prop], gInitialVals[prop],
+ `Computed style ${prop} of #parent should not be changed`);
+ }
+ // simulate click
+ window.addEventListener("click", secondClick);
+ synthesizeMouseAtWindowCenter();
+}
+
+function secondClick(evt) {
+ window.removeEventListener("click", secondClick);
+ is(evt.target, gFullscreen, "Click target should be #fullscreen now");
+ addFullscreenChangeContinuation("exit", exitFullscreen);
+ document.exitFullscreen();
+}
+
+function exitFullscreen() {
+ if (tests.length > 0) {
+ nextTest();
+ } else {
+ opener.nextTest();
+ }
+}
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-unprefix-disabled-inner.html b/dom/html/test/file_fullscreen-unprefix-disabled-inner.html
new file mode 100644
index 000000000..632a6c0ce
--- /dev/null
+++ b/dom/html/test/file_fullscreen-unprefix-disabled-inner.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <title>Test for Bug 1268749</title>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+ <div id="fullscreen"></div>
+<script>
+
+function ok(condition, msg) {
+ opener.opener.ok(condition, "[unprefix-disabled] " + msg);
+}
+
+function is(a, b, msg) {
+ opener.opener.is(a, b, "[unprefix-disabled] " + msg);
+}
+
+function info(msg) {
+ opener.opener.info("[unprefix-disabled] " + msg);
+}
+
+SimpleTest.requestFlakyTimeout(
+ "need to wait for a while to confirm no unexpected event is dispatched");
+
+let div = document.getElementById("fullscreen");
+let unattachedDiv = document.createElement('div');
+
+function begin() {
+ ok(!("requestFullscreen" in div), "No element.requestFullscreen");
+ ok(!("exitFullscreen" in document), "No document.exitFullscreen");
+ ok(!("fullscreen" in document), "No document.fullscreen");
+ ok(!("fullscreenElement" in document), "No document.fullscreenElement");
+ ok(!("fullscreenEnabled" in document), "No document.fullscreenEnabled");
+ ok(!("onfullscreenchange" in document), "No document.onfullscreenchange");
+ ok(!("onfullscreenerror" in document), "No document.onfullscreenerror");
+
+ for (var event of ["fullscreenchange", "fullscreenerror"]) {
+ let customEvent = new Event(event, {bubbles: true});
+ let gotCustomEventFromWindow = false;
+ let gotCustomEventFromDocument = false;
+ let listenerForWindow = evt => {
+ ok(!gotCustomEventFromWindow,
+ "Should get custom event from window only once");
+ ok(evt == customEvent, "Should get the desired custom event");
+ gotCustomEventFromWindow = true;
+ };
+ let listenerForDocument = evt => {
+ ok(!gotCustomEventFromDocument,
+ "Should get custom event from document only once");
+ ok(evt == customEvent, "Should get the desired custom event");
+ gotCustomEventFromDocument = true;
+ };
+ window.addEventListener(event, listenerForWindow);
+ document.addEventListener(event, listenerForDocument);
+ document.dispatchEvent(customEvent);
+ ok(gotCustomEventFromWindow, "Should get the custom event from window");
+ ok(gotCustomEventFromDocument, "Should get the custom event from document");
+ window.removeEventListener(event, listenerForWindow);
+ document.removeEventListener(event, listenerForDocument);
+
+ for (var target of [window, document]) {
+ target.addEventListener(event, () => {
+ ok(false, `No ${event} should be triggered on ${target}`);
+ });
+ }
+ }
+
+ document.addEventListener("mozfullscreenchange", enteredFullscreen);
+ SimpleTest.executeSoon(() => div.mozRequestFullScreen());
+}
+
+function enteredFullscreen() {
+ document.removeEventListener("mozfullscreenchange", enteredFullscreen);
+ document.addEventListener("mozfullscreenchange", exitedFullscreen);
+ SimpleTest.executeSoon(() => document.mozCancelFullScreen());
+}
+
+function exitedFullscreen() {
+ document.removeEventListener("mozfullscreenchange", exitedFullscreen);
+ document.addEventListener("mozfullscreenerror", errorFullscreen);
+ SimpleTest.executeSoon(() => unattachedDiv.mozRequestFullScreen());
+}
+
+function errorFullscreen() {
+ document.removeEventListener("mozfullscreenerror", errorFullscreen);
+ // Wait a short time before exiting this test to confirm that there is
+ // really no unwanted event gets dispatched.
+ setTimeout(() => opener.finish(), 200);
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-unprefix-disabled.html b/dom/html/test/file_fullscreen-unprefix-disabled.html
new file mode 100644
index 000000000..59737ec1d
--- /dev/null
+++ b/dom/html/test/file_fullscreen-unprefix-disabled.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="UTF-8">
+ <title>Test for Bug 1268749</title>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<script>
+
+var gWindow = null;
+
+function begin() {
+ SpecialPowers.pushPrefEnv({
+ "set": [["full-screen-api.unprefix.enabled", false]]
+ }, () => {
+ gWindow = window.open("file_fullscreen-unprefix-disabled-inner.html",
+ "", "width=500,height=500");
+ gWindow.addEventListener("load", () => {
+ gWindow.focus();
+ SimpleTest.waitForFocus(() => gWindow.begin(), gWindow);
+ });
+ });
+}
+
+function finish() {
+ gWindow.close();
+ SpecialPowers.popPrefEnv(opener.nextTest);
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_fullscreen-utils.js b/dom/html/test/file_fullscreen-utils.js
new file mode 100644
index 000000000..d1af72f8c
--- /dev/null
+++ b/dom/html/test/file_fullscreen-utils.js
@@ -0,0 +1,82 @@
+
+// Returns true if the window occupies the entire screen.
+// Note this only returns true once the transition from normal to
+// fullscreen mode is complete.
+function inFullscreenMode(win) {
+ return win.innerWidth == win.screen.width &&
+ win.innerHeight == win.screen.height;
+}
+
+// Returns true if the window is in normal mode, i.e. non fullscreen mode.
+// Note this only returns true once the transition from fullscreen back to
+// normal mode is complete.
+function inNormalMode(win) {
+ return win.innerWidth == win.normalSize.w &&
+ win.innerHeight == win.normalSize.h;
+}
+
+// Adds a listener that will be called once a fullscreen transition
+// is complete. When type==='enter', callback is called when we've
+// received a fullscreenchange event, and the fullscreen transition is
+// complete. When type==='exit', callback is called when we've
+// received a fullscreenchange event and the window dimensions match
+// the window dimensions when the window opened (so don't resize the
+// window while running your test!). inDoc is the document which
+// the listeners are added on, if absent, the listeners are added to
+// the current document.
+function addFullscreenChangeContinuation(type, callback, inDoc) {
+ var doc = inDoc || document;
+ var topWin = doc.defaultView.top;
+ // Remember the window size in non-fullscreen mode.
+ if (!topWin.normalSize) {
+ topWin.normalSize = {
+ w: window.innerWidth,
+ h: window.innerHeight
+ };
+ }
+ function checkCondition() {
+ if (type == "enter") {
+ return inFullscreenMode(topWin);
+ } else if (type == "exit") {
+ // If we just revert the state to a previous fullscreen state,
+ // the window won't back to the normal mode. Hence we check
+ // fullscreenElement first here. Note that we need to check
+ // the fullscreen element of the outmost document here instead
+ // of the current one.
+ return topWin.document.fullscreenElement || inNormalMode(topWin);
+ } else {
+ throw "'type' must be either 'enter', or 'exit'.";
+ }
+ }
+ function invokeCallback(event) {
+ // Use async call after a paint to workaround unfinished fullscreen
+ // change even when the window size has changed on Linux.
+ requestAnimationFrame(() => setTimeout(() => callback(event), 0), 0);
+ }
+ function onFullscreenChange(event) {
+ doc.removeEventListener("fullscreenchange", onFullscreenChange, false);
+ if (checkCondition()) {
+ invokeCallback(event);
+ return;
+ }
+ function onResize() {
+ if (checkCondition()) {
+ topWin.removeEventListener("resize", onResize, false);
+ invokeCallback(event);
+ }
+ }
+ topWin.addEventListener("resize", onResize, false);
+ }
+ doc.addEventListener("fullscreenchange", onFullscreenChange, false);
+}
+
+// Calls |callback| when the next fullscreenerror is dispatched to inDoc||document.
+function addFullscreenErrorContinuation(callback, inDoc) {
+ var doc = inDoc || document;
+ var listener = function(event) {
+ doc.removeEventListener("fullscreenerror", listener, false);
+ setTimeout(function(){callback(event);}, 0);
+ };
+ doc.addEventListener("fullscreenerror", listener, false);
+}
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if1.html b/dom/html/test/file_iframe_sandbox_a_if1.html
new file mode 100644
index 000000000..b60d52ca0
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if1.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ I am sandboxed without any permissions
+ <iframe id="if_2a" src="file_iframe_sandbox_a_if2.html" height="10" width="10"></iframe>
+ <iframe id="if_2b" sandbox="allow-scripts" src="file_iframe_sandbox_a_if2.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_a_if10.html b/dom/html/test/file_iframe_sandbox_a_if10.html
new file mode 100644
index 000000000..14306eb61
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if10.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<frameset>
+ <frame src="file_iframe_sandbox_a_if11.html">
+ <frame src="file_iframe_sandbox_a_if16.html">
+</frameset>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_a_if11.html b/dom/html/test/file_iframe_sandbox_a_if11.html
new file mode 100644
index 000000000..8eee71df1
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if11.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script>
+ function doStuff() {
+ try {
+ window.parent.parent.ok_wrapper(false, "a frame inside a sandboxed iframe should NOT be same origin with the iframe's parent");
+ }
+ catch (e) {
+ window.parent.parent.postMessage({ok: true, desc: "a frame inside a sandboxed iframe is not same origin with the iframe's parent"}, "*");
+ }
+ }
+ </script>
+</head>
+<frameset>
+ <frame onload='doStuff()' src="file_iframe_sandbox_a_if12.html">
+</frameset>
+I'm a &lt;frame&gt; inside an iframe which is sandboxed with 'allow-scripts allow-forms'
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if12.html b/dom/html/test/file_iframe_sandbox_a_if12.html
new file mode 100644
index 000000000..d49d4e562
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if12.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script>
+function doStuff() {
+ try {
+ window.parent.parent.parent.ok_wrapper(false, "a frame inside a frame inside a sandboxed iframe should NOT be same origin with the iframe's parent");
+ }
+ catch (e) {
+ dump("caught some e if12\n");
+ window.parent.parent.parent.postMessage({ok: true, desc: "a frame inside a frame inside a sandboxed iframe is not same origin with the iframe's parent"}, "*");
+ }
+}
+</script>
+<body onload='doStuff()'>
+ I'm a &lt;frame&gt; inside a &lt;frame&gt; inside an iframe which is sandboxed with 'allow-scripts allow-forms'
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if13.html b/dom/html/test/file_iframe_sandbox_a_if13.html
new file mode 100644
index 000000000..8737a7682
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if13.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 886262</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<body>
+ <object data="file_iframe_sandbox_a_if14.html"></object>
+</body>
+
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_a_if14.html b/dom/html/test/file_iframe_sandbox_a_if14.html
new file mode 100644
index 000000000..77210fca0
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if14.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 886262</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ window.addEventListener("message", receiveMessage, false);
+
+ function receiveMessage(event)
+ {
+ window.parent.parent.postMessage({ok: event.data.ok, desc: "objects containing " + event.data.desc}, "*");
+ }
+
+ function doStuff() {
+ try {
+ window.parent.parent.ok_wrapper(false, "an object inside a sandboxed iframe should NOT be same origin with the iframe's parent");
+ }
+ catch (e) {
+ window.parent.parent.postMessage({ok: true, desc: "an object inside a sandboxed iframe is not same origin with the iframe's parent"}, "*");
+ }
+ }
+</script>
+
+<body onload='doStuff()'>
+I'm a &lt;object&gt; inside an iframe which is sandboxed with 'allow-scripts allow-forms'
+
+ <object data="file_iframe_sandbox_a_if15.html"></object>
+</body>
+
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if15.html b/dom/html/test/file_iframe_sandbox_a_if15.html
new file mode 100644
index 000000000..9c5a003d7
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if15.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 886262</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+function doStuff() {
+ try {
+ window.parent.parent.parent.ok_wrapper(false, "an object inside a frame or object inside a sandboxed iframe should NOT be same origin with the iframe's parent");
+ }
+ catch (e) {
+ window.parent.parent.parent.postMessage({ok: true, desc: "an object inside a frame or object inside a sandboxed iframe is not same origin with the iframe's parent"}, "*");
+ }
+
+ // Check that sandboxed forms browsing context flag NOT set by attempting to submit a form.
+ document.getElementById('a_form').submit();
+}
+</script>
+
+<body onload='doStuff()'>
+ I'm a &lt;object&gt; inside a &lt;frame&gt; or &lt;object&gt; inside an iframe which is sandboxed with 'allow-scripts allow-forms'
+
+ <form method="get" action="file_iframe_sandbox_form_pass.html" id="a_form">
+ First name: <input type="text" name="firstname">
+ Last name: <input type="text" name="lastname">
+ <input type="submit" id="a_button">
+ </form>
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if16.html b/dom/html/test/file_iframe_sandbox_a_if16.html
new file mode 100644
index 000000000..f92531465
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if16.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 886262</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ window.addEventListener("message", receiveMessage, false);
+
+ function receiveMessage(event)
+ {
+ window.parent.parent.postMessage({ok: event.data.ok, desc: "objects containing " + event.data.desc}, "*");
+ }
+</script>
+
+<body>
+I'm a &lt;frame&gt; inside an iframe which is sandboxed with 'allow-scripts allow-forms'
+
+ <object data="file_iframe_sandbox_a_if15.html"></object>
+</body>
+
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if17.html b/dom/html/test/file_iframe_sandbox_a_if17.html
new file mode 100644
index 000000000..a736924bf
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if17.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 886262</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ function doTest() {
+ var if_18_19 = document.getElementById('if_18_19');
+ if_18_19.sandbox = "allow-scripts allow-same-origin";
+ if_18_19.contentWindow.postMessage("go", "*");
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed but with "allow-scripts". I change the sandbox flags on if_18_19 to
+ "allow-scripts allow-same-origin" then get it to re-navigate itself to
+ file_iframe_sandbox_a_if18.html, which attemps to call a function in my parent.
+ This should fail since my sandbox flags should be copied to it when the sandbox
+ flags are changed.
+
+ <iframe sandbox="allow-scripts" id="if_18_19" src="file_iframe_sandbox_a_if19.html" height="10" width="10"></iframe>
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if18.html b/dom/html/test/file_iframe_sandbox_a_if18.html
new file mode 100644
index 000000000..bbe90970d
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if18.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 886262</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ function doTest() {
+ try {
+ window.parent.parent.ok_wrapper(false, "an iframe in an iframe SHOULD copy its parent's sandbox flags when its sandbox flags are changed");
+ }
+ catch (e) {
+ window.parent.parent.postMessage({ok: true, desc: "an iframe in an iframe copies its parent's sandbox flags when its sandbox flags are changed"}, "*");
+ }
+ }
+</script>
+
+<body onload="doTest()">
+ I'm an iframe whose sandbox flags have been changed to include allow-same-origin.
+ I should not be able to call a function in my parent's parent because my parent's
+ iframe does not have allow-same-origin set.
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if19.html b/dom/html/test/file_iframe_sandbox_a_if19.html
new file mode 100644
index 000000000..a065a9450
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if19.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 886262</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+
+<script>
+ window.addEventListener("message", function(e){
+ window.open("file_iframe_sandbox_a_if18.html", "_self");
+ }, false);
+</script>
+
+<body>
+ I'm just here to navigate to file_iframe_sandbox_a_if18.html after my owning
+ iframe has had allow-same-origin added.
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if2.html b/dom/html/test/file_iframe_sandbox_a_if2.html
new file mode 100644
index 000000000..72bde69e4
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if2.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="text/javascript">
+function doStuff() {
+ // should NOT be able to execute scripts
+ window.parent.parent.postMessage({ok: false, desc: "a document within an iframe sandboxed with sandbox='' should NOT be able to execute scripts"}, "*");
+}
+</script>
+
+<body onLoad="doStuff()">
+ I am NOT sandboxed or am sandboxed with "allow-scripts" but am contained within an iframe sandboxed with sandbox = ""
+ or am sandboxed with sandbox='' inside an iframe sandboxed with "allow-scripts"
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if3.html b/dom/html/test/file_iframe_sandbox_a_if3.html
new file mode 100644
index 000000000..c103c19f2
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if3.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+
+<script type="text/javascript">
+ function ok_wrapper(condition, msg) {
+ window.parent.ok_wrapper(condition, msg);
+ }
+</script>
+
+<body>
+ I am sandboxed but with "allow-scripts"
+
+ <iframe id='if_4' src='file_iframe_sandbox_a_if4.html' height="10" width="10"></iframe>
+ <iframe id='if_7' src='file_iframe_sandbox_a_if7.html' height="10" width="10"></iframe>
+ <iframe id='if_2' sandbox='' src='file_iframe_sandbox_a_if2.html' height="10" width="10"></iframe>
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if4.html b/dom/html/test/file_iframe_sandbox_a_if4.html
new file mode 100644
index 000000000..2bd727e96
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if4.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+
+<script type="text/javascript">
+function doStuff() {
+ try {
+ window.parent.ok_wrapper(false, "a document contained within a sandboxed document without 'allow-same-origin' should NOT be same domain with its parent");
+ } catch(e) {
+ window.parent.parent.postMessage({type: "ok", ok: true, desc: "a document contained within a sandboxed document without 'allow-same-origin' should NOT be same domain with its parent"}, "*");
+ }
+
+ try {
+ window.parent.parent.ok_wrapper(false, "a document contained within a sandboxed document without 'allow-same-origin' should NOT be same domain with the top level");
+ } catch(e) {
+ window.parent.parent.postMessage({type: "ok", ok: true, desc: "a document contained within a sandboxed document without 'allow-same-origin' should NOT be same domain with the top level"}, "*");
+ }
+}
+</script>
+
+<body onLoad="doStuff()">
+ I am not sandboxed but contained within a sandboxed document with 'allow-scripts'
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if5.html b/dom/html/test/file_iframe_sandbox_a_if5.html
new file mode 100644
index 000000000..dfa0fed01
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if5.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+
+<script type="text/javascript">
+ function ok_wrapper(result, desc) {
+ window.parent.ok_wrapper(result, desc);
+ }
+</script>
+
+<body>
+ I am sandboxed but with "allow-scripts allow-same-origin"
+
+ <iframe sandbox='allow-scripts allow-same-origin' id='if_6' src='file_iframe_sandbox_a_if6.html' height="10" width="10"></iframe>
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if6.html b/dom/html/test/file_iframe_sandbox_a_if6.html
new file mode 100644
index 000000000..79f15e6ec
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if6.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+
+<script type="text/javascript">
+function doStuff() {
+ window.parent.ok_wrapper(true, "a document sandboxed with 'allow-same-origin' and contained within a sandboxed document with 'allow-same-origin' should be same domain with its parent");
+ window.parent.parent.ok_wrapper(true, "a document sandboxed with 'allow-same-origin' contained within a sandboxed document with 'allow-same-origin' should be same domain with the top level");
+}
+</script>
+
+<body onLoad="doStuff()">
+ I am sandboxed with 'allow-scripts allow-same-origin' and contained within a sandboxed document with 'allow-scripts allow-same-origin'
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if7.html b/dom/html/test/file_iframe_sandbox_a_if7.html
new file mode 100644
index 000000000..6480eebdb
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if7.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="text/javascript">
+function doStuff() {
+ // should be able to execute scripts
+ window.parent.parent.postMessage({ok: true, desc: "a document contained within an iframe contained within an iframe sandboxed with 'allow-scripts' should be able to execute scripts"}, "*");
+}
+</script>
+
+<body onLoad="doStuff()">
+ I am NOT sandboxed but am contained within an iframe contained within an iframe sandboxed with sandbox = "allow-scripts"
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if8.html b/dom/html/test/file_iframe_sandbox_a_if8.html
new file mode 100644
index 000000000..002df5df5
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if8.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script>
+function doSubload() {
+ var if_9 = document.getElementById('if_9');
+ if_9.src = 'file_iframe_sandbox_a_if9.html';
+}
+
+window.doSubload = doSubload;
+
+</script>
+<body>
+ I am sandboxed but with "allow-scripts allow-same-origin". After my initial load, "allow-same-origin" is removed
+ and then I load file_iframe_sandbox_a_if9.html, which attemps to call a function in window.top. This should
+ succeed since the new sandbox flags shouldn't have taken affect on me until I'm reloaded.
+
+ <iframe id='if_9' src='about:blank' height="10" width="10"></iframe>
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_a_if9.html b/dom/html/test/file_iframe_sandbox_a_if9.html
new file mode 100644
index 000000000..da2bcf1fa
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_a_if9.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script>
+function doStuff() {
+ window.parent.parent.ok_wrapper(true, "a subloaded document should inherit the flags of the document, not of the docshell/sandbox attribute");
+}
+</script>
+<body onload='doStuff()'>
+ I'm a subloaded document of file_iframe_sandbox_a_if8.html. I should be able to call a function in window.top
+ because I should be same-origin with it.
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_b_if1.html b/dom/html/test/file_iframe_sandbox_b_if1.html
new file mode 100644
index 000000000..a65cbec6b
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_b_if1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ I am sandboxed without any permissions
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_b_if2.html b/dom/html/test/file_iframe_sandbox_b_if2.html
new file mode 100644
index 000000000..08e745357
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_b_if2.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script>
+ function ok(condition, msg) {
+ window.parent.ok_wrapper(condition, msg);
+ }
+
+ function testXHR() {
+ var xhr = new XMLHttpRequest();
+
+ xhr.open("GET", "file_iframe_sandbox_b_if1.html");
+
+ xhr.onreadystatechange = function (oEvent) {
+ var result = false;
+ if (xhr.readyState == 4) {
+ if (xhr.status == 200) {
+ result = true;
+ }
+ ok(result, "XHR should work normally in an iframe sandboxed with 'allow-same-origin'");
+ }
+ }
+
+ xhr.send(null);
+ }
+
+ function doStuff() {
+ ok(true, "documents sandboxed with 'allow-same-origin' should be able to access their parent");
+
+ // should be able to access document.cookie since we have 'allow-same-origin'
+ ok(document.cookie == "", "a document sandboxed with allow-same-origin should be able to access document.cookie");
+
+ // should be able to access localStorage since we have 'allow-same-origin'
+ ok(window.localStorage, "a document sandboxed with allow-same-origin should be able to access localStorage");
+
+ // should be able to access sessionStorage since we have 'allow-same-origin'
+ ok(window.sessionStorage, "a document sandboxed with allow-same-origin should be able to access sessionStorage");
+
+ testXHR();
+ }
+</script>
+<body onLoad="doStuff()">
+ I am sandboxed but with "allow-same-origin" and "allow-scripts"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_b_if3.html b/dom/html/test/file_iframe_sandbox_b_if3.html
new file mode 100644
index 000000000..350e2ac47
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_b_if3.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script>
+ function ok(result, message) {
+ window.parent.postMessage({ok: result, desc: message}, "*");
+ }
+
+ function testXHR() {
+ // Standard URL should be blocked as we have a unique origin.
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", "file_iframe_sandbox_b_if1.html");
+ xhr.onreadystatechange = function (oEvent) {
+ var result = false;
+ if (xhr.readyState == 4) {
+ if (xhr.status == 0) {
+ result = true;
+ }
+ ok(result, "XHR should be blocked in an iframe sandboxed WITHOUT 'allow-same-origin'");
+ }
+ }
+ xhr.send(null);
+
+ // Blob URL should work as it will have our unique origin.
+ var blobXhr = new XMLHttpRequest();
+ var blobUrl = URL.createObjectURL(new Blob(["wibble"], {type: "text/plain"}));
+ blobXhr.open("GET", blobUrl);
+ blobXhr.onreadystatechange = function () {
+ if (this.readyState == 4) {
+ ok(this.status == 200 && this.response == "wibble", "XHR for a blob URL created in this document should NOT be blocked in an iframe sandboxed WITHOUT 'allow-same-origin'");
+ }
+ }
+ try {
+ blobXhr.send();
+ } catch(e) {
+ ok(false, "failed to send XHR for blob URL: error: " + e);
+ }
+
+ // Data URL should work as it inherits the loader's origin.
+ var dataXhr = new XMLHttpRequest();
+ dataXhr.open("GET", "data:text/html,wibble");
+ dataXhr.onreadystatechange = function () {
+ if (this.readyState == 4) {
+ ok(this.status == 200 && this.response == "wibble", "XHR for a data URL should NOT be blocked in an iframe sandboxed WITHOUT 'allow-same-origin'");
+ }
+ }
+ try {
+ dataXhr.send();
+ } catch(e) {
+ ok(false, "failed to send XHR for data URL: error: " + e);
+ }
+ }
+
+ function doStuff() {
+ try {
+ window.parent.ok(false, "documents sandboxed without 'allow-same-origin' should NOT be able to access their parent");
+ } catch (error) {
+ ok(true, "documents sandboxed without 'allow-same-origin' should NOT be able to access their parent");
+ }
+
+ // should NOT be able to access document.cookie
+ try {
+ var foo = document.cookie;
+ } catch(error) {
+ ok(true, "a document sandboxed without allow-same-origin should NOT be able to access document.cookie");
+ }
+
+ // should NOT be able to access localStorage
+ try {
+ var foo = window.localStorage;
+ } catch(error) {
+ ok(true, "a document sandboxed without allow-same-origin should NOT be able to access localStorage");
+ }
+
+ // should NOT be able to access sessionStorage
+ try {
+ var foo = window.sessionStorage;
+ } catch(error) {
+ ok(true, "a document sandboxed without allow-same-origin should NOT be able to access sessionStorage");
+ }
+
+ testXHR();
+ }
+</script>
+<body onLoad="doStuff()">
+ I am sandboxed but with "allow-scripts"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if1.html b/dom/html/test/file_iframe_sandbox_c_if1.html
new file mode 100644
index 000000000..fff2f6d40
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_c_if1.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.postMessage({ok: result, desc: desc}, "*");
+ }
+
+ function doStuff() {
+ ok(true, "documents sandboxed with allow-scripts should be able to run inline scripts");
+
+ document.getElementById('a_form').submit();
+
+ // trigger the javascript: url test
+ sendMouseEvent({type:'click'}, 'a_link');
+ }
+</script>
+<script src='file_iframe_sandbox_pass.js'></script>
+<body onLoad='ok(true, "documents sandboxed with allow-scripts should be able to run script from event listeners");doStuff();'>
+ I am sandboxed but with "allow-scripts"
+
+ <form method="get" action="file_iframe_sandbox_form_fail.html" id="a_form">
+ First name: <input type="text" name="firstname">
+ Last name: <input type="text" name="lastname">
+ <input type="submit" onclick="doSubmit()" id="a_button">
+ </form>
+
+ <a href = 'javascript:ok(true, "documents sandboxed with allow-scripts should be able to run script from javascript: URLs");' id='a_link'>click me</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if2.html b/dom/html/test/file_iframe_sandbox_c_if2.html
new file mode 100644
index 000000000..b39231919
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_c_if2.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.postMessage({ok: result, desc: desc}, "*");
+ }
+
+ function doStuff() {
+ ok(false, "documents sandboxed without allow-scripts should NOT be able to run inline scripts");
+ }
+</script>
+<script src='file_iframe_sandbox_fail.js'></script>
+<body onLoad='window.parent.postmessage({ok: false, desc: "documents sandboxed without allow-scripts should NOT be able to run script from event handlers"}, "*");doStuff();'>
+ I am sandboxed with no permissions
+ <img src="about:blank" onerror='ok(false, "documents sandboxed without allow-scripts should NOT be able to run script from event handlers");')>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if3.html b/dom/html/test/file_iframe_sandbox_c_if3.html
new file mode 100644
index 000000000..aca5d3356
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_c_if3.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+</head>
+<script type="text/javascript">
+ function doStuff() {
+ dump("*** c_if3 has loaded\n");
+ // try and submit the form - this should succeed
+ document.getElementById('a_form').submit();
+ }
+</script>
+<body onLoad="doStuff()">
+ I am sandboxed but with "allow-scripts allow-forms"
+
+ <form method="get" action="file_iframe_sandbox_form_pass.html" id="a_form">
+ First name: <input type="text" name="firstname">
+ Last name: <input type="text" name="lastname">
+ <input type="submit" onclick="doSubmit()" id="a_button">
+ </form>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if4.html b/dom/html/test/file_iframe_sandbox_c_if4.html
new file mode 100644
index 000000000..53bf49559
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_c_if4.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.ok_wrapper(result, desc);
+ }
+
+ function doStuff() {
+ // try to open a new window via target="_blank", target="BC341604", window.open(), and showModalDialog()
+ // the window we try to open closes itself once it opens
+ sendMouseEvent({type:'click'}, 'target_blank');
+ sendMouseEvent({type:'click'}, 'target_BC341604');
+
+ var threw = false;
+ try {
+ window.open("about:blank");
+ } catch (error) {
+ threw = true;
+ }
+
+ ok(threw, "window.open threw a JS exception and was not allowed");
+
+ threw = false;
+ try {
+ window.showModalDialog("about:blank");
+ } catch(error) {
+ threw = true;
+ }
+
+ ok(threw, "window.showModalDialog threw a JS exception and was not allowed");
+ }
+</script>
+<body onLoad="doStuff()">
+ I am sandboxed but with "allow-scripts allow-same-origin"
+
+ <a href="file_iframe_sandbox_open_window_fail.html" target="_blank" id="target_blank">open window</a>
+ <a href="file_iframe_sandbox_open_window_fail.html" target="BC341604" id="target_BC341604">open window</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if5.html b/dom/html/test/file_iframe_sandbox_c_if5.html
new file mode 100644
index 000000000..267864bd8
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_c_if5.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.ok_wrapper(result, desc);
+ }
+</script>
+<body onLoad="doStuff()">
+ I am sandboxed but with "allow-same-origin"
+
+ <a href = 'javascript:ok(false, "documents sandboxed without allow-scripts should not be able to run script with javascript: URLs");' id='a_link'>click me</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if6.html b/dom/html/test/file_iframe_sandbox_c_if6.html
new file mode 100644
index 000000000..3dab59771
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_c_if6.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.ok_wrapper(result, desc);
+ window.parent.postMessage({ok: result, desc: desc}, "*");
+ }
+
+ function doStuff() {
+ ok(true, "a document sandboxed with allow-same-origin and allow-scripts should be same origin with its parent and able to run scripts " +
+ "regardless of what kind of whitespace was used in its sandbox attribute");
+ }
+</script>
+<body onLoad="doStuff()">
+ I am sandboxed but with "allow-same-origin" and "allow-scripts"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if7.html b/dom/html/test/file_iframe_sandbox_c_if7.html
new file mode 100644
index 000000000..fbd55dbd4
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_c_if7.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.postMessage({ok: result, desc: desc}, "*");
+ }
+
+ function doStuff() {
+ try {
+ var thing = indexedDB.open("sandbox");
+ ok(false, "documents sandboxed without allow-same-origin should NOT be able to access indexedDB");
+ }
+
+ catch(e) {
+ ok(true, "documents sandboxed without allow-same-origin should NOT be able to access indexedDB");
+ }
+ }
+</script>
+<body onLoad='doStuff();'>
+ I am sandboxed but with "allow-scripts"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if8.html b/dom/html/test/file_iframe_sandbox_c_if8.html
new file mode 100644
index 000000000..a03cc77de
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_c_if8.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.postMessage({ok: result, desc: desc}, "*");
+ }
+
+ function doStuff() {
+ var thing = indexedDB.open("sandbox");
+
+ thing.onerror = function(event) {
+ ok(false, "documents sandboxed with allow-same-origin SHOULD be able to access indexedDB");
+ };
+ thing.onsuccess = function(event) {
+ ok(true, "documents sandboxed with allow-same-origin SHOULD be able to access indexedDB");
+ };
+ }
+</script>
+<body onLoad='doStuff();'>
+ I am sandboxed but with "allow-scripts allow-same-origin"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_c_if9.html b/dom/html/test/file_iframe_sandbox_c_if9.html
new file mode 100644
index 000000000..0c88a677c
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_c_if9.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 671389</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ I am
+ <ul>
+ <li>sandboxed but with "allow-forms", "allow-pointer-lock", "allow-popups", "allow-same-origin", "allow-scripts", and "allow-top-navigation", </li>
+ <li>sandboxed but with "allow-same-origin", "allow-scripts", </li>
+ <li>sandboxed, or </li>
+ <li>not sandboxed.</li>
+ </ul>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_close.html b/dom/html/test/file_iframe_sandbox_close.html
new file mode 100644
index 000000000..3b8753497
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_close.html
@@ -0,0 +1,3 @@
+<script>
+ self.close();
+</script>
diff --git a/dom/html/test/file_iframe_sandbox_d_if1.html b/dom/html/test/file_iframe_sandbox_d_if1.html
new file mode 100644
index 000000000..054edbfe1
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if1.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+function doTest() {
+ sendMouseEvent({type:'click'}, 'anchor');
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts'
+
+ <a href="file_iframe_sandbox_navigation_pass.html?Test 1:%20" target="_self" id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if10.html b/dom/html/test/file_iframe_sandbox_d_if10.html
new file mode 100644
index 000000000..8811c8897
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if10.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+function doTest() {
+ window.parent.postMessage({type: "if_10"}, "*");
+}
+</script>
+<body onload='doTest()'>
+ I am sandboxed with 'allow-scripts'
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if11.html b/dom/html/test/file_iframe_sandbox_d_if11.html
new file mode 100644
index 000000000..b6d431c89
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if11.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+function doTest() {
+ // this should fail the first time, but work the second
+ try {
+ window.parent.ok_wrapper(true, "a document that was loaded, navigated to another document, had 'allow-same-origin' added and then was" +
+ " navigated back should be same-origin with its parent");
+ }
+ catch (e) {
+ sendMouseEvent({type:'click'}, 'anchor');
+ }
+}
+
+</script>
+<body onload='doTest()'>
+ I am sandboxed with 'allow-scripts'
+ <a href='file_iframe_sandbox_d_if12.html' id='anchor'>CLICK ME</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if12.html b/dom/html/test/file_iframe_sandbox_d_if12.html
new file mode 100644
index 000000000..0d7936512
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if12.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+function doTest() {
+ window.parent.postMessage({test:'if_11'}, "*");
+}
+</script>
+<body onload='doTest()'>
+ I am sandboxed with 'allow-scripts'
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if13.html b/dom/html/test/file_iframe_sandbox_d_if13.html
new file mode 100644
index 000000000..275490f87
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if13.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+window.addEventListener("message", receiveMessage, false);
+
+function receiveMessage(event) {
+ // this message is part of if_11's test
+ if (event.data.test == 'if_11') {
+ doIf11TestPart2();
+ return;
+ }
+}
+
+function ok_wrapper(result, msg) {
+ window.opener.postMessage({ok: result, desc: msg}, "*");
+ window.close();
+}
+
+function doIf11TestPart2() {
+ var if_11 = document.getElementById('if_11');
+ if_11.sandbox = 'allow-scripts allow-same-origin';
+ // window.history is no longer cross-origin accessible in gecko.
+ SpecialPowers.wrap(if_11).contentWindow.history.back();
+}
+</script>
+<body>
+ <iframe sandbox='allow-scripts' id="if_11" src="file_iframe_sandbox_d_if11.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if14.html b/dom/html/test/file_iframe_sandbox_d_if14.html
new file mode 100644
index 000000000..c670b5ff6
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if14.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 838692</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="text/javascript">
+ var test20Context = "Test 20: Navigate another window (not opened by us): ";
+
+ function doTest() {
+ // Try to navigate auxiliary browsing context (window) not opened by us.
+ // We should not be able to do this as we are sandboxed.
+ sendMouseEvent({type:'click'}, 'navigate_window');
+ window.parent.postMessage({type: "attempted"}, "*");
+
+ // Try to navigate auxiliary browsing context (window) not opened by us, using window.open().
+ // We should not be able to do this as we are sandboxed.
+ try {
+ window.open("file_iframe_sandbox_window_navigation_fail.html?" + escape(test20Context), "window_to_navigate2");
+ window.parent.postMessage({type: "attempted"}, "*");
+ } catch(error) {
+ window.parent.postMessage({ok: true, desc: test20Context + "as expected, error thrown during window.open(..., \"window_to_navigate2\")"}, "*");
+ }
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed but with "allow-scripts allow-same-origin allow-top-navigation".
+
+ <a href="file_iframe_sandbox_window_navigation_fail.html?Test 14: Navigate another window (not opened by us):%20" target="window_to_navigate" id="navigate_window">navigate window</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if15.html b/dom/html/test/file_iframe_sandbox_d_if15.html
new file mode 100644
index 000000000..6c969c8fe
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if15.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<body>
+ I am an unsandboxed iframe.
+
+ <iframe sandbox="allow-same-origin allow-scripts" id="if_16" src="file_iframe_sandbox_d_if16.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if16.html b/dom/html/test/file_iframe_sandbox_d_if16.html
new file mode 100644
index 000000000..aba5d4b96
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if16.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+
+<script type="application/javascript">
+function doTest() {
+ window.parent.parent.postMessage({type: "attempted"}, "*");
+ sendMouseEvent({type:'click'}, 'anchor');
+}
+</script>
+
+<body onload="doTest()">
+ I am sandboxed with 'allow-same-origin allow-scripts'
+
+ <a href="file_iframe_sandbox_navigation_fail.html?Test 16: Navigate parent/ancestor by name:%20" target='if_parent' id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if17.html b/dom/html/test/file_iframe_sandbox_d_if17.html
new file mode 100644
index 000000000..047a08137
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if17.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="application/javascript">
+ var testContext = "Test 17: navigate _self with window.open(): ";
+
+ function doTest() {
+ try {
+ window.open("file_iframe_sandbox_navigation_pass.html?" + escape(testContext), "_self");
+ } catch(error) {
+ window.parent.postMessage({ok: false, desc: testContext + "error thrown during window.open(..., \"_self\")"}, "*");
+ }
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts'
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if18.html b/dom/html/test/file_iframe_sandbox_d_if18.html
new file mode 100644
index 000000000..03aa0aa9b
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if18.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+
+<script type="application/javascript">
+ window.addEventListener("message", receiveMessage, false);
+
+ function receiveMessage(event) {
+ window.parent.postMessage(event.data, "*");
+ }
+
+ var testContext = "Test 18: navigate child with window.open(): ";
+
+ function doTest() {
+ try {
+ window.open("file_iframe_sandbox_navigation_pass.html?" + escape(testContext), "foo");
+ } catch(error) {
+ window.parent.postMessage({ok: false, desc: testContext + " error thrown during window.open(..., \"foo\")"}, "*");
+ }
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts'
+
+ <iframe name="foo" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if19.html b/dom/html/test/file_iframe_sandbox_d_if19.html
new file mode 100644
index 000000000..d766d2649
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if19.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ I am sandboxed with 'allow-scripts'
+
+ <iframe sandbox="allow-scripts" id="if_20" src="file_iframe_sandbox_d_if20.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if2.html b/dom/html/test/file_iframe_sandbox_d_if2.html
new file mode 100644
index 000000000..763585c62
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if2.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+// needed to forward the message to the main test page
+window.addEventListener("message", receiveMessage, false);
+
+function receiveMessage(event) {
+ window.parent.postMessage(event.data, "*");
+}
+
+function doTest() {
+ sendMouseEvent({type:'click'}, 'anchor');
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts'
+
+ <iframe name="foo" src="file_iframe_sandbox_navigation_start.html" height="10" width="10"></iframe>
+
+ <a href="file_iframe_sandbox_navigation_pass.html?Test 2:%20" target='foo' id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if20.html b/dom/html/test/file_iframe_sandbox_d_if20.html
new file mode 100644
index 000000000..005c4bc82
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if20.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="application/javascript">
+ var testContext = "Test 19: navigate _parent with window.open(): ";
+
+ function doTest() {
+ try {
+ window.open("file_iframe_sandbox_navigation_fail.html?" + escape(testContext), "_parent");
+ window.parent.parent.postMessage({type: "attempted"}, "*");
+ } catch(error) {
+ window.parent.parent.postMessage({ok: true, desc: testContext + "as expected, error thrown during window.open(..., \"_parent\")"}, "*");
+ }
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts'
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if21.html b/dom/html/test/file_iframe_sandbox_d_if21.html
new file mode 100644
index 000000000..6d0ab232e
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if21.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<body>
+ I am an unsandboxed iframe.
+
+ <iframe sandbox="allow-same-origin allow-scripts" id="if_22" src="file_iframe_sandbox_d_if22.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if22.html b/dom/html/test/file_iframe_sandbox_d_if22.html
new file mode 100644
index 000000000..bd2715792
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if22.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="application/javascript">
+ var testContext = "Test 21: navigate parent by name with window.open(): ";
+
+ function doTest() {
+ try {
+ window.open("file_iframe_sandbox_navigation_fail.html?" + escape(testContext), "if_parent2");
+ window.parent.parent.postMessage({type: "attempted"}, "*");
+ } catch(error) {
+ window.parent.parent.postMessage({ok: true, desc: testContext + "as expected, error thrown during window.open(..., \"if_parent2\")"}, "*");
+ }
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed with 'allow-same-origin allow-scripts'
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if23.html b/dom/html/test/file_iframe_sandbox_d_if23.html
new file mode 100644
index 000000000..04688b3d9
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if23.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="application/javascript">
+ var test27Context = "Test 27: navigate opened window by name with anchor: ";
+ var test28Context = "Test 28: navigate opened window by name with window.open(): ";
+
+ var windowsToClose = new Array();
+
+ function closeWindows() {
+ for (var i = 0; i < windowsToClose.length; i++) {
+ windowsToClose[i].close();
+ }
+ }
+
+ // Add message listener to forward messages on to parent
+ window.addEventListener("message", receiveMessage, false);
+
+ function receiveMessage(event) {
+ switch (event.data.type) {
+ case "closeWindows":
+ closeWindows();
+ break;
+ default:
+ window.parent.postMessage(event.data, "*");
+ }
+ }
+
+ function doTest() {
+ try {
+ windowsToClose.push(window.open("about:blank", "test27window"));
+ var test27Anchor = document.getElementById("test27Anchor");
+ test27Anchor.href = "file_iframe_sandbox_window_navigation_pass.html?" + escape(test27Context);
+ sendMouseEvent({type:"click"}, "test27Anchor");
+ window.parent.postMessage({type: "attempted"}, "*");
+ } catch(error) {
+ window.parent.postMessage({ok: false, desc: test27Context + "error thrown during window.open(): " + error}, "*");
+ }
+
+ try {
+ windowsToClose.push(window.open("about:blank", "test28window"));
+ window.open("file_iframe_sandbox_window_navigation_pass.html?" + escape(test28Context), "test28window");
+ window.parent.postMessage({type: "attempted"}, "*");
+ } catch(error) {
+ window.parent.postMessage({ok: false, desc: test28Context + "error thrown during window.open(): " + error}, "*");
+ }
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts allow-popups'
+
+ <a id="test27Anchor" target="test27window">Test 27 anchor</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if3.html b/dom/html/test/file_iframe_sandbox_d_if3.html
new file mode 100644
index 000000000..cd2d53bce
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if3.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ I am sandboxed with 'allow-scripts'
+
+ <iframe sandbox="allow-scripts" id="if_4" src="file_iframe_sandbox_d_if4.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if4.html b/dom/html/test/file_iframe_sandbox_d_if4.html
new file mode 100644
index 000000000..64e173a64
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if4.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+function doTest() {
+ window.parent.parent.postMessage({type: "attempted"}, "*");
+ sendMouseEvent({type:'click'}, 'anchor');
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts'
+
+ <a href="file_iframe_sandbox_navigation_fail.html" target='_parent' id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if5.html b/dom/html/test/file_iframe_sandbox_d_if5.html
new file mode 100644
index 000000000..ba31053ad
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if5.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+function doTest() {
+ window.parent.postMessage({type: "attempted"}, "*");
+ sendMouseEvent({type:'click'}, 'anchor');
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts allow-same-origin'
+
+ <a href="file_iframe_sandbox_navigation_fail.html?Test 4: Navigate sibling iframe by name:%20" target='if_sibling' id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if6.html b/dom/html/test/file_iframe_sandbox_d_if6.html
new file mode 100644
index 000000000..e7e19fc2e
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if6.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+function doTest() {
+ sendMouseEvent({type:'click'}, 'anchor');
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts'
+
+ <a href="file_iframe_sandbox_d_if7.html" target='_self' id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if7.html b/dom/html/test/file_iframe_sandbox_d_if7.html
new file mode 100644
index 000000000..5023ee029
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if7.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+function doTest() {
+ try {
+ window.parent.ok_wrapper(false, "a sandboxed document when navigated should still NOT be same-origin with its parent");
+ } catch(error) {
+ window.parent.postMessage({ok: true, desc: "sandboxed document's attempt to access parent after navigation blocked, as not same-origin."}, "*");
+ }
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts'
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if8.html b/dom/html/test/file_iframe_sandbox_d_if8.html
new file mode 100644
index 000000000..2b4398ef0
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if8.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="application/javascript">
+ function doTest() {
+ window.parent.modify_if_8();
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts' and 'allow-same-origin' the first time I am loaded, and with 'allow-scripts' the second time
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_d_if9.html b/dom/html/test/file_iframe_sandbox_d_if9.html
new file mode 100644
index 000000000..ee641904f
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_d_if9.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+function doTest() {
+ window.parent.modify_if_9();
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts' and 'allow-same-origin' the first time I am loaded, and with 'allow-same-origin' the second time
+</body>
+</html>
+
diff --git a/dom/html/test/file_iframe_sandbox_e_if1.html b/dom/html/test/file_iframe_sandbox_e_if1.html
new file mode 100644
index 000000000..69f827ce4
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if1.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+
+<script>
+ function doTest() {
+ var testContext = location.search == "" ? "?Test 10: Navigate _top:%20" : location.search;
+ document.getElementById("if_6").src = "file_iframe_sandbox_e_if6.html" + testContext;
+ }
+</script>
+
+<body onload="doTest()">
+ <iframe sandbox='allow-scripts' id='if_6' height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if10.html b/dom/html/test/file_iframe_sandbox_e_if10.html
new file mode 100644
index 000000000..2484b8f34
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if10.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ function doTest() {
+ var testContext = "?Test 23: Nested navigate _top with window.open():%20";
+ document.getElementById("if_9").src = "file_iframe_sandbox_e_if9.html" + testContext;
+ }
+</script>
+
+<body onload="doTest()">
+ <iframe sandbox='allow-scripts allow-top-navigation' id='if_9' height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if11.html b/dom/html/test/file_iframe_sandbox_e_if11.html
new file mode 100644
index 000000000..42c28021a
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if11.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script>
+ function doTest() {
+ var testContext = location.search.substring(1);
+ try {
+ var topsOpener = window.top.opener;
+ window.open("file_iframe_sandbox_top_navigation_pass.html?" + testContext, "_top");
+ topsOpener.postMessage({ok: true, desc: unescape(testContext) + "top navigation should be allowed by a document sandboxed with 'allow-top-navigation.'"}, "*");
+ } catch(error) {
+ window.top.opener.postMessage({ok: false, desc: unescape(testContext) + "error thrown during window.open(..., \"_top\")"}, "*");
+ window.top.close();
+ }
+ }
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts and allow-top-navigation'
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if12.html b/dom/html/test/file_iframe_sandbox_e_if12.html
new file mode 100644
index 000000000..0b1b87e09
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if12.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ function doTest() {
+ var testContext = location.search == "" ? "?Test 24: Navigate _top with window.open():%20" : location.search;
+ document.getElementById("if_14").src = "file_iframe_sandbox_e_if14.html" + testContext;
+ }
+</script>
+
+<body onload="doTest()">
+ <iframe sandbox='allow-scripts' id='if_14' height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if13.html b/dom/html/test/file_iframe_sandbox_e_if13.html
new file mode 100644
index 000000000..f5cf912f6
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if13.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ function doTest() {
+ var testContext = "?Test 25: Nested navigate _top with window.open():%20";
+ document.getElementById("if_12").src = "file_iframe_sandbox_e_if12.html" + testContext;
+ }
+</script>
+
+<body onload="doTest()">
+ <iframe sandbox='allow-scripts allow-top-navigation' id='if_12' height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if14.html b/dom/html/test/file_iframe_sandbox_e_if14.html
new file mode 100644
index 000000000..76d978702
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if14.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script>
+ function doTest() {
+ var testContext = location.search.substring(1);
+ try {
+ var topsOpener = window.top.opener;
+ window.open("file_iframe_sandbox_top_navigation_fail.html?" + testContext, "_top");
+ topsOpener.postMessage({ok: false, desc: unescape(testContext) + "top navigation should NOT be allowed by a document sandboxed without 'allow-top-navigation.'"}, "*");
+ } catch(error) {
+ window.top.opener.postMessage({ok: true, desc: unescape(testContext) + "as expected error thrown during window.open(..., \"_top\")"}, "*");
+ window.top.close();
+ }
+ }
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts'
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if15.html b/dom/html/test/file_iframe_sandbox_e_if15.html
new file mode 100644
index 000000000..bf4138e1d
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if15.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ // Set our name, to allow an attempt to navigate us by name.
+ window.name = "e_if15";
+</script>
+
+<body>
+ <iframe sandbox='allow-scripts' id='if_16' src="file_iframe_sandbox_e_if16.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if16.html b/dom/html/test/file_iframe_sandbox_e_if16.html
new file mode 100644
index 000000000..06c8bf871
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if16.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ var testContext = "Test 26: navigate top by name with window.open(): ";
+
+ function doTest() {
+ try {
+ var topsOpener = window.top.opener;
+ window.open("file_iframe_sandbox_top_navigation_fail.html?" + escape(testContext), "e_if15");
+ topsOpener.postMessage({ok: false, desc: unescape(testContext) + "top navigation should NOT be allowed by a document sandboxed without 'allow-top-navigation.'"}, "*");
+ } catch(error) {
+ window.top.opener.postMessage({ok: true, desc: testContext + "as expected, error thrown during window.open(..., \"e_if15\")"}, "*");
+ window.top.close();
+ }
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed but with "allow-scripts"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if2.html b/dom/html/test/file_iframe_sandbox_e_if2.html
new file mode 100644
index 000000000..47251d6dc
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if2.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+ <iframe sandbox='allow-scripts allow-top-navigation allow-same-origin' id='if_1' src="file_iframe_sandbox_e_if1.html?Test 11: Nested navigate _top:%20" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if3.html b/dom/html/test/file_iframe_sandbox_e_if3.html
new file mode 100644
index 000000000..ce010e689
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if3.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <iframe sandbox='allow-scripts allow-top-navigation' id='if_5' src="file_iframe_sandbox_e_if5.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if4.html b/dom/html/test/file_iframe_sandbox_e_if4.html
new file mode 100644
index 000000000..740a33a94
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if4.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <iframe sandbox='allow-scripts allow-top-navigation' id='if_3' src="file_iframe_sandbox_e_if3.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if5.html b/dom/html/test/file_iframe_sandbox_e_if5.html
new file mode 100644
index 000000000..46bfff357
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if5.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+function doTest() {
+ sendMouseEvent({type:'click'}, 'anchor');
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts and allow-top-navigation'
+
+ <a href="file_iframe_sandbox_top_navigation_pass.html" target='_top' id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if6.html b/dom/html/test/file_iframe_sandbox_e_if6.html
new file mode 100644
index 000000000..b1266416c
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if6.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+function doTest() {
+ document.getElementById('anchor').href = "file_iframe_sandbox_top_navigation_fail.html" + location.search;
+ window.top.opener.postMessage({type: "attempted"}, "*");
+ sendMouseEvent({type:'click'}, 'anchor');
+}
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts'
+
+ <a target='_top' id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if7.html b/dom/html/test/file_iframe_sandbox_e_if7.html
new file mode 100644
index 000000000..9d60ed2db
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if7.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ // Set our name, to allow an attempt to navigate us by name.
+ window.name = "e_if7";
+</script>
+
+<body>
+ <iframe sandbox='allow-scripts' id='if_8' src="file_iframe_sandbox_e_if8.html" height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if8.html b/dom/html/test/file_iframe_sandbox_e_if8.html
new file mode 100644
index 000000000..324ccf90c
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if8.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+
+<script>
+ function doTest() {
+ // Try to navigate top using its name (e_if7). We should not be able to do this as allow-top-navigation is not specified.
+ window.top.opener.postMessage({type: "attempted"}, "*");
+ sendMouseEvent({type:'click'}, 'navigate_top');
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed but with "allow-scripts"
+
+ <a href="file_iframe_sandbox_top_navigation_fail.html?Test 15: Navigate top by name:%20" target="e_if7" id="navigate_top">navigate top</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_e_if9.html b/dom/html/test/file_iframe_sandbox_e_if9.html
new file mode 100644
index 000000000..f18a16dba
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_e_if9.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ function doTest() {
+ var testContext = location.search == "" ? "?Test 22: Navigate _top with window.open():%20" : location.search;
+ document.getElementById("if_11").src = "file_iframe_sandbox_e_if11.html" + testContext;
+ }
+</script>
+
+<body onload="doTest()">
+ <iframe sandbox='allow-scripts allow-top-navigation' id='if_11' height="10" width="10"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_f_if1.html b/dom/html/test/file_iframe_sandbox_f_if1.html
new file mode 100644
index 000000000..294bf0797
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_f_if1.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+I have 2 plugin instances embedded in me.
+<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
+<object type="application/x-test" width="200" height="200"></object>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_f_if2.html b/dom/html/test/file_iframe_sandbox_f_if2.html
new file mode 100644
index 000000000..7b3010d53
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_f_if2.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ I am a document that should be handled by a plugin load.
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_f_if2.html^headers^ b/dom/html/test/file_iframe_sandbox_f_if2.html^headers^
new file mode 100644
index 000000000..9af65b111
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_f_if2.html^headers^
@@ -0,0 +1 @@
+Content-Type: application/x-test
diff --git a/dom/html/test/file_iframe_sandbox_fail.js b/dom/html/test/file_iframe_sandbox_fail.js
new file mode 100644
index 000000000..63397c7de
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_fail.js
@@ -0,0 +1 @@
+ok(false, "documents sandboxed with allow-scripts should NOT be able to run <script src=...>"); \ No newline at end of file
diff --git a/dom/html/test/file_iframe_sandbox_form_fail.html b/dom/html/test/file_iframe_sandbox_form_fail.html
new file mode 100644
index 000000000..6254f87c7
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_form_fail.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<body onLoad="doStuff()">
+ I should NOT be loaded by a form submit from a sandbox without 'allow-forms'
+</body>
+</html>
+
+<script>
+ function doStuff() {
+ window.parent.postMessage({ok: false, desc: "documents sandboxed without allow-forms should NOT be able to submit forms"}, "*");
+ }
+</script> \ No newline at end of file
diff --git a/dom/html/test/file_iframe_sandbox_form_pass.html b/dom/html/test/file_iframe_sandbox_form_pass.html
new file mode 100644
index 000000000..1ba8853fa
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_form_pass.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+</head>
+
+<body onLoad="doStuff()">
+ I should be loaded by a form submit from a sandbox with 'allow-forms'
+</body>
+</html>
+
+<script>
+ function doStuff() {
+ window.parent.postMessage({ok: true, desc: "documents sandboxed with allow-forms should be able to submit forms"}, "*");
+ }
+</script> \ No newline at end of file
diff --git a/dom/html/test/file_iframe_sandbox_g_if1.html b/dom/html/test/file_iframe_sandbox_g_if1.html
new file mode 100644
index 000000000..9a985faf9
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_g_if1.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.postMessage({ok: result, desc: desc}, "*");
+ }
+
+ function doStuff() {
+ // test data URI
+
+ // self.onmessage = function(event) {
+ // self.postMessage('make it so');
+ // };
+ var data_url = "data:text/plain;charset=utf-8;base64,c2VsZi5vbm1lc3NhZ2UgPSBmdW5jdGlvbihldmVudCkgeyAgDQogICAgc2VsZi5wb3N0TWVzc2FnZSgnbWFrZSBpdCBzbycpOyAgDQp9Ow==";
+ var worker_data = new Worker(data_url);
+ worker_data.addEventListener('message', function(event) {
+ ok(true, "a worker in a sandboxed document should be able to be loaded from a data: URI");
+ }, false);
+
+ worker_data.postMessage("engage!");
+
+ // test a blob URI we created (will have the same null principal
+ // as us
+ var b = new Blob(["onmessage = function(event) { self.postMessage('make it so');};"]);
+
+ var blobURL = URL.createObjectURL(b);
+
+ var worker_blob = new Worker(blobURL);
+
+ worker_blob.addEventListener('message', function(event) {
+ ok(true, "a worker in a sandboxed document should be able to be loaded from a blob URI " +
+ "created by that sandboxed document");
+ }, false);
+
+ worker_blob.postMessage("engage!");
+
+ // test loading with relative url - this should fail since we are
+ // sandboxed and have a null principal
+ var worker_js = new Worker('file_iframe_sandbox_worker.js');
+ worker_js.onerror = function(error) {
+ ok(true, "a worker in a sandboxed document should tell the load error via error event");
+ }
+
+ worker_js.addEventListener('message', function(event) {
+ ok(false, "a worker in a sandboxed document should not be able to load from a relative URI");
+ }, false);
+
+ worker_js.postMessage('engage');
+ }
+</script>
+<body onload='doStuff();'>
+ I am sandboxed but with "allow-scripts"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_h_if1.html b/dom/html/test/file_iframe_sandbox_h_if1.html
new file mode 100644
index 000000000..3cb6781f1
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_h_if1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 766282</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.ok_wrapper(result, desc);
+ }
+
+ function doStuff() {
+ // Try to open a new window via target="_blank", target="BC766282" and window.open().
+ // The window we try to open closes itself once it opens.
+ sendMouseEvent({type:'click'}, 'target_blank');
+ sendMouseEvent({type:'click'}, 'target_BC766282');
+
+ try {
+ window.open("file_iframe_sandbox_open_window_pass.html");
+ } catch(e) {
+ ok(false, "Test 3: iframes sandboxed with allow-popups, should be able to open windows");
+ }
+ }
+</script>
+<body onLoad="doStuff()">
+ I am sandboxed but with "allow-popups allow-scripts allow-same-origin"
+
+ <a href="file_iframe_sandbox_open_window_pass.html" target="_blank" id="target_blank">open window</a>
+ <a href="file_iframe_sandbox_open_window_pass.html?BC766282" target="BC766282" id="target_BC766282">open window</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_j_if1.html b/dom/html/test/file_iframe_sandbox_j_if1.html
new file mode 100644
index 000000000..6d4347dfc
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_j_if1.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="text/javascript">
+ function doStuff() {
+ // Open a new window via showModalDialog().
+ try {
+ window.showModalDialog("file_iframe_sandbox_k_if5.html");
+ } catch(e) {
+ window.parent.ok_wrapper(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog");
+ }
+
+ // Open a new window via showModalDialog().
+ try {
+ window.showModalDialog("file_iframe_sandbox_k_if7.html");
+ } catch(e) {
+ window.parent.ok_wrapper(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog");
+ }
+ }
+</script>
+
+<body onLoad="doStuff()">
+ I am sandboxed with "allow-scripts allow-popups allow-same-origin allow-forms allow-top-navigation".
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_j_if2.html b/dom/html/test/file_iframe_sandbox_j_if2.html
new file mode 100644
index 000000000..9552307ee
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_j_if2.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="text/javascript">
+ function doSubOpens() {
+ // Open a new window showModalDialog().
+ try {
+ window.showModalDialog("file_iframe_sandbox_k_if9.html");
+ } catch(e) {
+ window.parent.ok_wrapper(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog");
+ }
+ }
+
+ window.doSubOpens = doSubOpens;
+</script>
+
+<body>
+ I am sandboxed but with "allow-scripts allow-popups allow-same-origin".
+ After my initial load, "allow-same-origin" is removed and then I open file_iframe_sandbox_k_if9.html,
+ which attemps to call a function in my parent.
+ This should succeed since the new sandbox flags shouldn't have taken affect on me until I'm reloaded.
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_j_if3.html b/dom/html/test/file_iframe_sandbox_j_if3.html
new file mode 100644
index 000000000..07c5b66c1
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_j_if3.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+</head>
+<script type="text/javascript">
+ function ok(result, desc) {
+ window.parent.ok_wrapper(result, desc);
+ }
+
+ function doStuff() {
+ // Try to open a new window via showModalDialog().
+ // The window we try to open closes itself once it opens.
+ try {
+ window.showModalDialog("file_iframe_sandbox_open_window_pass.html");
+ } catch(e) {
+ ok(false, "iframes sandboxed with allow-popups and allow-modals should be able to open a modal dialog");
+ }
+ }
+</script>
+<body onLoad="doStuff()">
+ I am sandboxed but with "allow-popups allow-scripts allow-same-origin"
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_k_if1.html b/dom/html/test/file_iframe_sandbox_k_if1.html
new file mode 100644
index 000000000..cb0719556
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_k_if1.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="text/javascript">
+ var windowsToClose = new Array();
+
+ function closeWindows() {
+ for (var i = 0; i < windowsToClose.length; i++) {
+ windowsToClose[i].close();
+ }
+ window.open("file_iframe_sandbox_close.html", "blank_if2");
+ window.open("file_iframe_sandbox_close.html", "BC766282_if2");
+ }
+
+ // Add message listener to forward messages on to parent
+ window.addEventListener("message", receiveMessage, false);
+
+ function receiveMessage(event) {
+ switch (event.data.type) {
+ case "closeWindows":
+ closeWindows();
+ break;
+ }
+ }
+
+ function doStuff() {
+ // Open a new window via target="_blank", target="BC766282_if2" and window.open().
+ sendMouseEvent({type:'click'}, 'target_blank_if2');
+ sendMouseEvent({type:'click'}, 'target_BC766282_if2');
+
+ windowsToClose.push(window.open("file_iframe_sandbox_k_if2.html"));
+ }
+</script>
+<body onLoad="doStuff()">
+ I am navigated to from file_iframe_sandbox_k_if8.html.
+ This was opened in an iframe with "allow-scripts allow-popups allow-same-origin".
+ However allow-same-origin was removed from the iframe before navigating to me,
+ so I should only have "allow-scripts allow-popups" in force.
+ <a href="file_iframe_sandbox_k_if2.html" target="_blank" id="target_blank_if2">open window</a>
+ <a href="file_iframe_sandbox_k_if2.html" target="BC766282_if2" id="target_BC766282_if2">open window</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_k_if2.html b/dom/html/test/file_iframe_sandbox_k_if2.html
new file mode 100644
index 000000000..dce42aef5
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_k_if2.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="text/javascript">
+ if (window.name == "") {
+ window.name = "blank_if2";
+ }
+
+ function ok(result, message) {
+ window.opener.parent.postMessage({type: "ok", ok: result, desc: message}, "*");
+ }
+
+ function doStuff() {
+ // Check that sandboxed forms browsing context flag copied by attempting to submit a form.
+ document.getElementById('a_form').submit();
+ window.opener.parent.postMessage({type: "attempted"}, "*");
+
+ // Check that sandboxed origin browsing context flag copied by attempting to access cookies.
+ try {
+ var foo = document.cookie;
+ ok(false, "Sandboxed origin browsing context flag NOT copied to new auxiliary browsing context.");
+ } catch(error) {
+ ok(true, "Sandboxed origin browsing context flag copied to new auxiliary browsing context.");
+ }
+
+ // Check that sandboxed top-level navigation browsing context flag copied.
+ // if_3 tries to navigate this document.
+ var if_3 = document.getElementById('if_3');
+ if_3.src = "file_iframe_sandbox_k_if3.html";
+ }
+</script>
+
+<body onLoad="doStuff()">
+ I am not sandboxed directly, but opened from a sandboxed document with 'allow-scripts allow-popups'
+
+ <form method="get" action="file_iframe_sandbox_window_form_fail.html" id="a_form">
+ First name: <input type="text" name="firstname">
+ Last name: <input type="text" name="lastname">
+ <input type="submit" id="a_button">
+ </form>
+
+ <iframe id="if_3" src="about:blank" height="10" width="10"></iframe>
+
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_k_if3.html b/dom/html/test/file_iframe_sandbox_k_if3.html
new file mode 100644
index 000000000..b6a005aa5
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_k_if3.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+<script type="application/javascript">
+ function doTest() {
+ sendMouseEvent({type:'click'}, 'anchor');
+ window.parent.opener.parent.postMessage({type: "attempted"}, "*");
+ }
+</script>
+<body onload="doTest()">
+ I am sandboxed with 'allow-scripts allow-popups'
+
+ <a href="file_iframe_sandbox_window_top_navigation_fail.html" target='_top' id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_k_if4.html b/dom/html/test/file_iframe_sandbox_k_if4.html
new file mode 100644
index 000000000..b9b4427ed
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_k_if4.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="text/javascript">
+ function doStuff() {
+ // Open a new window via target="_blank", target="BC766282_if5" and window.open().
+ sendMouseEvent({type:'click'}, 'target_blank_if5');
+ sendMouseEvent({type:'click'}, 'target_BC766282_if5');
+
+ window.open("file_iframe_sandbox_k_if5.html");
+
+ // Open a new window via target="_blank", target="BC766282_if7" and window.open().
+ sendMouseEvent({type:'click'}, 'target_blank_if7');
+ sendMouseEvent({type:'click'}, 'target_BC766282_if7');
+
+ window.open("file_iframe_sandbox_k_if7.html");
+ }
+</script>
+
+<body onLoad="doStuff()">
+ I am sandboxed with "allow-scripts allow-popups allow-same-origin allow-forms allow-top-navigation".
+ <a href="file_iframe_sandbox_k_if5.html" target="_blank" id="target_blank_if5">open window</a>
+ <a href="file_iframe_sandbox_k_if5.html" target="BC766282_if5" id="target_BC766282_if5">open window</a>
+
+ <a href="file_iframe_sandbox_k_if7.html" target="_blank" id="target_blank_if7">open window</a>
+ <a href="file_iframe_sandbox_k_if7.html" target="BC766282_if7" id="target_BC766282_if7">open window</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_k_if5.html b/dom/html/test/file_iframe_sandbox_k_if5.html
new file mode 100644
index 000000000..8deb65852
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_k_if5.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="text/javascript">
+ function doStuff() {
+ // Check that sandboxed origin browsing context flag NOT set by attempting to access cookies.
+ try {
+ var foo = document.cookie;
+ window.opener.parent.ok_wrapper(true, "Sandboxed origin browsing context flag NOT set on new auxiliary browsing context.");
+ } catch(error) {
+ window.opener.parent.ok_wrapper(false, "Sandboxed origin browsing context flag set on new auxiliary browsing context.");
+ }
+
+ // Check that sandboxed top-level navigation browsing context flag NOT set.
+ // if_6 tries to navigate this document.
+ var if_6 = document.getElementById('if_6');
+ if_6.src = "file_iframe_sandbox_k_if6.html";
+ }
+</script>
+
+<body onLoad="doStuff()">
+ I am not sandboxed directly, but opened from a sandboxed document with at least
+ 'allow-scripts allow-popups allow-same-origin allow-top-navigation'
+
+ <iframe id="if_6" src="about:blank" height="10" width="10"></iframe>
+
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_k_if6.html b/dom/html/test/file_iframe_sandbox_k_if6.html
new file mode 100644
index 000000000..22dec5c1c
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_k_if6.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+</head>
+
+<script type="application/javascript">
+ function doTest() {
+ sendMouseEvent({type:'click'}, 'anchor');
+ }
+</script>
+
+<body onload="doTest()">
+ I am sandboxed with at least 'allow-scripts allow-popups allow-top-navigation'
+
+ <a href="file_iframe_sandbox_window_top_navigation_pass.html" target='_top' id='anchor'>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_k_if7.html b/dom/html/test/file_iframe_sandbox_k_if7.html
new file mode 100644
index 000000000..269e31eb5
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_k_if7.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="text/javascript">
+ function doStuff() {
+ // Check that sandboxed forms browsing context flag NOT set by attempting to submit a form.
+ document.getElementById('a_form').submit();
+ }
+</script>
+
+<body onLoad="doStuff()">
+ I am not sandboxed directly, but opened from a sandboxed document with at least
+ 'allow-scripts allow-popups allow-forms allow-same-origin'
+
+ <form method="get" action="file_iframe_sandbox_window_form_pass.html" id="a_form">
+ First name: <input type="text" name="firstname">
+ Last name: <input type="text" name="lastname">
+ <input type="submit" id="a_button">
+ </form>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_k_if8.html b/dom/html/test/file_iframe_sandbox_k_if8.html
new file mode 100644
index 000000000..6f425c428
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_k_if8.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="text/javascript">
+ function doSubOpens() {
+ // Open a new window via target="_blank", target="BC766282_if9" and window.open().
+ sendMouseEvent({type:'click'}, 'target_blank_if9');
+ sendMouseEvent({type:'click'}, 'target_BC766282_if9');
+
+ window.open("file_iframe_sandbox_k_if9.html");
+
+ sendMouseEvent({type:'click'}, 'target_if1');
+ }
+
+ window.doSubOpens = doSubOpens;
+</script>
+
+<body>
+ I am sandboxed but with "allow-scripts allow-popups allow-same-origin".
+ After my initial load, "allow-same-origin" is removed and then I open file_iframe_sandbox_k_if9.html
+ in 3 different ways, which attemps to call a function in my parent.
+ This should succeed since the new sandbox flags shouldn't have taken affect on me until I'm reloaded.
+ <a href="file_iframe_sandbox_k_if9.html" target="_blank" id="target_blank_if9">open window</a>
+ <a href="file_iframe_sandbox_k_if9.html" target="BC766282_if9" id="target_BC766282_if9">open window</a>
+
+ Now navigate to file_iframe_sandbox_k_if1.html to do tests for a sandbox opening a window
+ when only "allow-scripts allow-popups" are specified.
+ <a href="file_iframe_sandbox_k_if1.html" id="target_if1">navigate to if1</a>
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_k_if9.html b/dom/html/test/file_iframe_sandbox_k_if9.html
new file mode 100644
index 000000000..56e8db3f9
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_k_if9.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ function doStuff() {
+ window.opener.parent.ok_wrapper(true, "A window opened from within a sandboxed document should inherit the flags of the document, not of the docshell/sandbox attribute.");
+ self.close();
+ }
+</script>
+
+<body onload='doStuff()'>
+ I'm a window opened from the sandboxed document of file_iframe_sandbox_k_if8.html.
+ I should be able to call ok_wrapper in main test page directly because I should be same-origin with it.
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_navigation_fail.html b/dom/html/test/file_iframe_sandbox_navigation_fail.html
new file mode 100644
index 000000000..bae5276bd
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_navigation_fail.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onLoad="doStuff()">
+FAIL
+</body>
+<script>
+ function doStuff() {
+ var testContext = unescape(location.search.substring(1));
+ window.parent.postMessage({ok: false, desc: testContext + "this navigation should NOT be allowed by a sandboxed document", addToAttempted: false}, "*");
+ }
+</script>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_navigation_pass.html b/dom/html/test/file_iframe_sandbox_navigation_pass.html
new file mode 100644
index 000000000..e07248247
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_navigation_pass.html
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script>
+function doStuff() {
+ var testContext = unescape(location.search.substring(1));
+ window.parent.postMessage({ok: true, desc: testContext + "this navigation should be allowed by a sandboxed document"}, "*");
+}
+</script>
+<body onLoad="doStuff()">
+PASS
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_navigation_start.html b/dom/html/test/file_iframe_sandbox_navigation_start.html
new file mode 100644
index 000000000..fa5642517
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_navigation_start.html
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+I am just a normal HTML document, probably contained in a sandboxed iframe
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_open_window_fail.html b/dom/html/test/file_iframe_sandbox_open_window_fail.html
new file mode 100644
index 000000000..64e0d3618
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_open_window_fail.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<body onLoad="doStuff()">
+ I should NOT be opened by a sandboxed iframe via any method
+</body>
+</html>
+
+<script>
+ function doStuff() {
+ window.opener.ok(false, "sandboxed documents should NOT be able to open windows");
+ self.close();
+ }
+</script>
diff --git a/dom/html/test/file_iframe_sandbox_open_window_pass.html b/dom/html/test/file_iframe_sandbox_open_window_pass.html
new file mode 100644
index 000000000..ac45c7fd3
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_open_window_pass.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<body onLoad="doStuff()">
+ I should be opened by a sandboxed iframe via any method when "allow-popups" is specified.
+</body>
+</html>
+
+<script>
+ function doStuff() {
+ // Check that the browsing context's (window's) name is as expected.
+ var expectedName = location.search.substring(1);
+ if (expectedName == window.name) {
+ window.opener.ok(true, "sandboxed documents should be able to open windows when \"allow-popups\" is specified");
+ } else {
+ window.opener.ok(false, "window opened with \"allow-popups\", but expected name was " + expectedName + " and actual was " + window.name);
+ }
+ self.close();
+ }
+</script>
diff --git a/dom/html/test/file_iframe_sandbox_pass.js b/dom/html/test/file_iframe_sandbox_pass.js
new file mode 100644
index 000000000..bd633056f
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_pass.js
@@ -0,0 +1 @@
+ok(true, "documents sandboxed with allow-scripts should be able to run <script src=...>"); \ No newline at end of file
diff --git a/dom/html/test/file_iframe_sandbox_redirect.html b/dom/html/test/file_iframe_sandbox_redirect.html
new file mode 100644
index 000000000..62419d7f4
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_redirect.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<body>redirect</body>
diff --git a/dom/html/test/file_iframe_sandbox_redirect.html^headers^ b/dom/html/test/file_iframe_sandbox_redirect.html^headers^
new file mode 100644
index 000000000..71b739c42
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_redirect.html^headers^
@@ -0,0 +1,2 @@
+HTTP 301 Moved Permanently
+Location: file_iframe_sandbox_redirect_target.html
diff --git a/dom/html/test/file_iframe_sandbox_redirect_target.html b/dom/html/test/file_iframe_sandbox_redirect_target.html
new file mode 100644
index 000000000..c134ac0ff
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_redirect_target.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+ <script>
+ onmessage = function(event) {
+ parent.postMessage(event.data + " redirect target", "*");
+ }
+ </script>
+</head>
+<body>I have been redirected</body>
diff --git a/dom/html/test/file_iframe_sandbox_refresh.html b/dom/html/test/file_iframe_sandbox_refresh.html
new file mode 100644
index 000000000..1fad80c42
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_refresh.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<body>refresh</body>
diff --git a/dom/html/test/file_iframe_sandbox_refresh.html^headers^ b/dom/html/test/file_iframe_sandbox_refresh.html^headers^
new file mode 100644
index 000000000..a7cc383b4
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_refresh.html^headers^
@@ -0,0 +1 @@
+Refresh: 0 url=data:text/html,Refreshed
diff --git a/dom/html/test/file_iframe_sandbox_top_navigation_fail.html b/dom/html/test/file_iframe_sandbox_top_navigation_fail.html
new file mode 100644
index 000000000..dad6b2c00
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_top_navigation_fail.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script>
+function doStuff() {
+ var testContext = unescape(location.search.substring(1));
+ window.opener.postMessage({ok: false, desc: testContext + "top navigation should NOT be allowed by a document sandboxed without 'allow-top-navigation'", addToAttempted: false}, "*");
+ window.close();
+}
+</script>
+<body onLoad="doStuff()">
+FAIL\
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_top_navigation_pass.html b/dom/html/test/file_iframe_sandbox_top_navigation_pass.html
new file mode 100644
index 000000000..fe016ab23
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_top_navigation_pass.html
@@ -0,0 +1,18 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script>
+function doStuff() {
+ var testContext = unescape(location.search.substring(1));
+ window.opener.postMessage({ok: true, desc: testContext + "top navigation should be allowed by a document sandboxed with 'allow-top-navigation'"}, "*");
+ window.close();
+}
+</script>
+<body onLoad="doStuff()">
+PASS
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_window_form_fail.html b/dom/html/test/file_iframe_sandbox_window_form_fail.html
new file mode 100644
index 000000000..2d678b3ac
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_window_form_fail.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<body onLoad="doStuff()">
+ I should NOT be loaded by a form submit from a window opened from a sandbox without 'allow-forms'.
+</body>
+</html>
+
+<script>
+ function doStuff() {
+ window.opener.parent.postMessage({ok: false, desc: "documents sandboxed without allow-forms should NOT be able to submit forms"}, "*");
+
+ self.close();
+ }
+</script>
diff --git a/dom/html/test/file_iframe_sandbox_window_form_pass.html b/dom/html/test/file_iframe_sandbox_window_form_pass.html
new file mode 100644
index 000000000..dd2656c1e
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_window_form_pass.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ function doStuff() {
+ window.opener.parent.ok_wrapper(true, "Sandboxed forms browsing context flag NOT set on new auxiliary browsing context.");
+
+ self.close();
+ }
+</script>
+
+<body onLoad="doStuff()">
+ I should be loaded by a form submit from a window opened from a sandbox with 'allow-forms allow-same-origin'.
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_window_navigation_fail.html b/dom/html/test/file_iframe_sandbox_window_navigation_fail.html
new file mode 100644
index 000000000..f8e3c83ce
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_window_navigation_fail.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 838692</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+function doStuff() {
+ var testContext = unescape(location.search.substring(1));
+ window.opener.postMessage({ok: false, desc: testContext + "a sandboxed document should not be able to navigate a window it hasn't opened.", addToAttempted: false}, "*");
+ window.close();
+}
+</script>
+
+<body onLoad="doStuff()">
+FAIL
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_window_navigation_pass.html b/dom/html/test/file_iframe_sandbox_window_navigation_pass.html
new file mode 100644
index 000000000..a1bff9eb8
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_window_navigation_pass.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+function doStuff() {
+ var testContext = unescape(location.search.substring(1));
+ window.opener.postMessage({type: "ok", ok: true, desc: testContext + "a permitted sandboxed document should be able to navigate a window it has opened.", addToAttempted: false}, "*");
+ window.close();
+}
+</script>
+
+<body onLoad="doStuff()">
+PASS
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html b/dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html
new file mode 100644
index 000000000..af5047604
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_window_top_navigation_fail.html
@@ -0,0 +1,24 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script>
+ function doStuff() {
+ window.opener.parent.postMessage({ok: false, desc: "Sandboxed top-level navigation browsing context flag NOT copied to new auxiliary browsing context."}, "*");
+
+ // Check that when no browsing context returned by "target='_top'", a new browsing context isn't opened by mistake.
+ try {
+ window.opener.parent.opener.parent.postMessage({ok: false, desc: "An attempt at top navigation without 'allow-top-navigation' should not have opened a new browsing context."}, "*");
+ } catch (error) {
+ }
+
+ self.close();
+ }
+</script>
+<body onLoad="doStuff()">
+FAIL
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html b/dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html
new file mode 100644
index 000000000..d3637fb04
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_window_top_navigation_pass.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 766282</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+ function doStuff() {
+ window.opener.parent.ok_wrapper(true, "Sandboxed top-level navigation browsing context flag NOT copied to new auxiliary browsing context.");
+
+ self.close();
+ }
+</script>
+
+<body onLoad="doStuff()">
+ I am navigated to from a window opened from a sandbox with allow-top-navigation.
+</body>
+</html>
diff --git a/dom/html/test/file_iframe_sandbox_worker.js b/dom/html/test/file_iframe_sandbox_worker.js
new file mode 100644
index 000000000..edb63eb6c
--- /dev/null
+++ b/dom/html/test/file_iframe_sandbox_worker.js
@@ -0,0 +1,3 @@
+self.onmessage = function(event) {
+ self.postMessage('make it so');
+}; \ No newline at end of file
diff --git a/dom/html/test/file_ignoreuserfocus.html b/dom/html/test/file_ignoreuserfocus.html
new file mode 100644
index 000000000..b9e330212
--- /dev/null
+++ b/dom/html/test/file_ignoreuserfocus.html
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+ <body>
+ <map name=a>
+ <area shape=rect coords=0,0,100,100 href=#fail>
+ </map>
+ <img usemap=#a src=image.png>
+ <input><iframe></iframe>
+ </body>
+</html>
diff --git a/dom/html/test/file_imports_basics.html b/dom/html/test/file_imports_basics.html
new file mode 100644
index 000000000..0abf4e848
--- /dev/null
+++ b/dom/html/test/file_imports_basics.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ </head>
+ <body>
+ <div id="foo">bar</div>
+ <script>
+ counter++;
+ var importDone = true;
+ is(document.currentScript.ownerDocument.getElementById("foo").textContent, "bar",
+ "currentScript.ownerDocument works in imported document,");
+ try{
+ document.currentScript.ownerDocument.open();
+ document.currentScript.ownerDocument.write("<h1>This should not show up!</h1>");
+ document.currentScript.ownerDocument.close();
+ ok(false, "document.write should have thrown (import)")
+ } catch (e) {
+ ok(true, "document.write has thrown (import)")
+ }
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/file_imports_redirect.html b/dom/html/test/file_imports_redirect.html
new file mode 100644
index 000000000..eaca3f49f
--- /dev/null
+++ b/dom/html/test/file_imports_redirect.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html>
+<body>
+</body>
+</html>
diff --git a/dom/html/test/file_imports_redirect.html^headers^ b/dom/html/test/file_imports_redirect.html^headers^
new file mode 100644
index 000000000..39585a340
--- /dev/null
+++ b/dom/html/test/file_imports_redirect.html^headers^
@@ -0,0 +1,2 @@
+HTTP 301 Moved Permanently
+Location: http://mochi.test:8888/tests/dom/html/test/file_imports_redirected.html
diff --git a/dom/html/test/file_imports_redirected.html b/dom/html/test/file_imports_redirected.html
new file mode 100644
index 000000000..031ca313d
--- /dev/null
+++ b/dom/html/test/file_imports_redirected.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script> var redirected = true; </script>
+</body>
+</html>
diff --git a/dom/html/test/file_mozaudiochannel.html b/dom/html/test/file_mozaudiochannel.html
new file mode 100644
index 000000000..588ae338b
--- /dev/null
+++ b/dom/html/test/file_mozaudiochannel.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<div id="content" style="display: none">
+ <audio id="audio1" />
+ <audio id="audio2" mozaudiochannel="foo" />
+</div>
+
+<script type="application/javascript">
+
+function is(a, b, msg) {
+ parent.postMessage({ status: a === b, msg: msg }, '*');
+}
+
+function ok(a, msg) {
+ parent.postMessage({ status: !!a, msg: msg }, '*');
+}
+
+function finish() {
+ parent.postMessage({ finish: true }, '*');
+}
+
+function test_basic() {
+ var audio1 = document.getElementById("audio1");
+ ok(audio1, "Audio Element exists");
+ is(audio1.mozAudioChannelType, "normal", "Default audio1 channel == 'normal'");
+ try {
+ audio1.mozAudioChannelType = "foo";
+ } catch(e) {}
+ is(audio1.mozAudioChannelType, "normal", "Default audio1 channel == 'normal'");
+
+ var audio2 = document.getElementById("audio2");
+ ok(audio2, "Audio Element exists");
+ is(audio2.mozAudioChannelType, "normal", "Default audio2 channel == 'normal'");
+ try {
+ audio2.mozAudioChannelType = "foo";
+ } catch(e) {}
+ is(audio2.mozAudioChannelType, "normal", "Default audio2 channel == 'normal'");
+
+ runTest();
+}
+
+function test_preferences(aChannel) {
+ SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", aChannel ]]},
+ function() {
+ var audio = document.createElement('audio');
+ ok(audio, "Audio Element created");
+ is(audio.mozAudioChannelType, aChannel, "Default audio channel == '" + aChannel + "'");
+ runTest();
+ }
+ );
+}
+
+function test_wrong_preferences() {
+ SpecialPowers.pushPrefEnv({"set": [["media.defaultAudioChannel", 'foobar' ]]},
+ function() {
+ var audio = document.createElement('audio');
+ ok(audio, "Audio Element created");
+ is(audio.mozAudioChannelType, 'normal', "Default audio channel == 'normal'");
+ runTest();
+ }
+ );
+}
+var tests = [
+ test_basic,
+
+ function() { test_preferences("content"); },
+ function() { test_preferences("notification"); },
+ function() { test_preferences("alarm"); },
+ function() { test_preferences("telephony"); },
+ function() { test_preferences("ringer"); },
+ function() { test_preferences("publicnotification"); },
+
+ test_wrong_preferences,
+];
+
+function runTest() {
+ if (!tests.length) {
+ finish();
+ return;
+ }
+
+ var test = tests.shift();
+ test();
+}
+
+runTest();
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/file_srcdoc-2.html b/dom/html/test/file_srcdoc-2.html
new file mode 100644
index 000000000..bd75f5e05
--- /dev/null
+++ b/dom/html/test/file_srcdoc-2.html
@@ -0,0 +1,10 @@
+<!doctype html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=802895
+-->
+<body>
+<iframe id="iframe" srcdoc="Hello World"></iframe>
+</body>
+
+</html>
diff --git a/dom/html/test/file_srcdoc.html b/dom/html/test/file_srcdoc.html
new file mode 100644
index 000000000..70fbff42f
--- /dev/null
+++ b/dom/html/test/file_srcdoc.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=802895
+-->
+<body>
+<iframe id="iframe" srcdoc="Hello World"></iframe>
+
+<iframe id="iframe1" src="about:mozilla"
+ srcdoc="Goodbye World"></iframe>
+<iframe id="iframe2" srcdoc="Peeking test" sandbox=""></iframe>
+<iframe id="iframe3" src="data:text/html;charset=US-ASCII,Gone"
+ srcdoc="Going"></iframe>
+</body>
+
+</html>
diff --git a/dom/html/test/file_window_open_close_inner.html b/dom/html/test/file_window_open_close_inner.html
new file mode 100644
index 000000000..dbc7e3aba
--- /dev/null
+++ b/dom/html/test/file_window_open_close_inner.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+<script>
+window.close();
+</script>
+</html>
+</body>
diff --git a/dom/html/test/file_window_open_close_outer.html b/dom/html/test/file_window_open_close_outer.html
new file mode 100644
index 000000000..b1450cee4
--- /dev/null
+++ b/dom/html/test/file_window_open_close_outer.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<a id="link" href="file_window_open_close_inner.html" target="_blank" onclick="setTimeout(function () { window.close() }, 0)">link</a>
+</html>
+</body>
diff --git a/dom/html/test/formData_test.js b/dom/html/test/formData_test.js
new file mode 100644
index 000000000..50341276f
--- /dev/null
+++ b/dom/html/test/formData_test.js
@@ -0,0 +1,212 @@
+function testHas() {
+ var f = new FormData();
+ f.append("foo", "bar");
+ f.append("another", "value");
+ ok(f.has("foo"), "has() on existing name should be true.");
+ ok(f.has("another"), "has() on existing name should be true.");
+ ok(!f.has("nonexistent"), "has() on non-existent name should be false.");
+}
+
+function testGet() {
+ var f = new FormData();
+ f.append("foo", "bar");
+ f.append("foo", "bar2");
+ f.append("blob", new Blob(["hey"], { type: 'text/plain' }));
+ f.append("file", new File(["hey"], 'testname', {type: 'text/plain'}));
+
+ is(f.get("foo"), "bar", "get() on existing name should return first value");
+ ok(f.get("blob") instanceof Blob, "get() on existing name should return first value");
+ is(f.get("blob").type, 'text/plain', "get() on existing name should return first value");
+ ok(f.get("file") instanceof File, "get() on existing name should return first value");
+ is(f.get("file").name, 'testname', "get() on existing name should return first value");
+
+ is(f.get("nonexistent"), null, "get() on non-existent name should return null.");
+}
+
+function testGetAll() {
+ var f = new FormData();
+ f.append("other", "value");
+ f.append("foo", "bar");
+ f.append("foo", "bar2");
+ f.append("foo", new Blob(["hey"], { type: 'text/plain' }));
+
+ var arr = f.getAll("foo");
+ is(arr.length, 3, "getAll() should retrieve all matching entries.");
+ is(arr[0], "bar", "values should match and be in order");
+ is(arr[1], "bar2", "values should match and be in order");
+ ok(arr[2] instanceof Blob, "values should match and be in order");
+
+ is(f.get("nonexistent"), null, "get() on non-existent name should return null.");
+}
+
+function testDelete() {
+ var f = new FormData();
+ f.append("other", "value");
+ f.append("foo", "bar");
+ f.append("foo", "bar2");
+ f.append("foo", new Blob(["hey"], { type: 'text/plain' }));
+
+ ok(f.has("foo"), "has() on existing name should be true.");
+ f.delete("foo");
+ ok(!f.has("foo"), "has() on deleted name should be false.");
+ is(f.getAll("foo").length, 0, "all entries should be deleted.");
+
+ is(f.getAll("other").length, 1, "other names should still be there.");
+ f.delete("other");
+ is(f.getAll("other").length, 0, "all entries should be deleted.");
+}
+
+function testSet() {
+ var f = new FormData();
+
+ f.set("other", "value");
+ ok(f.has("other"), "set() on new name should be similar to append()");
+ is(f.getAll("other").length, 1, "set() on new name should be similar to append()");
+
+ f.append("other", "value2");
+ is(f.getAll("other").length, 2, "append() should not replace existing entries.");
+
+ f.append("foo", "bar");
+ f.append("other", "value3");
+ f.append("other", "value3");
+ f.append("other", "value3");
+ is(f.getAll("other").length, 5, "append() should not replace existing entries.");
+
+ f.set("other", "value4");
+ is(f.getAll("other").length, 1, "set() should replace existing entries.");
+ is(f.getAll("other")[0], "value4", "set() should replace existing entries.");
+}
+
+function testFilename() {
+ var f = new FormData();
+ f.append("blob", new Blob(["hi"]));
+ ok(f.get("blob") instanceof Blob, "We should have a blob back.");
+
+ // If a filename is passed, that should replace the original.
+ f.append("blob2", new Blob(["hi"]), "blob2.txt");
+ is(f.get("blob2").name, "blob2.txt", "Explicit filename should override \"blob\".");
+
+ var file = new File(["hi"], "file1.txt");
+ f.append("file1", file);
+ // If a file is passed, the "create entry" algorithm should not create a new File, but reuse the existing one.
+ is(f.get("file1"), file, "Retrieved File object should be original File object and not a copy.");
+ is(f.get("file1").name, "file1.txt", "File's filename should be original's name if no filename is explicitly passed.");
+
+ file = new File(["hi"], "file2.txt");
+ f.append("file2", file, "fakename.txt");
+ ok(f.get("file2") !== file, "Retrieved File object should be new File object if explicit filename is passed.");
+ is(f.get("file2").name, "fakename.txt", "File's filename should be explicitly passed name.");
+ f.append("file3", new File(["hi"], ""));
+ is(f.get("file3").name, "", "File's filename is returned even if empty.");
+}
+
+function testIterable() {
+ var fd = new FormData();
+ fd.set('1','2');
+ fd.set('2','4');
+ fd.set('3','6');
+ fd.set('4','8');
+ fd.set('5','10');
+
+ var key_iter = fd.keys();
+ var value_iter = fd.values();
+ var entries_iter = fd.entries();
+ for (var i = 0; i < 5; ++i) {
+ var v = i + 1;
+ var key = key_iter.next();
+ var value = value_iter.next();
+ var entry = entries_iter.next();
+ is(key.value, v.toString(), "Correct Key iterator: " + v.toString());
+ ok(!key.done, "key.done is false");
+ is(value.value, (v * 2).toString(), "Correct Value iterator: " + (v * 2).toString());
+ ok(!value.done, "value.done is false");
+ is(entry.value[0], v.toString(), "Correct Entry 0 iterator: " + v.toString());
+ is(entry.value[1], (v * 2).toString(), "Correct Entry 1 iterator: " + (v * 2).toString());
+ ok(!entry.done, "entry.done is false");
+ }
+
+ var last = key_iter.next();
+ ok(last.done, "Nothing more to read.");
+ is(last.value, undefined, "Undefined is the last key");
+
+ last = value_iter.next();
+ ok(last.done, "Nothing more to read.");
+ is(last.value, undefined, "Undefined is the last value");
+
+ last = entries_iter.next();
+ ok(last.done, "Nothing more to read.");
+
+ key_iter = fd.keys();
+ key_iter.next();
+ key_iter.next();
+ fd.delete('1');
+ fd.delete('2');
+ fd.delete('3');
+ fd.delete('4');
+ fd.delete('5');
+
+ last = key_iter.next();
+ ok(last.done, "Nothing more to read.");
+ is(last.value, undefined, "Undefined is the last key");
+}
+
+function testSend(doneCb) {
+ var xhr = new XMLHttpRequest();
+ xhr.open("POST", "form_submit_server.sjs");
+ xhr.onload = function () {
+ var response = xhr.response;
+
+ for (var entry of response) {
+ is(entry.body, 'hey');
+ is(entry.headers['Content-Type'], 'text/plain');
+ }
+
+ is(response[0].headers['Content-Disposition'],
+ 'form-data; name="empty"; filename="blob"');
+
+ is(response[1].headers['Content-Disposition'],
+ 'form-data; name="explicit"; filename="explicit-file-name"');
+
+ is(response[2].headers['Content-Disposition'],
+ 'form-data; name="explicit-empty"; filename=""');
+
+ is(response[3].headers['Content-Disposition'],
+ 'form-data; name="file-name"; filename="testname"');
+
+ is(response[4].headers['Content-Disposition'],
+ 'form-data; name="empty-file-name"; filename=""');
+
+ is(response[5].headers['Content-Disposition'],
+ 'form-data; name="file-name-overwrite"; filename="overwrite"');
+
+ doneCb();
+ }
+
+ var file, blob = new Blob(['hey'], {type: 'text/plain'});
+
+ var fd = new FormData();
+ fd.append("empty", blob);
+ fd.append("explicit", blob, "explicit-file-name");
+ fd.append("explicit-empty", blob, "");
+ file = new File([blob], 'testname', {type: 'text/plain'});
+ fd.append("file-name", file);
+ file = new File([blob], '', {type: 'text/plain'});
+ fd.append("empty-file-name", file);
+ file = new File([blob], 'testname', {type: 'text/plain'});
+ fd.append("file-name-overwrite", file, "overwrite");
+ xhr.responseType = 'json';
+ xhr.send(fd);
+}
+
+function runTest(doneCb) {
+ testHas();
+ testGet();
+ testGetAll();
+ testDelete();
+ testSet();
+ testFilename();
+ testIterable();
+ // Finally, send an XHR and verify the response matches.
+ testSend(doneCb);
+}
+
diff --git a/dom/html/test/formData_worker.js b/dom/html/test/formData_worker.js
new file mode 100644
index 000000000..d83823554
--- /dev/null
+++ b/dom/html/test/formData_worker.js
@@ -0,0 +1,19 @@
+function ok(a, msg) {
+ postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
+}
+
+function is(a, b, msg) {
+ postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
+}
+
+function todo(a, msg) {
+ postMessage({type: 'todo', status: !!a, msg: a + ": " + msg });
+}
+
+importScripts("formData_test.js");
+
+onmessage = function() {
+ runTest(function() {
+ postMessage({type: 'finish'});
+ });
+}
diff --git a/dom/html/test/formSubmission_chrome.js b/dom/html/test/formSubmission_chrome.js
new file mode 100644
index 000000000..540a11755
--- /dev/null
+++ b/dom/html/test/formSubmission_chrome.js
@@ -0,0 +1,6 @@
+var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+Cu.importGlobalProperties(["File"]);
+
+addMessageListener("files.open", function (message) {
+ sendAsyncMessage("files.opened", message.map(path => File.createFromFileName(path)));
+});
diff --git a/dom/html/test/form_submit_server.sjs b/dom/html/test/form_submit_server.sjs
new file mode 100644
index 000000000..95c019d16
--- /dev/null
+++ b/dom/html/test/form_submit_server.sjs
@@ -0,0 +1,71 @@
+const CC = Components.Constructor;
+const BinaryInputStream = CC("@mozilla.org/binaryinputstream;1",
+ "nsIBinaryInputStream",
+ "setInputStream");
+
+function utf8decode(s) {
+ return decodeURIComponent(escape(s));
+}
+
+function utf8encode(s) {
+ return unescape(encodeURIComponent(s));
+}
+
+function handleRequest(request, response)
+{
+ var bodyStream = new BinaryInputStream(request.bodyInputStream);
+ var result = [];
+ var requestBody = "";
+ while ((bodyAvail = bodyStream.available()) > 0)
+ requestBody += bodyStream.readBytes(bodyAvail);
+
+ if (request.method == "POST") {
+
+ var contentTypeParams = {};
+ request.getHeader("Content-Type").split(/\s*\;\s*/).forEach(function(s) {
+ if (s.indexOf('=') >= 0) {
+ let [name, value] = s.split('=');
+ contentTypeParams[name] = value;
+ }
+ else {
+ contentTypeParams[''] = s;
+ }
+ });
+
+ if (contentTypeParams[''] == "multipart/form-data" &&
+ request.queryString == "") {
+ requestBody.split("--" + contentTypeParams.boundary).slice(1, -1).forEach(function (s) {
+
+ let headers = {};
+ let headerEnd = s.indexOf("\r\n\r\n");
+ s.substr(2, headerEnd-2).split("\r\n").forEach(function(s) {
+ // We're assuming UTF8 for now
+ let [name, value] = s.split(': ');
+ headers[name] = utf8decode(value);
+ });
+
+ let body = s.substring(headerEnd + 4, s.length - 2);
+ if (!headers["Content-Type"] || headers["Content-Type"] == "text/plain") {
+ // We're assuming UTF8 for now
+ body = utf8decode(body);
+ }
+ result.push({ headers: headers, body: body});
+ });
+ }
+ if (contentTypeParams[''] == "text/plain" &&
+ request.queryString == "plain") {
+ result = utf8decode(requestBody);
+ }
+ if (contentTypeParams[''] == "application/x-www-form-urlencoded" &&
+ request.queryString == "url") {
+ result = requestBody;
+ }
+ }
+ else if (request.method == "GET") {
+ result = request.queryString;
+ }
+
+ // Send response body
+ response.setHeader("Content-Type", "text/plain; charset=utf-8", false);
+ response.write(utf8encode(JSON.stringify(result)));
+}
diff --git a/dom/html/test/forms/chrome.ini b/dom/html/test/forms/chrome.ini
new file mode 100644
index 000000000..0c8fa8231
--- /dev/null
+++ b/dom/html/test/forms/chrome.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+support-files =
+ submit_invalid_file.sjs
+[test_autocompleteinfo.html]
+[test_submit_invalid_file.html]
diff --git a/dom/html/test/forms/mochitest.ini b/dom/html/test/forms/mochitest.ini
new file mode 100644
index 000000000..35955b189
--- /dev/null
+++ b/dom/html/test/forms/mochitest.ini
@@ -0,0 +1,107 @@
+[DEFAULT]
+support-files =
+ save_restore_radio_groups.sjs
+ test_input_number_data.js
+ !/dom/html/test/reflect.js
+
+[test_bug1039548.html]
+[test_bug1283915.html]
+[test_bug1286509.html]
+skip-if = os == "android" # up/down arrow keys not supported on android
+[test_button_attributes_reflection.html]
+[test_input_radio_indeterminate.html]
+[test_input_radio_radiogroup.html]
+[test_input_radio_required.html]
+[test_change_event.html]
+[test_datalist_element.html]
+[test_form_attribute-1.html]
+[test_form_attribute-2.html]
+[test_form_attribute-3.html]
+[test_form_attribute-4.html]
+[test_form_attributes_reflection.html]
+[test_form_named_getter_dynamic.html]
+[test_formaction_attribute.html]
+[test_formnovalidate_attribute.html]
+[test_input_attributes_reflection.html]
+[test_input_autocomplete.html]
+[test_input_color_input_change_events.html]
+[test_input_color_picker_initial.html]
+[test_input_color_picker_popup.html]
+skip-if = android_version == '18' # Android, bug 1147974
+[test_input_color_picker_update.html]
+skip-if = android_version == '18' # Android, bug 1147974
+[test_input_datetime_focus_blur.html]
+skip-if = os == "android"
+[test_input_datetime_tabindex.html]
+skip-if = os == "android"
+[test_input_defaultValue.html]
+[test_input_email.html]
+[test_input_event.html]
+skip-if = android_version == '18' # bug 1147974
+[test_input_file_picker.html]
+[test_input_list_attribute.html]
+[test_input_number_l10n.html]
+# We don't build ICU for Firefox for Android:
+skip-if = os == "android"
+[test_input_number_key_events.html]
+[test_input_number_mouse_events.html]
+# Not run on Firefox for Android where the spin buttons are hidden:
+skip-if = os == "android"
+[test_input_number_rounding.html]
+skip-if = os == "android"
+[test_input_number_validation.html]
+# We don't build ICU for Firefox for Android:
+skip-if = os == "android"
+[test_input_number_focus.html]
+[test_input_range_attr_order.html]
+[test_input_range_key_events.html]
+[test_input_range_mouse_and_touch_events.html]
+[test_input_range_rounding.html]
+[test_input_sanitization.html]
+[test_input_textarea_set_value_no_scroll.html]
+[test_input_time_key_events.html]
+skip-if = os == "android"
+[test_input_time_focus_blur_events.html]
+skip-if = os == "android"
+[test_input_types_pref.html]
+[test_input_typing_sanitization.html]
+[test_input_untrusted_key_events.html]
+[test_input_url.html]
+[test_interactive_content_in_label.html]
+[test_label_control_attribute.html]
+[test_label_input_controls.html]
+[test_max_attribute.html]
+[test_maxlength_attribute.html]
+[test_minlength_attribute.html]
+[test_meter_element.html]
+[test_meter_pseudo-classes.html]
+[test_min_attribute.html]
+[test_mozistextfield.html]
+[test_novalidate_attribute.html]
+[test_option_disabled.html]
+[test_option_index_attribute.html]
+[test_option_text.html]
+[test_output_element.html]
+[test_pattern_attribute.html]
+[test_progress_element.html]
+[test_radio_in_label.html]
+[test_radio_radionodelist.html]
+[test_required_attribute.html]
+[test_restore_form_elements.html]
+[test_save_restore_radio_groups.html]
+[test_select_change_event.html]
+skip-if = android_version == '18' || os == 'mac'
+[test_select_input_change_event.html]
+skip-if = android_version == '18' || os == 'mac'
+[test_select_selectedOptions.html]
+[test_select_validation.html]
+[test_set_range_text.html]
+[test_step_attribute.html]
+[test_stepup_stepdown.html]
+[test_textarea_attributes_reflection.html]
+[test_validation.html]
+[test_valueAsDate_pref.html]
+[test_valueasdate_attribute.html]
+[test_valueasnumber_attribute.html]
+[test_validation_not_in_doc.html]
+[test_reportValidation_preventDefault.html]
diff --git a/dom/html/test/forms/save_restore_radio_groups.sjs b/dom/html/test/forms/save_restore_radio_groups.sjs
new file mode 100644
index 000000000..f0e36cb52
--- /dev/null
+++ b/dom/html/test/forms/save_restore_radio_groups.sjs
@@ -0,0 +1,50 @@
+var pages = [
+ "<!DOCTYPE html>" +
+ "<html><body>" +
+ "<form>" +
+ "<input name='a' type='radio' checked><input name='a' type='radio'><input name='a' type='radio'>" +
+ "</form>" +
+ "</body></html>",
+ "<!DOCTYPE html>" +
+ "<html><body>" +
+ "<form>" +
+ "<input name='a' type='radio'><input name='a' type='radio' checked><input name='a' type='radio'>" +
+ "</form>" +
+ "</body></html>",
+ ];
+
+/**
+ * This SJS is going to send the same page the two first times it will be called
+ * and another page the two following times. After that, the response will have
+ * no content.
+ * The use case is to have two iframes using this SJS and both being reloaded
+ * once.
+ */
+
+function handleRequest(request, response)
+{
+ var counter = +getState("counter"); // convert to number; +"" === 0
+
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+ response.setHeader("Content-Type", "text/html");
+ response.setHeader("Cache-Control", "no-cache");
+
+ switch (counter) {
+ case 0:
+ case 1:
+ response.write(pages[0]);
+ break;
+ case 2:
+ case 3:
+ response.write(pages[1]);
+ break;
+ }
+
+ // When we finish the test case we need to reset the counter
+ if (counter == 3) {
+ setState("counter", "0");
+ } else {
+ setState("counter", "" + ++counter);
+ }
+}
+
diff --git a/dom/html/test/forms/submit_invalid_file.sjs b/dom/html/test/forms/submit_invalid_file.sjs
new file mode 100644
index 000000000..8f8b46957
--- /dev/null
+++ b/dom/html/test/forms/submit_invalid_file.sjs
@@ -0,0 +1,14 @@
+function handleRequest(request, response)
+{
+ response.setStatusLine(request.httpVersion, 200, "Ok");
+ response.setHeader("Content-Type", "text/html");
+ response.setHeader("Cache-Control", "no-cache");
+
+ var result = {};
+ request.bodyInputStream.search("testfile", true, result, {});
+ if (result.value) {
+ response.write("SUCCESS");
+ } else {
+ response.write("FAIL");
+ }
+}
diff --git a/dom/html/test/forms/test_autocompleteinfo.html b/dom/html/test/forms/test_autocompleteinfo.html
new file mode 100644
index 000000000..310b7c9f3
--- /dev/null
+++ b/dom/html/test/forms/test_autocompleteinfo.html
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test getAutocompleteInfo() on <input>
+-->
+<head>
+ <title>Test for getAutocompleteInfo()</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <form>
+ <input id="input"/>
+ </form>
+</div>
+<pre id="test">
+<script>
+"use strict";
+
+var values = [
+ // Missing or empty attribute
+ [undefined, {}],
+ ["", {}],
+
+ // One token
+ ["on", {fieldName: "on" }],
+ ["On", {fieldName: "on" }],
+ ["off", {fieldName: "off" } ],
+ ["username", {fieldName: "username" }],
+ [" username ", {fieldName: "username" }],
+ ["foobar", {}],
+
+ // Two tokens
+ ["on off", {}],
+ ["off on", {}],
+ ["username tel", {}],
+ ["tel username ", {}],
+ [" username tel ", {}],
+ ["tel mobile", {}],
+ ["tel shipping", {}],
+ ["shipping tel", {addressType: "shipping", fieldName: "tel"}],
+ ["shipPING tel", {addressType: "shipping", fieldName: "tel"}],
+ ["mobile tel", {contactType: "mobile", fieldName: "tel"}],
+ [" MoBiLe TeL ", {contactType: "mobile", fieldName: "tel"}],
+ ["XXX tel", {}],
+ ["XXX username", {}],
+
+ // Three tokens
+ ["billing invalid tel", {}],
+ ["___ mobile tel", {}],
+ ["mobile foo tel", {}],
+ ["mobile tel foo", {}],
+ ["tel mobile billing", {}],
+ ["billing mobile tel", {addressType: "billing", contactType: "mobile", fieldName: "tel"}],
+ [" BILLing MoBiLE tEl ", {addressType: "billing", contactType: "mobile", fieldName: "tel"}],
+ ["billing home tel", {addressType: "billing", contactType: "home", fieldName: "tel"}],
+
+ // Four tokens (invalid)
+ ["billing billing mobile tel", {}],
+
+ // Five tokens (invalid)
+ ["billing billing billing mobile tel", {}],
+];
+
+var autocompleteEnabledTypes = ["hidden", "text", "search", "url", "tel",
+ "email", "password", "date", "time", "number",
+ "range", "color"];
+var autocompleteDisabledTypes = ["reset", "submit", "image", "button", "radio",
+ "checkbox", "file"];
+
+function start() {
+ const fieldid = "input";
+ var field = document.getElementById(fieldid);
+ for (var test of values) {
+ if (typeof(test[0]) === "undefined")
+ field.removeAttribute("autocomplete");
+ else
+ field.setAttribute("autocomplete", test[0]);
+
+ var info = field.getAutocompleteInfo();
+
+ is(info.section, "section" in test[1] ? test[1].section : "",
+ "Checking autocompleteInfo.section for " + fieldid + ": " + test[0]);
+ is(info.addressType, "addressType" in test[1] ? test[1].addressType : "",
+ "Checking autocompleteInfo.addressType for " + fieldid + ": " + test[0]);
+ is(info.contactType, "contactType" in test[1] ? test[1].contactType : "",
+ "Checking autocompleteInfo.contactType for " + fieldid + ": " + test[0]);
+ is(info.fieldName, "fieldName" in test[1] ? test[1].fieldName : "",
+ "Checking autocompleteInfo.fieldName for " + fieldid + ": " + test[0]);
+
+ }
+
+ for (var type of autocompleteEnabledTypes) {
+ testAutocomplete(field, type, true);
+ }
+
+ for (var type of autocompleteDisabledTypes) {
+ testAutocomplete(field, type, false);
+ }
+ SimpleTest.finish();
+}
+
+function testAutocomplete(aField, aType, aEnabled) {
+ aField.type = aType;
+ if (aEnabled) {
+ ok(aField.getAutocompleteInfo() !== null, "getAutocompleteInfo shouldn't return null");
+ } else {
+ is(aField.getAutocompleteInfo(), null, "getAutocompleteInfo should return null");
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["dom.forms.autocomplete.experimental", true]]}, start);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_bug1039548.html b/dom/html/test/forms/test_bug1039548.html
new file mode 100644
index 000000000..0405d5482
--- /dev/null
+++ b/dom/html/test/forms/test_bug1039548.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1039548
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1039548</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1039548 **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ SimpleTest.waitForFocus(test);
+
+ var didTryToSubmit;
+ function test() {
+ var r = document.getElementById("radio");
+ r.focus();
+ didTryToSubmit = false;
+ sendKey("return");
+ ok(!didTryToSubmit, "Shouldn't have tried to submit!");
+
+ var t = document.getElementById("text");
+ t.focus();
+ didTryToSubmit = false;
+ sendKey("return");
+ ok(didTryToSubmit, "Should have tried to submit!");
+ SimpleTest.finish();
+ }
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1039548">Mozilla Bug 1039548</a>
+<p id="display"></p>
+<div id="content">
+
+ <form onsubmit="didTryToSubmit = true; event.preventDefault();">
+ <input type="radio" id="radio">
+ </form>
+
+ <form onsubmit="didTryToSubmit = true; event.preventDefault();">
+ <input type="text" id="text">
+ </form>
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_bug1283915.html b/dom/html/test/forms/test_bug1283915.html
new file mode 100644
index 000000000..0b0ac5f13
--- /dev/null
+++ b/dom/html/test/forms/test_bug1283915.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1283915
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1283915</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1283915 **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ function isCursorAtEnd(field){
+ is(field.selectionStart, field.value.length);
+ is(field.selectionEnd, field.value.length);
+ }
+
+ function test() {
+ var tField = document.getElementById("textField");
+ tField.focus();
+
+ synthesizeKey("a", {});
+ is(tField.value, "a");
+ isCursorAtEnd(tField);
+ document.body.offsetWidth; // frame must be created after type change
+
+ synthesizeKey("b", {});
+ is(tField.value, "ab");
+ isCursorAtEnd(tField);
+
+ synthesizeKey("c", {});
+ is(tField.value, "abc");
+ isCursorAtEnd(tField);
+
+ var nField = document.getElementById("numField");
+ nField.focus();
+
+ synthesizeKey("1", {});
+ is(nField.value, "1");
+ document.body.offsetWidth;
+
+ synthesizeKey("2", {});
+ is(nField.value, "12");
+
+ synthesizeKey("3", {});
+ is(nField.value, "123");
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForFocus(test);
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1283915">Mozilla Bug 1283915</a>
+<p id="display"></p>
+<input id="textField" type="text" oninput="if (this.type !='password') this.type = 'password';">
+<input id="numField" type="text" oninput="if (this.type !='number') this.type = 'number';">
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_bug1286509.html b/dom/html/test/forms/test_bug1286509.html
new file mode 100644
index 000000000..05fbbac31
--- /dev/null
+++ b/dom/html/test/forms/test_bug1286509.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1286509
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1286509</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1286509">Mozilla Bug 1286509</a>
+<p id="display"></p>
+<div id="content">
+ <input type="range" id="test_input" min="0" max="10" value="5">
+</div>
+<pre id="test">
+ <script type="application/javascript">
+ /** Test for Bug 1286509 **/
+ SimpleTest.waitForExplicitFinish();
+ var expectedEventSequence = ['keydown', 'change', 'keyup'];
+ var eventCounts = {};
+ var expectedEventIdx = 0;
+
+ function test() {
+ var range = document.getElementById("test_input");
+ range.focus();
+ expectedEventSequence.forEach((eventName) => {
+ eventCounts[eventName] = 0;
+ range.addEventListener(eventName, (e) => {
+ ++eventCounts[eventName];
+ is(expectedEventSequence[expectedEventIdx], e.type, "Events sequence should be keydown, change, keyup");
+ expectedEventIdx = (expectedEventIdx + 1) % 3;
+ }, false);
+ });
+ synthesizeKey("VK_UP", {});
+ synthesizeKey("VK_DOWN", {});
+ synthesizeKey("VK_LEFT", {});
+ synthesizeKey("VK_RIGHT", {});
+ is(eventCounts['change'], 4, "Expect key up/down/left/right should trigger range input to fire change events");
+ SimpleTest.finish();
+ }
+ addLoadEvent(test);
+ </script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_button_attributes_reflection.html b/dom/html/test/forms/test_button_attributes_reflection.html
new file mode 100644
index 000000000..26858e939
--- /dev/null
+++ b/dom/html/test/forms/test_button_attributes_reflection.html
@@ -0,0 +1,137 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLButtonElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="../reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLButtonElement attributes reflection **/
+
+// .autofocus
+reflectBoolean({
+ element: document.createElement("button"),
+ attribute: "autofocus",
+});
+
+// .disabled
+reflectBoolean({
+ element: document.createElement("button"),
+ attribute: "disabled",
+});
+
+// TODO: formAction (URL). But note that we currently reflect it weirdly; see
+// dom/html/test/test_bug607145.html
+
+// .formEnctype
+reflectLimitedEnumerated({
+ element: document.createElement("button"),
+ attribute: "formEnctype",
+ validValues: [
+ "application/x-www-form-urlencoded",
+ "multipart/form-data",
+ "text/plain",
+ ],
+ invalidValues: [ "text/html", "", "tulip" ],
+ defaultValue: {
+ invalid: "application/x-www-form-urlencoded",
+ missing: "",
+ }
+});
+
+// .formMethod
+reflectLimitedEnumerated({
+ element: document.createElement("button"),
+ attribute: "formMethod",
+ validValues: [ "get", "post" ],
+ invalidValues: [ "put", "", "tulip" ],
+ unsupportedValues: [ "dialog" ],
+ defaultValue: {
+ invalid: "get",
+ missing: "",
+ }
+});
+
+// .formNoValidate
+reflectBoolean({
+ element: document.createElement("button"),
+ attribute: "formNoValidate",
+});
+
+// .formTarget
+reflectString({
+ element: document.createElement("button"),
+ attribute: "formTarget",
+ otherValues: [ "_blank", "_self", "_parent", "_top" ],
+});
+
+// .name
+reflectString({
+ element: document.createElement("button"),
+ attribute: "name",
+ otherValues: [ "isindex", "_charset_" ]
+});
+
+// .type
+reflectLimitedEnumerated({
+ element: document.createElement("button"),
+ attribute: "type",
+ validValues: [ "submit", "reset", "button" ],
+ invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ],
+ unsupportedValues: [ "menu" ],
+ defaultValue: "submit",
+});
+
+// .value
+reflectString({
+ element: document.createElement("button"),
+ attribute: "value",
+});
+
+// .willValidate
+ok("willValidate" in document.createElement("button"),
+ "willValidate should be an IDL attribute of the button element");
+is(typeof(document.createElement("button").willValidate), "boolean",
+ "button.willValidate should be a boolean");
+
+// .validity
+ok("validity" in document.createElement("button"),
+ "validity should be an IDL attribute of the button element");
+is(typeof(document.createElement("button").validity), "object",
+ "button.validity should be an object");
+ok(document.createElement("button").validity instanceof ValidityState,
+ "button.validity sohuld be an instance of ValidityState");
+
+// .validationMessage
+ok("validationMessage" in document.createElement("button"),
+ "validationMessage should be an IDL attribute of the button element");
+is(typeof(document.createElement("button").validationMessage), "string",
+ "button.validationMessage should be a string");
+
+// .checkValidity()
+ok("checkValidity" in document.createElement("button"),
+ "checkValidity() should be a method of the button element");
+is(typeof(document.createElement("button").checkValidity), "function",
+ "button.checkValidity should be a function");
+
+// .setCustomValidity()
+ok("setCustomValidity" in document.createElement("button"),
+ "setCustomValidity() should be a method of the button element");
+is(typeof(document.createElement("button").setCustomValidity), "function",
+ "button.setCustomValidity should be a function");
+
+// .labels
+todo("labels" in document.createElement("button"),
+ "button.labels isn't implemented yet");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_change_event.html b/dom/html/test/forms/test_change_event.html
new file mode 100644
index 000000000..d1f0f827e
--- /dev/null
+++ b/dom/html/test/forms/test_change_event.html
@@ -0,0 +1,287 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=722599
+-->
+<head>
+<title>Test for Bug 722599</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=722599">Mozilla Bug 722599</a>
+<p id="display"></p>
+<div id="content">
+<input type="file" id="fileInput"></input>
+<textarea id="textarea" onchange="++textareaChange;"></textarea>
+<input type="text" id="input_text" onchange="++textInputChange[0];"></input>
+<input type="email" id="input_email" onchange="++textInputChange[1];"></input>
+<input type="search" id="input_search" onchange="++textInputChange[2];"></input>
+<input type="tel" id="input_tel" onchange="++textInputChange[3];"></input>
+<input type="url" id="input_url" onchange="++textInputChange[4];"></input>
+<input type="password" id="input_password" onchange="++textInputChange[5];"></input>
+
+<!-- "Non-text" inputs-->
+<input type="button" id="input_button" onchange="++NonTextInputChange[0];"></input>
+<input type="submit" id="input_submit" onchange="++NonTextInputChange[1];"></input>
+<input type="image" id="input_image" onchange="++NonTextInputChange[2];"></input>
+<input type="reset" id="input_reset" onchange="++NonTextInputChange[3];"></input>
+<input type="radio" id="input_radio" onchange="++NonTextInputChange[4];"></input>
+<input type="checkbox" id="input_checkbox" onchange="++NonTextInputChange[5];"></input>
+<input type="number" id="input_number" onchange="++numberChange;"></input>
+<input type="range" id="input_range" onchange="++rangeChange;"></input>
+
+<!-- Input text with default value and blurs on focus-->
+<input type="text" id="input_text_value" onchange="++textInputValueChange"
+ onfocus="this.blur();" value="foo"></input>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ /** Test for Bug 722599 **/
+
+ const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
+
+ var textareaChange = 0;
+ var fileInputChange = 0;
+ var textInputValueChange = 0;
+
+ var textInputTypes = ["text", "email", "search", "tel", "url", "password"];
+ var textInputChange = [0, 0, 0, 0, 0, 0];
+
+ var NonTextInputTypes = ["button", "submit", "image", "reset", "radio", "checkbox"];
+ var NonTextInputChange = [0, 0, 0, 0, 0, 0];
+
+ var numberChange = 0;
+ var rangeChange = 0;
+
+ var blurTestCalled = false; //Sentinel to prevent infinite loop.
+
+ SimpleTest.waitForExplicitFinish();
+ var MockFilePicker = SpecialPowers.MockFilePicker;
+ MockFilePicker.init(window);
+
+ function fileInputBlurTest() {
+ var btn = document.getElementById('fileInput');
+ btn.focus()
+ btn.blur();
+ is(fileInputChange, 1, "change event shouldn't be dispatched on blur for file input element(1)");
+ }
+
+ function testUserInput() {
+ //Simulating an OK click and with a file name return.
+ MockFilePicker.useBlobFile();
+ MockFilePicker.returnValue = MockFilePicker.returnOK;
+ var input = document.getElementById('fileInput');
+ input.focus();
+
+ input.addEventListener("change", function (aEvent) {
+ ++fileInputChange;
+ if (!blurTestCalled) {
+ is(fileInputChange, 1, "change event should have been dispatched on file input.");
+ blurTestCalled = true;
+ fileInputBlurTest();
+ }
+ else {
+ is(fileInputChange, 1, "change event shouldn't be dispatched on blur for file input element (2)");
+ }
+ }, false);
+ input.click();
+ // blur the file input, we can't use blur() because of bug 760283
+ document.getElementById('input_text').focus();
+ setTimeout(testUserInput2, 0);
+ }
+
+ function testUserInput2() {
+ var input = document.getElementById('fileInput');
+ // remove it, otherwise cleanup() opens a native file picker!
+ input.parentNode.removeChild(input);
+ MockFilePicker.cleanup();
+
+ //text, email, search, telephone, url & password input tests
+ for (var i = 0; i < textInputTypes.length; ++i) {
+ input = document.getElementById("input_" + textInputTypes[i]);
+ input.focus();
+ synthesizeKey("VK_RETURN", {});
+ is(textInputChange[i], 0, "Change event shouldn't be dispatched on " + textInputTypes[i] + " input element");
+
+ synthesizeKey("m", {});
+ synthesizeKey("VK_RETURN", {});
+ is(textInputChange[i], 1, textInputTypes[i] + " input element should have dispatched change event.");
+ }
+
+ //focus and blur text input
+ input = document.getElementById("input_text");
+ input.focus();
+ synthesizeKey("f", {});
+ input.blur();
+ is(textInputChange[0], 2, "text input element should have dispatched change event (2).");
+
+ // value being set while focused
+ input.focus();
+ input.value = 'foo';
+ input.blur();
+ is(textInputChange[0], 2, "text input element should not have dispatched change event (2).");
+
+ // value being set while focused after being modified manually
+ input.focus();
+ synthesizeKey("f", {});
+ input.value = 'bar';
+ input.blur();
+ is(textInputChange[0], 3, "text input element should have dispatched change event (3).");
+
+ //focus and blur textarea
+ var textarea = document.getElementById("textarea");
+ textarea.focus();
+ synthesizeKey("f", {});
+ textarea.blur();
+ is(textareaChange, 1, "Textarea element should have dispatched change event.");
+
+ // value being set while focused
+ textarea.focus();
+ textarea.value = 'foo';
+ textarea.blur();
+ is(textareaChange, 1, "textarea should not have dispatched change event (1).");
+
+ // value being set while focused after being modified manually
+ textarea.focus();
+ synthesizeKey("f", {});
+ textarea.value = 'bar';
+ textarea.blur();
+ is(textareaChange, 2, "textearea should have dispatched change event (2).");
+
+ //Non-text input tests:
+ for (var i = 0; i < NonTextInputTypes.length; ++i) {
+ //button, submit, image and reset input type tests.
+ if (i < 4) {
+ input = document.getElementById("input_" + NonTextInputTypes[i]);
+ input.focus();
+ input.click();
+ is(NonTextInputChange[i], 0, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element");
+ input.blur();
+ is(NonTextInputChange[i], 0, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element(2)");
+ }
+ //for radio and and checkboxes, we require that change event should ONLY be dispatched on setting the value.
+ else {
+ input = document.getElementById("input_" + NonTextInputTypes[i]);
+ input.focus();
+ input.click();
+ is(NonTextInputChange[i], 1, NonTextInputTypes[i] + " input element should have dispatched change event.");
+ input.blur();
+ is(NonTextInputChange[i], 1, "Change event shouldn't be dispatched on " + NonTextInputTypes[i] + " input element");
+
+ // Test that change event is not dispatched if click event is cancelled.
+ function preventDefault(e) {
+ e.preventDefault();
+ }
+ input.addEventListener("click", preventDefault, false);
+ input.click();
+ is(NonTextInputChange[i], 1, "Change event shouldn't be dispatched if click event is cancelled");
+ input.removeEventListener("click", preventDefault, false);
+ }
+ }
+
+ // Special case type=number
+ var number = document.getElementById("input_number");
+ number.focus();
+ synthesizeKey("a", {});
+ number.blur();
+ is(numberChange, 0, "Change event shouldn't be dispatched on number input element for key changes that don't change its value");
+ number.value = "";
+ number.focus();
+ synthesizeKey("1", {});
+ synthesizeKey("2", {});
+ is(numberChange, 0, "Change event shouldn't be dispatched on number input element for keyboard input until it loses focus");
+ number.blur();
+ is(numberChange, 1, "Change event should be dispatched on number input element on blur");
+ is(number.value, "12", "Sanity check that number keys were actually handled");
+ if (isDesktop) { // up/down arrow keys not supported on android/b2g
+ number.value = "";
+ number.focus();
+ synthesizeKey("VK_UP", {});
+ synthesizeKey("VK_UP", {});
+ synthesizeKey("VK_DOWN", {});
+ is(numberChange, 4, "Change event should be dispatched on number input element for up/down arrow keys (a special case)");
+ is(number.value, "1", "Sanity check that number and arrow keys were actually handled");
+ }
+
+ // Special case type=range
+ var range = document.getElementById("input_range");
+ range.focus();
+ synthesizeKey("a", {});
+ range.blur();
+ is(rangeChange, 0, "Change event shouldn't be dispatched on range input element for key changes that don't change its value");
+ range.focus();
+ synthesizeKey("VK_HOME", {});
+ is(rangeChange, 1, "Change event should be dispatched on range input element for key changes");
+ range.blur();
+ is(rangeChange, 1, "Change event shouldn't be dispatched on range input element on blur");
+ range.focus();
+ var bcr = range.getBoundingClientRect();
+ var centerOfRangeX = bcr.width / 2;
+ var centerOfRangeY = bcr.height / 2;
+ synthesizeMouse(range, centerOfRangeX - 10, centerOfRangeY, { type: "mousedown" });
+ is(rangeChange, 1, "Change event shouldn't be dispatched on range input element for mousedown");
+ synthesizeMouse(range, centerOfRangeX - 5, centerOfRangeY, { type: "mousemove" });
+ is(rangeChange, 1, "Change event shouldn't be dispatched on range input element during drag of thumb");
+ synthesizeMouse(range, centerOfRangeX, centerOfRangeY, { type: "mouseup" });
+ is(rangeChange, 2, "Change event should be dispatched on range input element at end of drag");
+ range.blur();
+ is(rangeChange, 2, "Change event shouldn't be dispatched on range input element when range loses focus after a drag");
+ synthesizeMouse(range, centerOfRangeX - 10, centerOfRangeY, {});
+ is(rangeChange, 3, "Change event should be dispatched on range input element for a click that gives the range focus");
+
+ if (isDesktop) { // up/down arrow keys not supported on android/b2g
+ synthesizeKey("VK_UP", {});
+ is(rangeChange, 4, "Change event should be dispatched on range input element for key changes that change its value (VK_UP)");
+ synthesizeKey("VK_DOWN", {});
+ is(rangeChange, 5, "Change event should be dispatched on range input element for key changes that change its value (VK_DOWN)");
+ synthesizeKey("VK_RIGHT", {});
+ is(rangeChange, 6, "Change event should be dispatched on range input element for key changes that change its value (VK_RIGHT)");
+ synthesizeKey("VK_LEFT", {});
+ is(rangeChange, 7, "Change event should be dispatched on range input element for key changes that change its value (VK_LEFT)");
+ synthesizeKey("VK_UP", {shiftKey: true});
+ is(rangeChange, 8, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_UP)");
+ synthesizeKey("VK_DOWN", {shiftKey: true});
+ is(rangeChange, 9, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_DOWN)");
+ synthesizeKey("VK_RIGHT", {shiftKey: true});
+ is(rangeChange, 10, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_RIGHT)");
+ synthesizeKey("VK_LEFT", {shiftKey: true});
+ is(rangeChange, 11, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_LEFT)");
+ synthesizeKey("VK_PAGE_UP", {});
+ is(rangeChange, 12, "Change event should be dispatched on range input element for key changes that change its value (VK_PAGE_UP)");
+ synthesizeKey("VK_PAGE_DOWN", {});
+ is(rangeChange, 13, "Change event should be dispatched on range input element for key changes that change its value (VK_PAGE_DOWN");
+ synthesizeKey("VK_RIGHT", {shiftKey: true});
+ is(rangeChange, 14, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_PAGE_UP)");
+ synthesizeKey("VK_LEFT", {shiftKey: true});
+ is(rangeChange, 15, "Change event should be dispatched on range input element for key changes that change its value (Shift+VK_PAGE_DOWN)");
+ }
+ //Input type change test.
+ input = document.getElementById("input_checkbox");
+ input.type = "text";
+ input.focus();
+ input.click();
+ input.blur();
+ is(NonTextInputChange[5], 1, "Change event shouldn't be dispatched for checkbox ---> text input type change");
+
+ setTimeout(testInputWithDefaultValue, 0);
+ }
+
+ function testInputWithDefaultValue() {
+ // focus and blur an input text should not trigger change event if content hasn't changed.
+ var input = document.getElementById('input_text_value');
+ input.focus();
+ is(textInputValueChange, 0, "change event shouldn't be dispatched on input text with default value");
+
+ SimpleTest.finish();
+ }
+
+ addLoadEvent(testUserInput);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_datalist_element.html b/dom/html/test/forms/test_datalist_element.html
new file mode 100644
index 000000000..67c8e854a
--- /dev/null
+++ b/dom/html/test/forms/test_datalist_element.html
@@ -0,0 +1,118 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for the datalist element</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <datalist>
+ </datalist>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 555840 **/
+
+function checkClassesAndAttributes()
+{
+ var d = document.getElementsByTagName('datalist');
+ is(d.length, 1, "One datalist has been found");
+
+ d = d[0];
+ ok(d instanceof HTMLDataListElement,
+ "The datalist should be instance of HTMLDataListElement");
+
+ ok('options' in d, "datalist has an options IDL attribute");
+
+ ok(d.options, "options IDL attribute is not null");
+ ok(!d.getAttribute('options'), "datalist has no options content attribute");
+
+ ok(d.options instanceof HTMLCollection,
+ "options IDL attribute should be instance of HTMLCollection");
+}
+
+function checkOptions()
+{
+ var testData = [
+ /* [ Child list, Function modifying children, Recognized options ] */
+ [['option'], null, 1],
+ [['option', 'option', 'option', 'option'], null, 4],
+ /* Disabled options are not valid. */
+ [['option'], function(d) { d.childNodes[0].disabled = true; }, 0],
+ [['option', 'option'], function(d) { d.childNodes[0].disabled = true; }, 1],
+ /* Non-option elements are not recognized. */
+ [['input'], null, 0],
+ [['input', 'option'], null, 1],
+ [['input', 'textarea'], null, 0],
+ /* .value and .label are not needed to be valid options. */
+ [['option', 'option'], function(d) { d.childNodes[0].value = 'value'; }, 2],
+ [['option', 'option'], function(d) { d.childNodes[0].label = 'label'; }, 2],
+ [['option', 'option'], function(d) { d.childNodes[0].value = 'value'; d.childNodes[0].label = 'label'; }, 2],
+ [['select'],
+ function(d) {
+ var s = d.childNodes[0];
+ s.appendChild(new Option("foo"));
+ s.appendChild(new Option("bar"));
+ },
+ 2],
+ [['select'],
+ function(d) {
+ var s = d.childNodes[0];
+ s.appendChild(new Option("foo"));
+ s.appendChild(new Option("bar"));
+ var label = document.createElement("label");
+ d.appendChild(label);
+ label.appendChild(new Option("foobar"));
+ },
+ 3],
+ [['select'],
+ function(d) {
+ var s = d.childNodes[0];
+ s.appendChild(new Option("foo"));
+ s.appendChild(new Option("bar"));
+ var label = document.createElement("label");
+ d.appendChild(label);
+ label.appendChild(new Option("foobar"));
+ s.appendChild(new Option())
+ },
+ 4],
+ [[], function(d) { d.appendChild(document.createElementNS("foo", "option")); }, 0]
+ ];
+
+ var d = document.getElementsByTagName('datalist')[0];
+ var cachedOptions = d.options;
+
+ testData.forEach(function(data) {
+ data[0].forEach(function(e) {
+ d.appendChild(document.createElement(e));
+ })
+
+ /* Modify children. */
+ if (data[1]) {
+ data[1](d);
+ }
+
+ is(d.options, cachedOptions, "Should get the same object")
+ is(d.options.length, data[2],
+ "The number of recognized options should be " + data[2])
+
+ for (var i = 0; i < d.options.length; ++i) {
+ is(d.options[i].localName, "option",
+ "Should get an option for d.options[" + i + "]")
+ }
+
+ /* Cleaning-up. */
+ d.textContent = "";
+ })
+}
+
+checkClassesAndAttributes();
+checkOptions();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_form_attribute-1.html b/dom/html/test/forms/test_form_attribute-1.html
new file mode 100644
index 000000000..bb82cb0da
--- /dev/null
+++ b/dom/html/test/forms/test_form_attribute-1.html
@@ -0,0 +1,473 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=588683
+-->
+<head>
+ <title>Test for form attributes 1</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=588683">Mozilla Bug 588683</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for form attributes 1 **/
+
+/**
+ * All functions take an array of forms in first argument and an array of
+ * elements in second argument.
+ * Then, it returns an array containing an array of form and an array of array
+ * of elements. The array represent the form association with elements like this:
+ * [ [ form1, form2 ], [ [ elmt1ofForm1, elmt2ofForm2 ], [ elmtofForm2 ] ] ]
+ */
+
+/**
+ * test0a and test0b are testing the regular behavior of form ownership.
+ */
+function test0a(aForms, aElements)
+{
+ // <form><element></form>
+ // <form><element></form>
+ aForms[0].appendChild(aElements[0]);
+ aForms[1].appendChild(aElements[1]);
+
+ return [[aForms[0],aForms[1]],[[aElements[0]],[aElements[1]]]];
+}
+
+function test0b(aForms, aElements)
+{
+ // <form><element><form><element></form></form>
+ aForms[0].appendChild(aElements[0]);
+ aForms[0].appendChild(aForms[1]);
+ aForms[1].appendChild(aElements[1]);
+
+ return [[aForms[0],aForms[1]],[[aElements[0]],[aElements[1]]]];
+}
+
+/**
+ * This function test that, when an element is not a descendant of a form
+ * element and has @form set to a valid form id, it's form owner is the form
+ * which has the id.
+ */
+function test1(aForms, aElements)
+{
+ // <form id='f'></form><element id='f'>
+ aForms[0].id = 'f';
+ aElements[0].setAttribute('form', 'f');
+
+ return [[aForms[0]], [[aElements[0]]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a valid form id (not it's descendant), it's form
+ * owner is the form which has the id.
+ */
+function test2(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+
+ return [[aForms[0], aForms[1]], [[aElements[0]],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a valid form id (not it's descendant), then the
+ * form attribute is removed, it does not have a form owner.
+ */
+function test3(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+ aElements[0].removeAttribute('form');
+
+ return [[aForms[0], aForms[1]], [[],[aElements[0]]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a valid form id (not it's descendant), then the
+ * form's id attribute is removed, it does not have a form owner.
+ */
+function test4(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+ aForms[0].removeAttribute('id');
+
+ return [[aForms[0], aForms[1]], [[],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to an invalid form id, then it does not have a form
+ * owner.
+ */
+function test5(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='foo'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'foo');
+
+ return [[aForms[0], aForms[1]], [[],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a valid form id (not it's descendant), then the
+ * form id attribute is changed to an invalid id, it does not have a form owner.
+ */
+function test6(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+ aElements[0].setAttribute('form', 'foo');
+
+ return [[aForms[0], aForms[1]], [[],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to an invalid form id, then the form id attribute
+ * is changed to a valid form id, it's form owner is the form which has this id.
+ */
+function test7(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='foo'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'foo');
+ aElements[0].setAttribute('form', 'f');
+
+ return [[aForms[0], aForms[1]], [[aElements[0]],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a list of ids containing one valid form, then
+ * it does not have a form owner.
+ */
+function test8(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f foo'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f foo');
+
+ return [[aForms[0], aForms[1]], [[],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a form id which is valid in a case insensitive
+ * way, then it does not have a form owner.
+ */
+function test9(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='F'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'F');
+
+ return [[aForms[0], aForms[1]], [[],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a form id which is not a valid id, then it's
+ * form owner is it does not have a form owner.
+ */
+function test10(aForms, aElements)
+{
+ // <form id='F'></form><form><element form='f'></form>
+ aForms[0].id = 'F';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+
+ return [[aForms[0], aForms[1]], [[],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a form id which is not a valid id, then it's
+ * form owner is it does not have a form owner.
+ */
+function test11(aForms, aElements)
+{
+ // <form id='foo bar'></form><form><element form='foo bar'></form>
+ aForms[0].id = 'foo bar';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'foo bar');
+
+ return [[aForms[0], aForms[1]], [[aElements[0]],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a valid form id and the form id change, then
+ * it does not have a form owner.
+ */
+function test12(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+ aForms[0].id = 'foo';
+
+ return [[aForms[0], aForms[1]], [[],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to an invalid form id and the form id change to a
+ * valid one, then it's form owner is the form which has the id.
+ */
+function test13(aForms, aElements)
+{
+ // <form id='foo'></form><form><element form='f'></form>
+ aForms[0].id = 'foo';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+ aForms[0].id = 'f';
+
+ return [[aForms[0], aForms[1]], [[aElements[0]],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a valid form id and a form with the same id is
+ * inserted before in the tree, then it's form owner is the form which has the
+ * id.
+ */
+function test14(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+ aForms[2].id = 'f';
+
+ document.getElementById('content').insertBefore(aForms[2], aForms[0]);
+
+ return [[aForms[0], aForms[1], aForms[2]], [[],[],[aElements[0]]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a valid form id and an element with the same id is
+ * inserted before in the tree, then it does not have a form owner.
+ */
+function test15(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+ aElements[1].id = 'f';
+
+ document.getElementById('content').insertBefore(aElements[1], aForms[0]);
+
+ return [[aForms[0], aForms[1]], [[],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form
+ * element and has @form set to a valid form id and the form is removed from
+ * the tree, then it does not have a form owner.
+ */
+function test16(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+ aElements[1].id = 'f';
+
+ document.getElementById('content').removeChild(aForms[0]);
+
+ return [[aForms[0], aForms[1]], [[],[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form element
+ * and has @form set to the empty string, it does not have a form owner.
+ */
+function test17(aForms, aElements)
+{
+ // <form><element form=''></form>
+ aForms[0].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', '');
+
+ return [[aForms[0]], [[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form element
+ * and has @form set to the empty string, it does not have a form owner even if
+ * it's parent has its id equals to the empty string.
+ */
+function test18(aForms, aElements)
+{
+ // <form id=''><element form=''></form>
+ aForms[0].id = '';
+ aForms[0].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', '');
+
+ return [[aForms[0]], [[]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form element
+ * and has @form set to a valid form id and the element is being moving inside
+ * it's parent, it's form owner will remain the form with the id.
+ */
+function test19(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f'><element></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aForms[1].appendChild(aElements[1]);
+ aElements[0].setAttribute('form', 'f');
+ aForms[1].appendChild(aElements[0]);
+
+ return [[aForms[0],aForms[1]],[[aElements[0]],[aElements[1]]]];
+}
+
+/**
+ * This function test that, when an element is a descendant of a form element
+ * and has @form set to a valid form id and the element is being moving inside
+ * another form, it's form owner will remain the form with the id.
+ */
+function test20(aForms, aElements)
+{
+ // <form id='f'></form><form><element form='f'><element></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aForms[1].appendChild(aElements[1]);
+ aElements[0].setAttribute('form', 'f');
+ aForms[2].appendChild(aElements[0]);
+
+ return [[aForms[0],aForms[1],aForms[2]],[[aElements[0]],[aElements[1]],[]]];
+}
+
+/**
+ * This function test that when removing a form, the elements with a @form set
+ * will be correctly removed from there form owner.
+ */
+function test21(aForms, aElements)
+{
+ // <form id='f'><form><form><element form='f'></form>
+ aForms[0].id = 'f';
+ aForms[1].appendChild(aElements[0]);
+ aElements[0].setAttribute('form', 'f');
+ document.getElementById('content').removeChild(aForms[1]);
+
+ return [[aForms[0]],[[]]];
+}
+
+var functions = [
+ test0a, test0b,
+ test1, test2, test3, test4, test5, test6, test7, test8, test9,
+ test10, test11, test12, test13, test14, test15, test16, test17, test18, test19,
+ test20, test21,
+];
+
+// Global variable to have an easy access to <div id='content'>.
+var content = document.getElementById('content');
+
+// Initializing the needed elements.
+var forms = [
+ document.createElement('form'),
+ document.createElement('form'),
+ document.createElement('form'),
+];
+
+var elementNames = [
+ 'button', 'fieldset', 'input', 'label', 'object', 'output', 'select',
+ 'textarea'
+];
+
+var todoElements = [
+ ['keygen', 'Keygen'],
+];
+
+for (var e of todoElements) {
+ var node = document.createElement(e[0]);
+ var nodeString = HTMLElement.prototype.toString.apply(node);
+ nodeString = nodeString.replace(/Element[\] ].*/, "Element");
+ todo_is(nodeString, "[object HTML" + e[1] + "Element",
+ e[0] + " should not be implemented");
+}
+
+for (var name of elementNames) {
+ var elements = [
+ document.createElement(name),
+ document.createElement(name),
+ ];
+
+ for (var func of functions) {
+ // Clean-up.
+ while (content.firstChild) {
+ content.removeChild(content.firstChild);
+ }
+ for (form of forms) {
+ content.appendChild(form);
+ form.removeAttribute('id');
+ }
+ for (e of elements) {
+ content.appendChild(e);
+ e.removeAttribute('form');
+ is(e.form, null, "The element should not have a form owner");
+ }
+
+ // Calling the test.
+ var results = func(forms, elements);
+
+ // Checking the results.
+ var formsList = results[0];
+ for (var i=0; i<formsList.length; ++i) {
+ var elementsList = results[1][i];
+ if (name != 'label' && name != 'meter' && name != 'progress') {
+ is(formsList[i].elements.length, elementsList.length,
+ "The form should contain " + elementsList.length + " elements");
+ }
+ for (var j=0; j<elementsList.length; ++j) {
+ if (name != 'label' && name != 'meter' && name != 'progress') {
+ is(formsList[i].elements[j], elementsList[j],
+ "The form should contain " + elementsList[j]);
+ }
+ if (name != 'label') {
+ is(elementsList[j].form, formsList[i],
+ "The form owner should be the form associated to the list");
+ }
+ }
+ }
+ }
+
+ // Cleaning-up.
+ for (e of elements) {
+ e.parentNode.removeChild(e);
+ e = null;
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_form_attribute-2.html b/dom/html/test/forms/test_form_attribute-2.html
new file mode 100644
index 000000000..96c706b3a
--- /dev/null
+++ b/dom/html/test/forms/test_form_attribute-2.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=588683
+-->
+<head>
+ <title>Test for form attributes 2</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=588683">Mozilla Bug 588683</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <form id='a'>
+ <form id='b'>
+ <input id='i' form='b'>
+ <script>
+ is(document.getElementById('i').form, document.getElementById('b'),
+ "While parsing, the form property should work.");
+ </script>
+ </form>
+ </form>
+ <form id='c'>
+ <form id='d'>
+ <input id='i2' form='c'>
+ <script>
+ is(document.getElementById('i2').form, document.getElementById('c'),
+ "While parsing, the form property should work.");
+ </script>
+ </form>
+ </form>
+ <!-- Let's tests without @form -->
+ <form id='e'>
+ <form id='f'>
+ <input id='i3'>
+ <script>
+ // bug 589073
+ todo_is(document.getElementById('i3').form, document.getElementById('f'),
+ "While parsing, the form property should work.");
+ </script>
+ </form>
+ </form>
+ <form id='g'>
+ <input id='i4'>
+ <script>
+ is(document.getElementById('i4').form, document.getElementById('g'),
+ "While parsing, the form property should work.");
+ </script>
+ </form>
+</div>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_form_attribute-3.html b/dom/html/test/forms/test_form_attribute-3.html
new file mode 100644
index 000000000..a8d4fabef
--- /dev/null
+++ b/dom/html/test/forms/test_form_attribute-3.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=588683
+-->
+<head>
+ <title>Test for form attributes 3</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=588683">Mozilla Bug 588683</a>
+<p id="display"></p>
+<div id="content">
+ <form id='f'>
+ <input name='e1'>
+ </form>
+ <form id='f2'>
+ <input name='e2'>
+ <input id='i3' form='f'
+ onfocus="var catched=false;
+ try { e1; } catch(e) { catched=true; }
+ ok(!catched, 'e1 should be in the scope of i3');
+ catched = false;
+ try { e2; } catch(e) { catched=true; }
+ ok(catched, 'e2 should not be in the scope of i3');
+ document.getElementById('i4').focus();"
+ >
+ <input id='i4' form='f2'
+ onfocus="var catched=false;
+ try { e2; } catch(e) { catched=true; }
+ ok(!catched, 'e2 should be in the scope of i4');
+ document.getElementById('i5').focus();"
+ >
+ <input id='i5'
+ onfocus="var catched=false;
+ try { e2; } catch(e) { catched=true; }
+ ok(!catched, 'e2 should be in the scope of i5');
+ document.getElementById('i6').focus();"
+ >
+ </form>
+ <input id='i6' form='f'
+ onfocus="var catched=false;
+ try { e1; } catch(e) { catched=true; }
+ ok(!catched, 'e1 should be in the scope of i6');
+ document.getElementById('i7').focus();"
+ >
+ <input id='i7' form='f2'
+ onfocus="var catched=false;
+ try { e2; } catch(e) { catched=true; }
+ ok(!catched, 'e2 should be in the scope of i7');
+ this.blur();
+ SimpleTest.finish();"
+ >
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for form attributes 3 **/
+
+SimpleTest.waitForExplicitFinish();
+
+document.getElementById('i3').focus();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_form_attribute-4.html b/dom/html/test/forms/test_form_attribute-4.html
new file mode 100644
index 000000000..67484f72e
--- /dev/null
+++ b/dom/html/test/forms/test_form_attribute-4.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=588683
+-->
+<head>
+ <title>Test for form attributes 4</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=588683">Mozilla Bug 588683</a>
+<p id="display"></p>
+<div id="content" style='display:none;'>
+ <form id='f'>
+ </form>
+ <table id='t'>
+ <form id='f2'>
+ <tr><td><input id='i1'></td></tr>
+ <tr><td><input id='i2' form='f'></td></tr>
+ </form>
+ </table>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for form attributes 4 **/
+
+var table = document.getElementById('t');
+var i1 = document.getElementById('i1');
+var i2 = document.getElementById('i2');
+
+is(i1.form, document.getElementById('f2'),
+ "i1 form should be it's parent");
+is(i2.form, document.getElementById('f'),
+ "i1 form should be the form with the id in @form");
+
+table.removeChild(document.getElementById('f2'));
+is(i1, document.getElementById('i1'),
+ "i1 should still be in the document");
+is(i1.form, null, "i1 should not have any form owner");
+is(i2.form, document.getElementById('f'),
+ "i1 form should be the form with the id in @form");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_form_attributes_reflection.html b/dom/html/test/forms/test_form_attributes_reflection.html
new file mode 100644
index 000000000..0c64ac4ea
--- /dev/null
+++ b/dom/html/test/forms/test_form_attributes_reflection.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLFormElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="../reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLFormElement attributes reflection **/
+
+// .acceptCharset
+reflectString({
+ element: document.createElement("form"),
+ attribute: { idl: "acceptCharset", content: "accept-charset" },
+ otherValues: [ "ISO-8859-1", "UTF-8" ],
+});
+
+// TODO: action (URL). But note that we currently reflect it weirdly; see
+// dom/html/test/test_bug607145.html
+
+// .autocomplete
+reflectLimitedEnumerated({
+ element: document.createElement("form"),
+ attribute: "autocomplete",
+ validValues: [ "on", "off" ],
+ invalidValues: [ "", "foo", "tulip", "default" ],
+ defaultValue: "on",
+});
+
+// .enctype
+reflectLimitedEnumerated({
+ element: document.createElement("form"),
+ attribute: "enctype",
+ validValues: [ "application/x-www-form-urlencoded", "multipart/form-data",
+ "text/plain" ],
+ invalidValues: [ "", "foo", "tulip", "multipart/foo" ],
+ defaultValue: "application/x-www-form-urlencoded"
+});
+
+// .encoding
+reflectLimitedEnumerated({
+ element: document.createElement("form"),
+ attribute: { idl: "encoding", content: "enctype" },
+ validValues: [ "application/x-www-form-urlencoded", "multipart/form-data",
+ "text/plain" ],
+ invalidValues: [ "", "foo", "tulip", "multipart/foo" ],
+ defaultValue: "application/x-www-form-urlencoded"
+});
+
+// .method
+reflectLimitedEnumerated({
+ element: document.createElement("form"),
+ attribute: "method",
+ validValues: [ "get", "post" ],
+ invalidValues: [ "", "foo", "tulip" ],
+ defaultValue: "get"
+});
+
+// .name
+reflectString({
+ element: document.createElement("form"),
+ attribute: "name",
+});
+
+// .noValidate
+reflectBoolean({
+ element: document.createElement("form"),
+ attribute: "noValidate",
+});
+
+// .target
+reflectString({
+ element: document.createElement("form"),
+ attribute: "target",
+ otherValues: [ "_blank", "_self", "_parent", "_top" ],
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_form_named_getter_dynamic.html b/dom/html/test/forms/test_form_named_getter_dynamic.html
new file mode 100644
index 000000000..4a1976845
--- /dev/null
+++ b/dom/html/test/forms/test_form_named_getter_dynamic.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=377413
+-->
+<head>
+ <title>Test for Bug 377413</title>
+ <script type="text/javascript" src="/resources/testharness.js"></script>
+ <link rel='stylesheet' href='/resources/testharness.css'>
+ <script type="text/javascript" src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=377413">Mozilla Bug 377413</a>
+<p id="log"></p>
+<div id="content">
+ <form>
+ <table>
+ <tbody>
+ </tbody>
+ </table>
+ </form>
+</div>
+
+<script type="text/javascript">
+
+/** Tests for Bug 377413 **/
+var tb = document.getElementsByTagName('tbody')[0];
+
+test(function(){
+ tb.innerHTML = '<tr><td><input name="fooboo"></td></tr>';
+ document.forms[0].fooboo.value = 'testme';
+ document.getElementsByTagName('table')[0].deleteRow(0);
+ assert_equals(document.forms[0].fooboo, undefined);
+}, "no element reference after deleting it with deleteRow()");
+
+test(function(){
+ var b = tb.appendChild(document.createElement('tr')).appendChild(document.createElement('td')).appendChild(document.createElement('button'));
+ b.name = b.value = 'boofoo';
+ assert_equals(document.forms[0].elements[0].value, 'boofoo');
+}, 'element value set correctly');
+
+test(function(){
+ assert_true('boofoo' in document.forms[0]);
+}, 'element name has created property on form');
+
+test(function(){
+ tb.innerHTML = '';
+ assert_false('boofoo' in document.forms[0]);
+}, "no element reference after deleting it by setting innerHTML");
+
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_formaction_attribute.html b/dom/html/test/forms/test_formaction_attribute.html
new file mode 100644
index 000000000..24af8b2db
--- /dev/null
+++ b/dom/html/test/forms/test_formaction_attribute.html
@@ -0,0 +1,176 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=566160
+-->
+<head>
+ <title>Test for Bug 566160</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566160">Mozilla Bug 566160</a>
+<p id="display"></p>
+<style>
+ iframe { width: 130px; height: 100px;}
+</style>
+<iframe name='frame1' id='frame1'></iframe>
+<iframe name='frame2' id='frame2'></iframe>
+<iframe name='frame3' id='frame3'></iframe>
+<iframe name='frame3bis' id='frame3bis'></iframe>
+<iframe name='frame4' id='frame4'></iframe>
+<iframe name='frame5' id='frame5'></iframe>
+<iframe name='frame6' id='frame6'></iframe>
+<iframe name='frame7' id='frame7'></iframe>
+<div id="content">
+ <!-- submit controls with formaction that are validated with a CLICK -->
+ <form target="frame1" action="data:text/html,FAIL" method="GET">
+ <input name='foo' value='foo'>
+ <input type='submit' id='is' formaction="data:text/html,">
+ </form>
+ <form target="frame2" action="data:text/html,FAIL" method="GET">
+ <input name='bar' value='bar'>
+ <input type='image' id='ii' formaction="data:text/html,">
+ </form>
+ <form target="frame3" action="data:text/html,FAIL" method="GET">
+ <input name='tulip' value='tulip'>
+ <button type='submit' id='bs' formaction="data:text/html,">submit</button>
+ </form>
+ <form target="frame3bis" action="data:text/html,FAIL" method="GET">
+ <input name='tulipbis' value='tulipbis'>
+ <button type='submit' id='bsbis' formaction="data:text/html,">submit</button>
+ </form>
+
+ <!-- submit controls with formaction that are validated with ENTER -->
+ <form target="frame4" action="data:text/html,FAIL" method="GET">
+ <input name='footulip' value='footulip'>
+ <input type='submit' id='is2' formaction="data:text/html,">
+ </form>
+ <form target="frame5" action="data:text/html,FAIL" method="GET">
+ <input name='foobar' value='foobar'>
+ <input type='image' id='ii2' formaction="data:text/html,">
+ </form>
+ <form target="frame6" action="data:text/html,FAIL" method="GET">
+ <input name='tulip2' value='tulip2'>
+ <button type='submit' id='bs2' formaction="data:text/html,">submit</button>
+ </form>
+
+ <!-- check that when submitting a from from an element
+ which is not a submit control, @formaction isn't used -->
+ <form target='frame7' action="data:text/html," method="GET">
+ <input id='enter' name='input' value='enter' formaction="data:text/html,FAIL">
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 566160 **/
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+var gTestResults = {
+ frame1: "data:text/html,?foo=foo",
+ frame2: "data:text/html,?bar=bar&x=0&y=0",
+ frame3: "data:text/html,?tulip=tulip",
+ frame3bis: "data:text/html,?tulipbis=tulipbis",
+ frame4: "data:text/html,?footulip=footulip",
+ frame5: "data:text/html,?foobar=foobar&x=0&y=0",
+ frame6: "data:text/html,?tulip2=tulip2",
+ frame7: "data:text/html,?input=enter",
+};
+
+var gPendingLoad = 0; // Has to be set after depending on the frames number.
+
+function runTests()
+{
+ // We add a load event for the frames which will be called when the forms
+ // will be submitted.
+ var frames = [ document.getElementById('frame1'),
+ document.getElementById('frame2'),
+ document.getElementById('frame3'),
+ document.getElementById('frame3bis'),
+ document.getElementById('frame4'),
+ document.getElementById('frame5'),
+ document.getElementById('frame6'),
+ document.getElementById('frame7'),
+ ];
+ gPendingLoad = frames.length;
+
+ for (var i=0; i<frames.length; i++) {
+ frames[i].setAttribute('onload', "frameLoaded(this);");
+ }
+
+ /**
+ * We are going to focus each element before interacting with either for
+ * simulating the ENTER key (synthesizeKey) or a click (synthesizeMouse) or
+ * using .click(). This because it may be needed (ENTER) and because we want
+ * to have the element visible in the iframe.
+ *
+ * Focusing the first element (id='is') is launching the tests.
+ */
+ document.getElementById('is').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('is'), 5, 5, {});
+ document.getElementById('ii').focus();
+ }, false);
+
+ document.getElementById('ii').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('ii'), 5, 5, {});
+ document.getElementById('bs').focus();
+ }, false);
+
+ document.getElementById('bs').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('bs'), 5, 5, {});
+ document.getElementById('bsbis').focus();
+ }, false);
+
+ document.getElementById('bsbis').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ document.getElementById('bsbis').click();
+ document.getElementById('is2').focus();
+ }, false);
+
+ document.getElementById('is2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('ii2').focus();
+ }, false);
+
+ document.getElementById('ii2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('bs2').focus();
+ }, false);
+
+ document.getElementById('bs2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('enter').focus();
+ }, false);
+
+ document.getElementById('enter').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ }, false);
+
+ document.getElementById('is').focus();
+}
+
+function frameLoaded(aFrame) {
+ // Check if formaction/action has the correct behavior.
+ is(aFrame.contentWindow.location.href, gTestResults[aFrame.name],
+ "the action attribute doesn't have the correct behavior");
+
+ if (--gPendingLoad == 0) {
+ SimpleTest.finish();
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_formnovalidate_attribute.html b/dom/html/test/forms/test_formnovalidate_attribute.html
new file mode 100644
index 000000000..067060a5c
--- /dev/null
+++ b/dom/html/test/forms/test_formnovalidate_attribute.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=589696
+-->
+<head>
+ <title>Test for Bug 589696</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=589696">Mozilla Bug 589696</a>
+<p id="display"></p>
+<iframe style='width:50px; height: 50px;' name='t'></iframe>
+<div id="content">
+ <!-- Next forms should not submit because formnovalidate isn't set on the
+ element used for the submission. -->
+ <form target='t' action='data:text/html,'>
+ <input id='av' required>
+ <input type='submit' formnovalidate>
+ <input id='a' type='submit'>
+ </form>
+ <form target='t' action='data:text/html,'>
+ <input id='bv' type='checkbox' required>
+ <button type='submit' formnovalidate></button>
+ <button id='b' type='submit'></button>
+ </form>
+ <!-- Next form should not submit because formnovalidate only applies for
+ submit controls. -->
+ <form target='t' action='data:text/html,'>
+ <input id='c' required formnovalidate>
+ </form>
+ <!--- Next forms should submit without any validation check. -->
+ <form target='t' action='data:text/html,'>
+ <input id='dv' required>
+ <input id='d' type='submit' formnovalidate>
+ </form>
+ <form target='t' action='data:text/html,'>
+ <input id='ev' type='checkbox' required>
+ <button id='e' type='submit' formnovalidate></button>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 589696 **/
+
+var os = SpecialPowers.Cc['@mozilla.org/observer-service;1']
+ .getService(SpecialPowers.Ci.nsIObserverService);
+var observers = os.enumerateObservers("invalidformsubmit");
+
+/**
+ * formnovalidate should prevent form validation if set on the submit control
+ * used to submit the form.
+ *
+ * The following test should not be done if there is no observer for
+ * "invalidformsubmit" because the form submission will not be canceled in that
+ * case.
+ */
+
+if (observers.hasMoreElements()) {
+ document.getElementById('av').addEventListener("invalid", function(aEvent) {
+ aEvent.target.removeAttribute("invalid", arguments.callee, false);
+ ok(true, "formnovalidate should not apply on if not set on the submit " +
+ "control used for the submission");
+ document.getElementById('b').click();
+ }, false);
+
+ document.getElementById('bv').addEventListener("invalid", function(aEvent) {
+ aEvent.target.removeAttribute("invalid", arguments.callee, false);
+ ok(true, "formnovalidate should not apply on if not set on the submit " +
+ "control used for the submission");
+ var c = document.getElementById('c');
+ c.focus();
+ synthesizeKey("KEY_Enter", { code: "Enter" });
+ }, false);
+
+ document.getElementById('c').addEventListener("invalid", function(aEvent) {
+ aEvent.target.removeAttribute("invalid", arguments.callee, false);
+ ok(true, "formnovalidate should only apply on submit controls");
+ document.getElementById('d').click();
+ }, false);
+
+ document.forms[3].addEventListener("submit", function(aEvent) {
+ aEvent.target.removeAttribute("submit", arguments.callee, false);
+ ok(true, "formnovalidate applies if set on the submit control used for the submission");
+ document.getElementById('e').click();
+ }, false);
+
+ document.forms[4].addEventListener("submit", function(aEvent) {
+ aEvent.target.removeAttribute("submit", arguments.callee, false);
+ ok(true, "formnovalidate applies if set on the submit control used for the submission");
+ SimpleTest.executeSoon(SimpleTest.finish);
+ }, false);
+
+ /**
+ * We have to be sure invalid events behave as expected.
+ * They should be sent before the submit event so we can just create a test
+ * failure if we got one when unexpected. All of them should be caught if
+ * sent.
+ * At worst, we got random green which isn't harmful.
+ * If expected, they will be part of the chain reaction.
+ */
+ function unexpectedInvalid(aEvent)
+ {
+ aEvent.target.removeAttribute("invalid", unexpectedInvalid, false);
+ ok(false, "invalid event should not be sent");
+ }
+
+ document.getElementById('dv').addEventListener("invalid", unexpectedInvalid, false);
+ document.getElementById('ev').addEventListener("invalid", unexpectedInvalid, false);
+
+ /**
+ * Some submission have to be canceled. In that case, the submit events should
+ * not be sent.
+ * Same behavior as unexpected invalid events.
+ */
+ function unexpectedSubmit(aEvent)
+ {
+ aEvent.target.removeAttribute("submit", unexpectedSubmit, false);
+ ok(false, "submit event should not be sent");
+ }
+
+ document.forms[0].addEventListener("submit", unexpectedSubmit, false);
+ document.forms[1].addEventListener("submit", unexpectedSubmit, false);
+ document.forms[2].addEventListener("submit", unexpectedSubmit, false);
+
+ SimpleTest.waitForExplicitFinish();
+
+ // This is going to call all the tests (with a chain reaction).
+ SimpleTest.waitForFocus(function() {
+ document.getElementById('a').click();
+ });
+} else {
+ todo(false, "No 'invalidformsubmit' observers. Skip test.");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_attributes_reflection.html b/dom/html/test/forms/test_input_attributes_reflection.html
new file mode 100644
index 000000000..6a0eaf225
--- /dev/null
+++ b/dom/html/test/forms/test_input_attributes_reflection.html
@@ -0,0 +1,275 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLInputElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="../reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLInputElement attributes reflection **/
+
+// TODO: maybe make those reflections be tested against all input types.
+
+function testWidthHeight(attr) {
+ var element = document.createElement('input');
+ is(element[attr], 0, attr + ' always returns 0 if not type=image');
+ element.setAttribute(attr, '42');
+ is(element[attr], 0, attr + ' always returns 0 if not type=image');
+ is(element.getAttribute(attr), '42');
+ element[attr] = 0;
+ is(element.getAttribute(attr), '0', 'setting ' + attr + ' changes the content attribute');
+ element[attr] = 12;
+ is(element.getAttribute(attr), '12', 'setting ' + attr + ' changes the content attribute');
+
+ element.removeAttribute(attr);
+ is(element.getAttribute(attr), null);
+
+ element = document.createElement('input');
+ element.type = 'image';
+ document.getElementById('content').appendChild(element);
+ isnot(element[attr], 0, attr + ' represents the dimension of the element if type=image');
+
+ element.setAttribute(attr, '42');
+ isnot(element[attr], 0, attr + ' represents the dimension of the element if type=image');
+ isnot(element[attr], 42, attr + ' represents the dimension of the element if type=image');
+ is(element.getAttribute(attr), '42');
+ element[attr] = 0;
+ is(element.getAttribute(attr), '0', 'setting ' + attr + ' changes the content attribute');
+ element[attr] = 12;
+ is(element.getAttribute(attr), '12', 'setting ' + attr + ' changes the content attribute');
+
+ element.removeAttribute(attr);
+ is(element.getAttribute(attr), null);
+}
+
+// .accept
+reflectString({
+ element: document.createElement("input"),
+ attribute: "accept",
+ otherValues: [ "audio/*", "video/*", "image/*", "image/png",
+ "application/msword", "appplication/pdf" ],
+});
+
+// .alt
+reflectString({
+ element: document.createElement("input"),
+ attribute: "alt",
+});
+
+// .autocomplete
+reflectLimitedEnumerated({
+ element: document.createElement("input"),
+ attribute: "autocomplete",
+ validValues: [ "on", "off" ],
+ invalidValues: [ "", "default", "foo", "tulip" ],
+});
+
+// .autofocus
+reflectBoolean({
+ element: document.createElement("input"),
+ attribute: "autofocus",
+});
+
+// .defaultChecked
+reflectBoolean({
+ element: document.createElement("input"),
+ attribute: { idl: "defaultChecked", content: "checked" },
+});
+
+// .checked doesn't reflect a content attribute.
+
+// .dirName
+todo("dirName" in document.createElement("input"),
+ "dirName isn't implemented yet");
+
+// .disabled
+reflectBoolean({
+ element: document.createElement("input"),
+ attribute: "disabled",
+});
+
+// TODO: form (HTMLFormElement)
+// TODO: files (FileList)
+// TODO: formAction (URL). But note that we currently reflect it weirdly; see
+// dom/html/test/test_bug607145.html
+
+// .formEnctype
+reflectLimitedEnumerated({
+ element: document.createElement("input"),
+ attribute: "formEnctype",
+ validValues: [ "application/x-www-form-urlencoded", "multipart/form-data",
+ "text/plain" ],
+ invalidValues: [ "", "foo", "tulip", "multipart/foo" ],
+ defaultValue: { invalid: "application/x-www-form-urlencoded", missing: "" }
+});
+
+// .formMethod
+reflectLimitedEnumerated({
+ element: document.createElement("input"),
+ attribute: "formMethod",
+ validValues: [ "get", "post" ],
+ invalidValues: [ "", "foo", "tulip" ],
+ defaultValue: { invalid: "get", missing: "" }
+});
+
+// .formNoValidate
+reflectBoolean({
+ element: document.createElement("input"),
+ attribute: "formNoValidate",
+});
+
+// .formTarget
+reflectString({
+ element: document.createElement("input"),
+ attribute: "formTarget",
+ otherValues: [ "_blank", "_self", "_parent", "_top" ],
+});
+
+// .height
+testWidthHeight('height');
+
+// .indeterminate doesn't reflect a content attribute.
+
+// .inputmode
+if (SpecialPowers.getBoolPref("dom.forms.inputmode")) {
+reflectLimitedEnumerated({
+ element: document.createElement("input"),
+ attribute: "inputMode",
+ validValues: [ "numeric", "digit", "uppercase", "lowercase", "titlecase", "autocapitalized", "auto" ],
+ invalidValues: [ "", "foo", "tulip" ],
+ defaultValue: "auto"
+});
+}
+
+// TODO: list (HTMLElement)
+
+// .max
+reflectString({
+ element: document.createElement('input'),
+ attribute: 'max',
+});
+
+// .maxLength
+reflectInt({
+ element: document.createElement("input"),
+ attribute: "maxLength",
+ nonNegative: true,
+});
+
+// .min
+reflectString({
+ element: document.createElement('input'),
+ attribute: 'min',
+});
+
+// .multiple
+reflectBoolean({
+ element: document.createElement("input"),
+ attribute: "multiple",
+});
+
+// .name
+reflectString({
+ element: document.createElement("input"),
+ attribute: "name",
+ otherValues: [ "isindex", "_charset_" ],
+});
+
+// .pattern
+reflectString({
+ element: document.createElement("input"),
+ attribute: "pattern",
+ otherValues: [ "[0-9][A-Z]{3}" ],
+});
+
+// .placeholder
+reflectString({
+ element: document.createElement("input"),
+ attribute: "placeholder",
+ otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ],
+});
+
+// .readOnly
+reflectBoolean({
+ element: document.createElement("input"),
+ attribute: "readOnly",
+});
+
+// .required
+reflectBoolean({
+ element: document.createElement("input"),
+ attribute: "required",
+});
+
+// .size
+reflectUnsignedInt({
+ element: document.createElement("input"),
+ attribute: "size",
+ nonZero: true,
+ defaultValue: 20,
+});
+
+// .src (URL)
+reflectURL({
+ element: document.createElement('input'),
+ attribute: 'src',
+});
+
+// .step
+reflectString({
+ element: document.createElement('input'),
+ attribute: 'step',
+});
+
+// .type
+reflectLimitedEnumerated({
+ element: document.createElement("input"),
+ attribute: "type",
+ validValues: [ "hidden", "text", "search", "tel", "url", "email", "password",
+ "checkbox", "radio", "file", "submit", "image", "reset",
+ "button", "date", "time", "number", "range", "color", "month",
+ "week", "datetime-local" ],
+ invalidValues: [ "this-is-probably-a-wrong-type", "", "tulip" ],
+ defaultValue: "text"
+});
+
+// .defaultValue
+reflectString({
+ element: document.createElement("input"),
+ attribute: { idl: "defaultValue", content: "value" },
+ otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ],
+});
+
+// .value doesn't reflect a content attribute.
+
+// .valueAsDate
+is("valueAsDate" in document.createElement("input"), true,
+ "valueAsDate should be available");
+
+// Deeper check will be done with bug 763305.
+is('valueAsNumber' in document.createElement("input"), true,
+ "valueAsNumber should be available");
+
+// .selectedOption
+todo("selectedOption" in document.createElement("input"),
+ "selectedOption isn't implemented yet");
+
+// .width
+testWidthHeight('width');
+
+// .willValidate doesn't reflect a content attribute.
+// .validity doesn't reflect a content attribute.
+// .validationMessage doesn't reflect a content attribute.
+// .labels doesn't reflect a content attribute.
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_autocomplete.html b/dom/html/test/forms/test_input_autocomplete.html
new file mode 100644
index 000000000..2aaeac020
--- /dev/null
+++ b/dom/html/test/forms/test_input_autocomplete.html
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html>
+<!--
+Test @autocomplete on <input>
+-->
+<head>
+ <title>Test for &lt;input autocomplete='…'&gt;</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<script>
+"use strict";
+
+var values = [
+ // @autocomplete content attribute, expected IDL attribute value
+
+ // Missing or empty attribute
+ [undefined, ""],
+ ["", ""],
+
+ // One token
+ ["on", "on"],
+ ["On", "on"],
+ ["off", "off"],
+ ["OFF", "off"],
+ ["username", "username"],
+ [" username ", "username"],
+ ["foobar", ""],
+
+ // Two tokens
+ ["on off", ""],
+ ["off on", ""],
+ ["username tel", ""],
+ ["tel username ", ""],
+ [" username tel ", ""],
+ ["tel mobile", ""],
+ ["tel shipping", ""],
+ ["shipping tel", "shipping tel"],
+ ["shipPING tel", "shipping tel"],
+ ["mobile tel", "mobile tel"],
+ [" MoBiLe TeL ", "mobile tel"],
+ ["XXX tel", ""],
+ ["XXX username", ""],
+
+ // Three tokens
+ ["billing invalid tel", ""],
+ ["___ mobile tel", ""],
+ ["mobile foo tel", ""],
+ ["mobile tel foo", ""],
+ ["tel mobile billing", ""],
+ ["billing mobile tel", "billing mobile tel"],
+ [" BILLing MoBiLE tEl ", "billing mobile tel"],
+ ["billing home tel", "billing home tel"],
+
+ // Four tokens (invalid)
+ ["billing billing mobile tel", ""],
+
+ // Five tokens (invalid)
+ ["billing billing billing mobile tel", ""],
+];
+
+var types = [undefined, "hidden", "text", "search"]; // Valid types for all non-multiline hints.
+
+function checkAutocompleteValues(field, type) {
+ for (var test of values) {
+ if (typeof(test[0]) === "undefined")
+ field.removeAttribute("autocomplete");
+ else
+ field.setAttribute("autocomplete", test[0]);
+ is(field.autocomplete, test[1], "Checking @autocomplete for @type=" + type + " of: " + test[0]);
+ is(field.autocomplete, test[1], "Checking cached @autocomplete for @type=" + type + " of: " + test[0]);
+ }
+}
+
+function start() {
+ var inputField = document.getElementById("input-field");
+ for (var type of types) {
+ // Switch the input type
+ if (typeof(type) === "undefined")
+ inputField.removeAttribute("type");
+ else
+ inputField.type = type;
+ checkAutocompleteValues(inputField, type || "");
+ }
+
+ var selectField = document.getElementById("select-field");
+ checkAutocompleteValues(selectField, "select");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["dom.forms.autocomplete.experimental", true]]}, start);
+</script>
+</head>
+
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <form>
+ <input id="input-field" />
+ <select id="select-field" />
+ </form>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_color_input_change_events.html b/dom/html/test/forms/test_input_color_input_change_events.html
new file mode 100644
index 000000000..d9e7558f8
--- /dev/null
+++ b/dom/html/test/forms/test_input_color_input_change_events.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=885996
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1234567</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript;version=1.8">
+
+ /** Test that update() modifies the element value such as done() when it is
+ * not called as a concellation.
+ */
+
+ SimpleTest.waitForExplicitFinish();
+
+ var MockColorPicker = SpecialPowers.MockColorPicker;
+
+ var test = runTest();
+
+ SimpleTest.waitForFocus(function() {
+ test.next();
+ });
+
+ function runTest() {
+ MockColorPicker.init(window);
+ var element = null;
+
+ MockColorPicker.showCallback = function(picker, update) {
+ is(picker.initialColor, element.value);
+
+ var inputEvent = false;
+ var changeEvent = false;
+ element.oninput = function() {
+ inputEvent = true;
+ };
+ element.onchange = function() {
+ changeEvent = true;
+ };
+
+ if (element.dataset.type == 'update') {
+ update('#f00ba4');
+
+ is(inputEvent, true, 'input event should have been received');
+ is(changeEvent, false, 'change event should not have been received');
+
+ inputEvent = changeEvent = false;
+
+ is(element.value, '#f00ba4');
+
+ MockColorPicker.returnColor = '#f00ba7';
+ isnot(element.value, MockColorPicker.returnColor);
+ } else if (element.dataset.type == 'cancel') {
+ MockColorPicker.returnColor = '#bababa';
+ isnot(element.value, MockColorPicker.returnColor);
+ } else if (element.dataset.type == 'done') {
+ MockColorPicker.returnColor = '#098766';
+ isnot(element.value, MockColorPicker.returnColor);
+ } else if (element.dataset.type == 'noop-done') {
+ MockColorPicker.returnColor = element.value;
+ is(element.value, MockColorPicker.returnColor);
+ }
+
+ SimpleTest.executeSoon(function() {
+ if (element.dataset.type == 'cancel') {
+ isnot(element.value, MockColorPicker.returnColor);
+ is(inputEvent, false, 'no input event should have been sent');
+ is(changeEvent, false, 'no change event should have been sent');
+ } else if (element.dataset.type == 'noop-done') {
+ is(element.value, MockColorPicker.returnColor);
+ is(inputEvent, false, 'no input event should have been sent');
+ is(changeEvent, false, 'no change event should have been sent');
+ } else {
+ is(element.value, MockColorPicker.returnColor);
+ is(inputEvent, true, 'input event should have been sent');
+ is(changeEvent, true, 'change event should have been sent');
+ }
+
+ changeEvent = false;
+ element.blur();
+
+ setTimeout(function() {
+ is(changeEvent, false, "change event should not be fired on blur");
+ test.next();
+ });
+ });
+
+ return element.dataset.type == 'cancel' ? "" : MockColorPicker.returnColor;
+ };
+
+ for (var i = 0; i < document.getElementsByTagName('input').length; ++i) {
+ element = document.getElementsByTagName('input')[i];
+ element.focus();
+ synthesizeMouseAtCenter(element, {});
+ yield undefined;
+ };
+
+ MockColorPicker.cleanup();
+ SimpleTest.finish();
+ yield undefined;
+ }
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a>
+<p id="display"></p>
+<div id="content">
+ <input type='color' data-type='update'>
+ <input type='color' data-type='cancel'>
+ <input type='color' data-type='done'>
+ <input type='color' data-type='noop-done'>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_color_picker_initial.html b/dom/html/test/forms/test_input_color_picker_initial.html
new file mode 100644
index 000000000..4b6a45cbb
--- /dev/null
+++ b/dom/html/test/forms/test_input_color_picker_initial.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=885996
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1234567</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript;version=1.8">
+
+ /** Test that the initial value of the nsIColorPicker is the current value of
+ the <input type='color'> element. **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ var MockColorPicker = SpecialPowers.MockColorPicker;
+
+ var test = runTest();
+
+ SimpleTest.waitForFocus(function() {
+ test.next();
+ });
+
+ function runTest() {
+ MockColorPicker.init(window);
+ var element = null;
+
+ MockColorPicker.showCallback = function(picker) {
+ is(picker.initialColor, element.value);
+ SimpleTest.executeSoon(function() {
+ test.next();
+ });
+ return "";
+ };
+
+ for (var i = 0; i < document.getElementsByTagName('input').length; ++i) {
+ element = document.getElementsByTagName('input')[i];
+ if (element.parentElement.id === 'dynamic-values') {
+ element.value = '#deadbe';
+ }
+ synthesizeMouseAtCenter(element, {});
+ yield undefined;
+ };
+
+ MockColorPicker.cleanup();
+ SimpleTest.finish();
+ yield undefined;
+ }
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a>
+<p id="display"></p>
+<div id="content">
+ <div id='valid-values'>
+ <input type='color' value='#ff00ff'>
+ <input type='color' value='#ab3275'>
+ <input type='color' value='#abcdef'>
+ <input type='color' value='#ABCDEF'>
+ </div>
+ <div id='invalid-values'>
+ <input type='color' value='ffffff'>
+ <input type='color' value='#abcdez'>
+ <input type='color' value='#0123456'>
+ </div>
+ <div id='dynamic-values'>
+ <input type='color' value='#ab4594'>
+ <input type='color' value='#984534'>
+ <input type='color' value='#f8b9a0'>
+ </div>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_color_picker_popup.html b/dom/html/test/forms/test_input_color_picker_popup.html
new file mode 100644
index 000000000..239f14014
--- /dev/null
+++ b/dom/html/test/forms/test_input_color_picker_popup.html
@@ -0,0 +1,140 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=885996
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1234567</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style> body { font-family: serif } </style>
+ <script type="application/javascript;version=1.8">
+
+ /** Test the behaviour of the <input type='color'> when clicking on it from
+ different ways. **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ var MockColorPicker = SpecialPowers.MockColorPicker;
+
+ var test = runTest();
+ var testData = [
+ { id: 'normal', result: true },
+ { id: 'hidden', result: false },
+ { id: 'normal', type: 'untrusted', result: true },
+ { id: 'normal', type: 'prevent-default-1', result: false },
+ { id: 'normal', type: 'prevent-default-2', result: false },
+ { id: 'normal', type: 'click-method', result: true },
+ { id: 'normal', type: 'right-click', result: false },
+ { id: 'normal', type: 'middle-click', result: false },
+ { id: 'label-1', result: true },
+ { id: 'label-2', result: true },
+ { id: 'label-3', result: true },
+ { id: 'label-4', result: true },
+ { id: 'button-click', result: true },
+ { id: 'button-down', result: true },
+ { id: 'button-up', result: true },
+ { id: 'div-click', result: true },
+ { id: 'div-click-on-demand', result: true },
+ ];
+ var currentTest = null;
+
+ SimpleTest.waitForFocus(function() {
+ test.next();
+ });
+
+ function runTest() {
+ MockColorPicker.init(window);
+ var element = null;
+
+ MockColorPicker.showCallback = function(picker) {
+ ok(currentTest.result);
+ SimpleTest.executeSoon(function() {
+ test.next();
+ });
+ return "";
+ };
+
+ while (testData.length != 0) {
+ var currentTest = testData.shift();
+ element = document.getElementById(currentTest.id);
+
+ // To make sure we can actually click on the element.
+ element.focus();
+
+ switch (currentTest.type) {
+ case 'untrusted':
+ var e = document.createEvent('MouseEvents');
+ e.initEvent('click', true, false);
+ document.getElementById(element.dispatchEvent(e));
+ break;
+ case 'prevent-default-1':
+ element.onclick = function() {
+ return false;
+ };
+ element.click();
+ element.onclick = function() {};
+ break;
+ case 'prevent-default-2':
+ element.onclick = function(e) {
+ e.preventDefault();
+ };
+ element.click();
+ element.onclick = function() {};
+ break;
+ case 'click-method':
+ element.click();
+ break;
+ case 'right-click':
+ synthesizeMouseAtCenter(element, { button: 2 });
+ break;
+ case 'middle-click':
+ synthesizeMouseAtCenter(element, { button: 1 });
+ break;
+ default:
+ synthesizeMouseAtCenter(element, {});
+ }
+
+ if (!currentTest.result) {
+ setTimeout(function() {
+ setTimeout(function() {
+ ok(true);
+ SimpleTest.executeSoon(function() {
+ test.next();
+ });
+ });
+ });
+ }
+ yield undefined;
+ };
+
+ MockColorPicker.cleanup();
+ SimpleTest.finish();
+ yield undefined;
+ }
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a>
+<p id="display"></p>
+<div id="content">
+ <input type='color' id='normal'>
+ <input type='color' id='hidden' hidden>
+ <label id='label-1'>foo<input type='color'></label>
+ <label id='label-2' for='labeled-2'>foo</label><input id='labeled-2' type='color'></label>
+ <label id='label-3'>foo<input type='color'></label>
+ <label id='label-4' for='labeled-4'>foo</label><input id='labeled-4' type='color'></label>
+ <input id='by-button' type='color'>
+ <button id='button-click' onclick="document.getElementById('by-button').click();">click</button>
+ <button id='button-down' onclick="document.getElementById('by-button').click();">click</button>
+ <button id='button-up' onclick="document.getElementById('by-button').click();">click</button>
+ <div id='div-click' onclick="document.getElementById('by-button').click();">click</div>
+ <div id='div-click-on-demand' onclick="var i=document.createElement('input'); i.type='color'; i.click();">click</div>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_color_picker_update.html b/dom/html/test/forms/test_input_color_picker_update.html
new file mode 100644
index 000000000..c40791323
--- /dev/null
+++ b/dom/html/test/forms/test_input_color_picker_update.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=885996
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1234567</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style> body { font-family: serif } </style>
+ <script type="application/javascript;version=1.8">
+
+ /** Test that update() modifies the element value such as done() when it is
+ * not called as a concellation.
+ */
+
+ SimpleTest.waitForExplicitFinish();
+
+ var MockColorPicker = SpecialPowers.MockColorPicker;
+
+ var test = runTest();
+
+ SimpleTest.waitForFocus(function() {
+ test.next();
+ });
+
+ function runTest() {
+ MockColorPicker.init(window);
+ var element = null;
+
+ MockColorPicker.showCallback = function(picker, update) {
+ is(picker.initialColor, element.value);
+
+ if (element.dataset.type == 'update') {
+ update('#f00ba4');
+ is(element.value, '#f00ba4');
+
+ MockColorPicker.returnColor = '#f00ba7';
+ isnot(element.value, MockColorPicker.returnColor);
+ } else if (element.dataset.type == 'cancel') {
+ MockColorPicker.returnColor = '#bababa';
+ isnot(element.value, MockColorPicker.returnColor);
+ } else if (element.dataset.type == 'done') {
+ MockColorPicker.returnColor = '#098766';
+ isnot(element.value, MockColorPicker.returnColor);
+ }
+
+ SimpleTest.executeSoon(function() {
+ if (element.dataset.type == 'cancel') {
+ isnot(element.value, MockColorPicker.returnColor);
+ } else {
+ is(element.value, MockColorPicker.returnColor);
+ }
+
+ test.next();
+ });
+
+ return element.dataset.type == 'cancel' ? "" : MockColorPicker.returnColor;
+ };
+
+ for (var i = 0; i < document.getElementsByTagName('input').length; ++i) {
+ element = document.getElementsByTagName('input')[i];
+ synthesizeMouseAtCenter(element, {});
+ yield undefined;
+ };
+
+ MockColorPicker.cleanup();
+ SimpleTest.finish();
+ yield undefined;
+ }
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885996">Mozilla Bug 885996</a>
+<p id="display"></p>
+<div id="content">
+ <input type='color' data-type='update'>
+ <input type='color' data-type='cancel'>
+ <input type='color' data-type='done'>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_datetime_focus_blur.html b/dom/html/test/forms/test_input_datetime_focus_blur.html
new file mode 100644
index 000000000..5b8d95b25
--- /dev/null
+++ b/dom/html/test/forms/test_input_datetime_focus_blur.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
+-->
+<head>
+ <title>Test focus/blur behaviour for &lt;input type='time'&gt;</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a>
+<p id="display"></p>
+<div id="content">
+ <input id="input" type="time">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 1288591.
+ * This test checks whether date/time input types' .focus()/.blur() works
+ * correctly. This test also checks when focusing on an date/time input element,
+ * the focus is redirected to the anonymous text control, but the
+ * document.activeElement still returns date/time input element.
+ **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ test();
+ SimpleTest.finish();
+});
+
+function test() {
+ let time = document.getElementById("input");
+ time.focus();
+
+ // The active element returns the input type=time.
+ let activeElement = document.activeElement;
+ is(activeElement, time, "activeElement should be the time element");
+ is(activeElement.localName, "input", "activeElement should be an input element");
+ is(activeElement.type, "time", "activeElement should be of type time");
+
+ // Use FocusManager to check that the actual focus is on the anonymous
+ // text control.
+ let fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"]
+ .getService(SpecialPowers.Ci.nsIFocusManager);
+ let focusedElement = fm.focusedElement;
+ is(focusedElement.localName, "input", "focusedElement should be an input element");
+ is(focusedElement.type, "text", "focusedElement should be of type text");
+
+ time.blur();
+ isnot(document.activeElement, time, "activeElement should no longer be the time element");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_datetime_tabindex.html b/dom/html/test/forms/test_input_datetime_tabindex.html
new file mode 100644
index 000000000..fb7c9b2f1
--- /dev/null
+++ b/dom/html/test/forms/test_input_datetime_tabindex.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
+-->
+<head>
+ <title>Test tabindex attribute for &lt;input type='time'&gt;</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a>
+<p id="display"></p>
+<div id="content">
+ <input id="time1" type="time" tabindex="0">
+ <input id="time2" type="time" tabindex="-1">
+ <input id="time3" type="time" tabindex="0">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 1288591.
+ * This test checks whether date/time input types' tabindex attribute works
+ * correctly.
+ **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ test();
+ SimpleTest.finish();
+});
+
+function test() {
+ let time1 = document.getElementById("time1");
+ let time2 = document.getElementById("time2");
+ let time3 = document.getElementById("time3");
+
+ time1.focus();
+ is(document.activeElement, time1,
+ "input element with tabindex=0 is focusable");
+
+ // Advance to time1 minute field
+ synthesizeKey("VK_TAB", {});
+ is(document.activeElement, time1,
+ "input element with tabindex=0 is tabbable");
+
+ // Advance to time1 AM/PM field
+ synthesizeKey("VK_TAB", {});
+ is(document.activeElement, time1,
+ "input element with tabindex=0 is tabbable");
+
+ // Advance to next element
+ synthesizeKey("VK_TAB", {});
+ is(document.activeElement, time3,
+ "input element with tabindex=-1 is not tabbable");
+
+ time2.focus();
+ is(document.activeElement, time2,
+ "input element with tabindex=-1 is still focusable");
+
+ // Changing the tabindex attribute dynamically.
+ time3.setAttribute("tabindex", "-1");
+ synthesizeKey("VK_TAB", {}); // need only one TAB since time2 is not tabbable
+ isnot(document.activeElement, time3,
+ "element with tabindex changed to -1 should not be tabbable");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_defaultValue.html b/dom/html/test/forms/test_input_defaultValue.html
new file mode 100644
index 000000000..53d2dd43a
--- /dev/null
+++ b/dom/html/test/forms/test_input_defaultValue.html
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=977029
+-->
+<head>
+ <title>Test for Bug 977029</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<div id="content">
+ <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=977029">Bug 977029</a>
+ <p>
+ Goal of this test is to check that modifying defaultValue and value attribute
+ of input types is working as expected.
+ </p>
+ <form>
+ <input id='a' type="color" value="#00ff00">
+ <input id='b' type="text" value="foo">
+ <input id='c' type="email" value="foo">
+ <input id='d' type="date" value="2010-09-20">
+ <input id='e' type="search" value="foo">
+ <input id='f' type="tel" value="foo">
+ <input id='g' type="url" value="foo">
+ <input id='h' type="number" value="42">
+ <input id='i' type="range" value="42" min="0" max="100">
+ <input id='j' type="time" value="17:00:25.54">
+ </form>
+</div>
+<script type="application/javascript">
+
+// [ element id | original defaultValue | another value | another default value]
+// Preferably use only valid values: the goal of this test isn't to test the
+// value sanitization algorithm (for input types which have one) as this is
+// already part of another test)
+var testData = [["a", "#00ff00", "#00aaaa", "#00ccaa"],
+ ["b", "foo", "bar", "tulip"],
+ ["c", "foo", "foo@bar.org", "tulip"],
+ ["d", "2010-09-20", "2012-09-21", ""],
+ ["e", "foo", "bar", "tulip"],
+ ["f", "foo", "bar", "tulip"],
+ ["g", "foo", "bar", "tulip"],
+ ["h", "42", "1337", "3"],
+ ["i", "42", "17", "3"],
+ ["j", "17:00:25.54", "07:00:25", "03:00:03"],
+ ];
+
+for (var data of testData) {
+ id = data[0];
+ input = document.getElementById(id);
+ originalDefaultValue = data[1];
+ is(originalDefaultValue, input.defaultValue,
+ "Default value isn't the expected one");
+ is(originalDefaultValue, input.value,
+ "input.value original value is different from defaultValue");
+ input.defaultValue = data[2]
+ is(input.defaultValue, input.value,
+ "Changing default value before value was changed should change value too");
+ input.value = data[3];
+ input.defaultValue = originalDefaultValue;
+ is(input.value, data[3],
+ "Changing default value after value was changed should not change value");
+ input.value = data[2];
+ is(originalDefaultValue, input.defaultValue,
+ "defaultValue shouldn't change when changing value");
+ input.defaultValue = data[3];
+ is(input.defaultValue, data[3],
+ "defaultValue should have changed");
+ // Change the value...
+ input.value = data[2];
+ is(input.value, data[2],
+ "value should have changed");
+ // ...then reset the form
+ input.form.reset();
+ is(input.defaultValue, input.value,
+ "reset form should bring back the default value");
+}
+</script>
+</body>
+</html>
+
diff --git a/dom/html/test/forms/test_input_email.html b/dom/html/test/forms/test_input_email.html
new file mode 100644
index 000000000..9f35cbe22
--- /dev/null
+++ b/dom/html/test/forms/test_input_email.html
@@ -0,0 +1,237 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=555559
+https://bugzilla.mozilla.org/show_bug.cgi?id=668817
+https://bugzilla.mozilla.org/show_bug.cgi?id=854812
+-->
+<head>
+ <title>Test for &lt;input type='email'&gt; validity</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=555559">Mozilla Bug 555559</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=668817">Mozilla Bug 668817</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=854812">Mozilla Bug 854812</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <form>
+ <input type='email' name='email' id='i' oninvalid="invalidEventHandler(event);">
+ <form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for <input type='email'> validity **/
+
+var gInvalid = false;
+
+function invalidEventHandler(e)
+{
+ is(e.type, "invalid", "Invalid event type should be invalid");
+ gInvalid = true;
+}
+
+function checkValidEmailAddress(element)
+{
+ gInvalid = false;
+ ok(!element.validity.typeMismatch && !element.validity.badInput,
+ "Element should not suffer from type mismatch or bad input (with value='"+element.value+"')");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "Element should be valid");
+ ok(!gInvalid, "The invalid event should not have been thrown");
+ is(element.validationMessage, '',
+ "Validation message should be the empty string");
+ ok(element.matches(":valid"), ":valid pseudo-class should apply");
+}
+
+const VALID = 0;
+const TYPE_MISMATCH = 1 << 0;
+const BAD_INPUT = 1 << 1;
+
+function checkInvalidEmailAddress(element, failedValidityStates)
+{
+ info("Checking " + element.value);
+ gInvalid = false;
+ var expectTypeMismatch = !!(failedValidityStates & TYPE_MISMATCH);
+ var expectBadInput = !!(failedValidityStates & BAD_INPUT);
+ ok(element.validity.typeMismatch == expectTypeMismatch,
+ "Element should " + (expectTypeMismatch ? "" : "not ") + "suffer from type mismatch (with value='"+element.value+"')");
+ ok(element.validity.badInput == expectBadInput,
+ "Element should " + (expectBadInput ? "" : "not ") + "suffer from bad input (with value='"+element.value+"')");
+ ok(!element.validity.valid, "Element should not be valid");
+ ok(!element.checkValidity(), "Element should not be valid");
+ ok(gInvalid, "The invalid event should have been thrown");
+ is(element.validationMessage, "Please enter an email address.",
+ "Validation message is not valid");
+ ok(element.matches(":invalid"), ":invalid pseudo-class should apply");
+}
+
+function testEmailAddress(aElement, aValue, aMultiple, aValidityFailures)
+{
+ aElement.multiple = aMultiple;
+ aElement.value = aValue;
+
+ if (!aValidityFailures) {
+ checkValidEmailAddress(aElement);
+ } else {
+ checkInvalidEmailAddress(aElement, aValidityFailures);
+ }
+}
+
+var email = document.forms[0].elements[0];
+
+// Simple values, checking the e-mail syntax validity.
+var values = [
+ [ '' ], // The empty string shouldn't be considered as invalid.
+ [ 'foo@bar.com', VALID ],
+ [ ' foo@bar.com', VALID ],
+ [ 'foo@bar.com ', VALID ],
+ [ '\r\n foo@bar.com', VALID ],
+ [ 'foo@bar.com \n\r', VALID ],
+ [ '\n\n \r\rfoo@bar.com\n\n \r\r', VALID ],
+ [ '\n\r \n\rfoo@bar.com\n\r \n\r', VALID ],
+ [ 'tulip', TYPE_MISMATCH ],
+ // Some checks on the user part of the address.
+ [ '@bar.com', TYPE_MISMATCH ],
+ [ 'f\noo@bar.com', VALID ],
+ [ 'f\roo@bar.com', VALID ],
+ [ 'f\r\noo@bar.com', VALID ],
+ [ 'fü@foo.com', TYPE_MISMATCH ],
+ // Some checks for the domain part.
+ [ 'foo@bar', VALID ],
+ [ 'foo@b', VALID ],
+ [ 'foo@', TYPE_MISMATCH ],
+ [ 'foo@bar.', TYPE_MISMATCH ],
+ [ 'foo@foo.bar', VALID ],
+ [ 'foo@foo..bar', TYPE_MISMATCH ],
+ [ 'foo@.bar', TYPE_MISMATCH ],
+ [ 'foo@tulip.foo.bar', VALID ],
+ [ 'foo@tulip.foo-bar', VALID ],
+ [ 'foo@1.2', VALID ],
+ [ 'foo@127.0.0.1', VALID ],
+ [ 'foo@1.2.3', VALID ],
+ [ 'foo@b\nar.com', VALID ],
+ [ 'foo@b\rar.com', VALID ],
+ [ 'foo@b\r\nar.com', VALID ],
+ [ 'foo@.', TYPE_MISMATCH ],
+ [ 'foo@fü.com', VALID ],
+ [ 'foo@fu.cüm', VALID ],
+ [ 'thisUsernameIsLongerThanSixtyThreeCharactersInLengthRightAboutNow@mozilla.tld', VALID ],
+ // Long strings with UTF-8 in username.
+ [ 'this.is.email.should.be.longer.than.sixty.four.characters.föö@mözillä.tld', TYPE_MISMATCH ],
+ [ 'this-is-email-should-be-longer-than-sixty-four-characters-föö@mözillä.tld', TYPE_MISMATCH, true ],
+ // Long labels (labels greater than 63 chars long are not allowed).
+ [ 'foo@thislabelisexactly63characterssssssssssssssssssssssssssssssssss', VALID ],
+ [ 'foo@thislabelisexactly63characterssssssssssssssssssssssssssssssssss.com', VALID ],
+ [ 'foo@foo.thislabelisexactly63characterssssssssssssssssssssssssssssssssss.com', VALID ],
+ [ 'foo@foo.thislabelisexactly63characterssssssssssssssssssssssssssssssssss', VALID ],
+ [ 'foo@thislabelisexactly64charactersssssssssssssssssssssssssssssssssss', TYPE_MISMATCH | BAD_INPUT ],
+ [ 'foo@thislabelisexactly64charactersssssssssssssssssssssssssssssssssss.com', TYPE_MISMATCH | BAD_INPUT ],
+ [ 'foo@foo.thislabelisexactly64charactersssssssssssssssssssssssssssssssssss.com', TYPE_MISMATCH | BAD_INPUT ],
+ [ 'foo@foo.thislabelisexactly64charactersssssssssssssssssssssssssssssssssss', TYPE_MISMATCH | BAD_INPUT ],
+ // Long labels with UTF-8 (punycode encoding will increase the label to more than 63 chars).
+ [ 'foo@thisläbelisexäctly63charäcterssssssssssssssssssssssssssssssssss', TYPE_MISMATCH | BAD_INPUT ],
+ [ 'foo@thisläbelisexäctly63charäcterssssssssssssssssssssssssssssssssss.com', TYPE_MISMATCH | BAD_INPUT ],
+ [ 'foo@foo.thisläbelisexäctly63charäcterssssssssssssssssssssssssssssssssss.com', TYPE_MISMATCH | BAD_INPUT ],
+ [ 'foo@foo.thisläbelisexäctly63charäcterssssssssssssssssssssssssssssssssss', TYPE_MISMATCH | BAD_INPUT ],
+ // The domains labels (sub-domains or tld) can't start or finish with a '-'
+ [ 'foo@foo-bar', VALID ],
+ [ 'foo@-foo', TYPE_MISMATCH ],
+ [ 'foo@foo-.bar', TYPE_MISMATCH ],
+ [ 'foo@-.-', TYPE_MISMATCH ],
+ [ 'foo@fo-o.bar', VALID ],
+ [ 'foo@fo-o.-bar', TYPE_MISMATCH ],
+ [ 'foo@fo-o.bar-', TYPE_MISMATCH ],
+ [ 'foo@fo-o.-', TYPE_MISMATCH ],
+ [ 'foo@fo--o', VALID ],
+];
+
+// Multiple values, we don't check e-mail validity, only multiple stuff.
+var multipleValues = [
+ [ 'foo@bar.com, foo@bar.com', VALID ],
+ [ 'foo@bar.com,foo@bar.com', VALID ],
+ [ 'foo@bar.com,foo@bar.com,foo@bar.com', VALID ],
+ [ ' foo@bar.com , foo@bar.com ', VALID ],
+ [ '\tfoo@bar.com\t,\tfoo@bar.com\t', VALID ],
+ [ '\rfoo@bar.com\r,\rfoo@bar.com\r', VALID ],
+ [ '\nfoo@bar.com\n,\nfoo@bar.com\n', VALID ],
+ [ '\ffoo@bar.com\f,\ffoo@bar.com\f', VALID ],
+ [ '\t foo@bar.com\r,\nfoo@bar.com\f', VALID ],
+ [ 'foo@b,ar.com,foo@bar.com', TYPE_MISMATCH ],
+ [ 'foo@bar.com,foo@bar.com,', TYPE_MISMATCH ],
+ [ ' foo@bar.com , foo@bar.com , ', TYPE_MISMATCH ],
+ [ ',foo@bar.com,foo@bar.com', TYPE_MISMATCH ],
+ [ ',foo@bar.com,foo@bar.com', TYPE_MISMATCH ],
+ [ 'foo@bar.com,,,foo@bar.com', TYPE_MISMATCH ],
+ [ 'foo@bar.com;foo@bar.com', TYPE_MISMATCH ],
+ [ '<foo@bar.com>, <foo@bar.com>', TYPE_MISMATCH ],
+ [ 'foo@bar, foo@bar.com', VALID ],
+ [ 'foo@bar.com, foo', TYPE_MISMATCH ],
+ [ 'foo, foo@bar.com', TYPE_MISMATCH ],
+];
+
+/* Additional username checks. */
+
+var legalCharacters = "abcdefghijklmnopqrstuvwxyz";
+legalCharacters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+legalCharacters += "0123456789";
+legalCharacters += "!#$%&'*+-/=?^_`{|}~.";
+
+// Add all username legal characters individually to the list.
+for (c of legalCharacters) {
+ values.push([c + "@bar.com", VALID]);
+}
+// Add the concatenation of all legal characters too.
+values.push([legalCharacters + "@bar.com", VALID]);
+
+// Add username illegal characters, the same way.
+var illegalCharacters = "()<>[]:;@\\, \t";
+for (c of illegalCharacters) {
+ values.push([illegalCharacters + "@bar.com", TYPE_MISMATCH]);
+}
+
+/* Additional domain checks. */
+
+legalCharacters = "abcdefghijklmnopqrstuvwxyz";
+legalCharacters += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+legalCharacters += "0123456789";
+
+// Add domain legal characters (except '.' and '-' because they are special).
+for (c of legalCharacters) {
+ values.push(["foo@foo.bar" + c, VALID]);
+}
+// Add the concatenation of all legal characters too.
+values.push(["foo@bar." + legalCharacters, VALID]);
+
+// Add domain illegal characters.
+illegalCharacters = "()<>[]:;@\\,!#$%&'*+/=?^_`{|}~ \t";
+for (c of illegalCharacters) {
+ values.push(['foo@foo.ba' + c + 'r', TYPE_MISMATCH]);
+}
+
+values.forEach(function([value, valid, todo]) {
+ if (todo === true) {
+ email.value = value;
+ todo_is(email.validity.valid, true, "value should be valid");
+ } else {
+ testEmailAddress(email, value, false, valid);
+ }
+});
+
+multipleValues.forEach(function([value, valid]) {
+ testEmailAddress(email, value, true, valid);
+});
+
+// Make sure setting multiple changes the value.
+email.multiple = false;
+email.value = "foo@bar.com, foo@bar.com";
+checkInvalidEmailAddress(email, TYPE_MISMATCH);
+email.multiple = true;
+checkValidEmailAddress(email);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_event.html b/dom/html/test/forms/test_input_event.html
new file mode 100644
index 000000000..f458b1b48
--- /dev/null
+++ b/dom/html/test/forms/test_input_event.html
@@ -0,0 +1,234 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=851780
+-->
+<head>
+<title>Test for input event</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=851780">Mozilla Bug 851780</a>
+<p id="display"></p>
+<div id="content">
+<input type="file" id="fileInput"></input>
+<textarea id="textarea" oninput="++textareaInput;"></textarea>
+<input type="text" id="input_text" oninput="++textInput[0];"></input>
+<input type="email" id="input_email" oninput="++textInput[1];"></input>
+<input type="search" id="input_search" oninput="++textInput[2];"></input>
+<input type="tel" id="input_tel" oninput="++textInput[3];"></input>
+<input type="url" id="input_url" oninput="++textInput[4];"></input>
+<input type="password" id="input_password" oninput="++textInput[5];"></input>
+
+<!-- "Non-text" inputs-->
+<input type="button" id="input_button" oninput="++NonTextInput[0];"></input>
+<input type="submit" id="input_submit" oninput="++NonTextInput[1];"></input>
+<input type="image" id="input_image" oninput="++NonTextInput[2];"></input>
+<input type="reset" id="input_reset" oninput="++NonTextInput[3];"></input>
+<input type="radio" id="input_radio" oninput="++NonTextInput[4];"></input>
+<input type="checkbox" id="input_checkbox" oninput="++NonTextInput[5];"></input>
+<input type="range" id="input_range" oninput="++rangeInput;"></input>
+<input type="number" id="input_number" oninput="++numberInput;"></input>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ /** Test for input event. This is highly based on test_change_event.html **/
+
+ const isDesktop = !/Mobile|Tablet/.test(navigator.userAgent);
+
+ var textareaInput = 0;
+
+ // Those are types were the input event apply.
+ var textTypes = ["text", "email", "search", "tel", "url", "password"];
+ var textInput = [0, 0, 0, 0, 0, 0];
+
+ // Those are events were the input event does not apply.
+ var NonTextTypes = ["button", "submit", "image", "reset", "radio", "checkbox"];
+ var NonTextInput = [0, 0, 0, 0, 0, 0];
+
+ var rangeInput = 0;
+ var numberInput = 0;
+
+ SimpleTest.waitForExplicitFinish();
+ var MockFilePicker = SpecialPowers.MockFilePicker;
+ MockFilePicker.init(window);
+
+ function testUserInput() {
+ // Simulating an OK click and with a file name return.
+ MockFilePicker.useBlobFile();
+ MockFilePicker.returnValue = MockFilePicker.returnOK;
+ var input = document.getElementById('fileInput');
+ input.focus();
+
+ input.addEventListener("input", function (aEvent) {
+ ok(true, "input event should have been dispatched on file input.");
+ }, false);
+
+ input.click();
+ setTimeout(testUserInput2, 0);
+ }
+
+ function testUserInput2() {
+ // Some generic checks for types that support the input event.
+ for (var i = 0; i < textTypes.length; ++i) {
+ input = document.getElementById("input_" + textTypes[i]);
+ input.focus();
+ synthesizeKey("VK_RETURN", {});
+ is(textInput[i], 0, "input event shouldn't be dispatched on " + textTypes[i] + " input element");
+
+ synthesizeKey("m", {});
+ is(textInput[i], 1, textTypes[i] + " input element should have dispatched input event.");
+ synthesizeKey("VK_RETURN", {});
+ is(textInput[i], 1, "input event shouldn't be dispatched on " + textTypes[i] + " input element");
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ is(textInput[i], 2, textTypes[i] + " input element should have dispatched input event.");
+ }
+
+ // Some scenarios of value changing from script and from user input.
+ input = document.getElementById("input_text");
+ input.focus();
+ synthesizeKey("f", {});
+ is(textInput[0], 3, "input event should have been dispatched");
+ input.blur();
+ is(textInput[0], 3, "input event should not have been dispatched");
+
+ input.focus();
+ input.value = 'foo';
+ is(textInput[0], 3, "input event should not have been dispatched");
+ input.blur();
+ is(textInput[0], 3, "input event should not have been dispatched");
+
+ input.focus();
+ synthesizeKey("f", {});
+ is(textInput[0], 4, "input event should have been dispatched");
+ input.value = 'bar';
+ is(textInput[0], 4, "input event should not have been dispatched");
+ input.blur();
+ is(textInput[0], 4, "input event should not have been dispatched");
+
+ // Same for textarea.
+ var textarea = document.getElementById("textarea");
+ textarea.focus();
+ synthesizeKey("f", {});
+ is(textareaInput, 1, "input event should have been dispatched");
+ textarea.blur();
+ is(textareaInput, 1, "input event should not have been dispatched");
+
+ textarea.focus();
+ textarea.value = 'foo';
+ is(textareaInput, 1, "input event should not have been dispatched");
+ textarea.blur();
+ is(textareaInput, 1, "input event should not have been dispatched");
+
+ textarea.focus();
+ synthesizeKey("f", {});
+ is(textareaInput, 2, "input event should have been dispatched");
+ textarea.value = 'bar';
+ is(textareaInput, 2, "input event should not have been dispatched");
+ synthesizeKey("VK_BACK_SPACE", {});
+ is(textareaInput, 3, "input event should have been dispatched");
+ textarea.blur();
+ is(textareaInput, 3, "input event should not have been dispatched");
+
+ // Non-text input tests:
+ for (var i = 0; i < NonTextTypes.length; ++i) {
+ // Button, submit, image and reset input type tests.
+ if (i < 4) {
+ input = document.getElementById("input_" + NonTextTypes[i]);
+ input.focus();
+ input.click();
+ is(NonTextInput[i], 0, "input event doesn't apply");
+ input.blur();
+ is(NonTextInput[i], 0, "input event doesn't apply");
+ }
+ // For radio and checkboxes, input event should be dispatched.
+ else {
+ input = document.getElementById("input_" + NonTextTypes[i]);
+ input.focus();
+ input.click();
+ is(NonTextInput[i], 1, "input event should have been dispatched");
+ input.blur();
+ is(NonTextInput[i], 1, "input event should not have been dispatched");
+
+ // Test that input event is not dispatched if click event is cancelled.
+ function preventDefault(e) {
+ e.preventDefault();
+ }
+ input.addEventListener("click", preventDefault, false);
+ input.click();
+ is(NonTextInput[i], 1, "input event shouldn't be dispatched if click event is cancelled");
+ input.removeEventListener("click", preventDefault, false);
+ }
+ }
+
+ // Type changes.
+ var input = document.createElement('input');
+ input.type = 'text';
+ input.value = 'foo';
+ input.oninput = function() {
+ ok(false, "we shouldn't get an input event when the type changes");
+ };
+ input.type = 'range';
+ isnot(input.value, 'foo');
+
+ // Tests for type='range'.
+ var range = document.getElementById("input_range");
+
+ range.focus();
+ synthesizeKey("a", {});
+ range.blur();
+ is(rangeInput, 0, "input event shouldn't be dispatched on range input " +
+ "element for key changes that don't change its value");
+
+ range.focus();
+ synthesizeKey("VK_HOME", {});
+ is(rangeInput, 1, "input event should be dispatched for key changes");
+ range.blur();
+ is(rangeInput, 1, "input event shouldn't be dispatched on blur");
+
+ range.focus();
+ var bcr = range.getBoundingClientRect();
+ var centerOfRangeX = bcr.width / 2;
+ var centerOfRangeY = bcr.height / 2;
+ synthesizeMouse(range, centerOfRangeX - 10, centerOfRangeY, { type: "mousedown" });
+ is(rangeInput, 2, "Input event should be dispatched on mousedown if the value changes");
+ synthesizeMouse(range, centerOfRangeX - 5, centerOfRangeY, { type: "mousemove" });
+ is(rangeInput, 3, "Input event should be dispatched during a drag");
+ synthesizeMouse(range, centerOfRangeX, centerOfRangeY, { type: "mouseup" });
+ is(rangeInput, 4, "Input event should be dispatched at the end of a drag");
+
+ // Tests for type='number'.
+ // We only test key events here since input events for mouse event changes
+ // are tested in test_input_number_mouse_events.html
+ var number = document.getElementById("input_number");
+
+ if (isDesktop) { // up/down arrow keys not supported on android/b2g
+ number.value = "";
+ number.focus();
+ synthesizeKey("KEY_ArrowUp", { code: "ArrowUp" });
+ is(numberInput, 1, "input event should be dispatched for up/down arrow key keypress");
+ is(number.value, "1", "sanity check value of number control after keypress");
+
+ synthesizeKey("KEY_ArrowDown", { code: "ArrowDown", repeat: 3 });
+ is(numberInput, 4, "input event should be dispatched for each up/down arrow key keypress event, even when rapidly repeated");
+ is(number.value, "-2", "sanity check value of number control after multiple keydown events");
+
+ number.blur();
+ is(numberInput, 4, "input event shouldn't be dispatched on blur");
+ }
+
+ MockFilePicker.cleanup();
+ SimpleTest.finish();
+ }
+
+ addLoadEvent(testUserInput);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_file_picker.html b/dom/html/test/forms/test_input_file_picker.html
new file mode 100644
index 000000000..6d3a98631
--- /dev/null
+++ b/dom/html/test/forms/test_input_file_picker.html
@@ -0,0 +1,267 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for &lt;input type='file'&gt; file picker</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=377624">Mozilla Bug 36619</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=377624">Mozilla Bug 377624</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=565274">Mozilla Bug 565274</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=701353">Mozilla Bug 701353</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=826176">Mozilla Bug 826176</a>
+<p id="display"></p>
+<div id="content">
+ <input id='a' type='file' accept="image/*">
+ <input id='b' type='file' accept="audio/*">
+ <input id='c' type='file' accept="video/*">
+ <input id='d' type='file' accept="image/*, audio/* ">
+ <input id='e' type='file' accept=" image/*,video/*">
+ <input id='f' type='file' accept="audio/*,video/*">
+ <input id='g' type='file' accept="image/*, audio/* ,video/*">
+ <input id='h' type='file' accept="foo/baz,image/*,bogus/duh">
+ <input id='i' type='file' accept="mime/type;parameter,video/*">
+ <input id='j' type='file' accept="audio/*, audio/*, audio/*">
+ <input id='k' type="file" accept="image/gif,image/png">
+ <input id='l' type="file" accept="image/*,image/gif,image/png">
+ <input id='m' type="file" accept="image/gif,image/gif">
+ <input id='n' type="file" accept="">
+ <input id='o' type="file" accept=".test">
+ <input id='p' type="file" accept="image/gif,.csv">
+ <input id='q' type="file" accept="image/gif,.gif">
+ <input id='r' type="file" accept=".prefix,.prefixPlusSomething">
+ <input id='s' type="file" accept=".xls,.xlsx">
+ <input id='t' type="file" accept=".mp3,.wav,.flac">
+ <input id='u' type="file" accept=".xls, .xlsx">
+ <input id='v' type="file" accept=".xlsx, .xls">
+ <input id='w' type="file" accept=".xlsx; .xls">
+ <input id='x' type="file" accept=".xls, .xlsx">
+ <input id='y' type="file" accept=".xlsx, .xls">
+ <input id='z' type='file' accept="i/am,a,pathological,;,,,,test/case">
+ <input id='A' type="file" accept=".xlsx, .xls*">
+ <input id='mix-ref' type="file" accept="image/jpeg">
+ <input id='mix' type="file" accept="image/jpeg,.jpg">
+ <input id='hidden' hidden type='file'>
+ <input id='untrusted-click' type='file'>
+ <input id='prevent-default' type='file'>
+ <input id='prevent-default-false' type='file'>
+ <input id='right-click' type='file'>
+ <input id='middle-click' type='file'>
+ <input id='left-click' type='file'>
+ <label id='label-1'>foo<input type='file'></label>
+ <label id='label-2' for='labeled-2'>foo</label><input id='labeled-2' type='file'></label>
+ <label id='label-3'>foo<input type='file'></label>
+ <label id='label-4' for='labeled-4'>foo</label><input id='labeled-4' type='file'></label>
+ <input id='by-button' type='file'>
+ <button id='button-click' onclick="document.getElementById('by-button').click();">foo</button>
+ <button id='button-down' onclick="document.getElementById('by-button').click();">foo</button>
+ <button id='button-up' onclick="document.getElementById('by-button').click();">foo</button>
+ <div id='div-click' onclick="document.getElementById('by-button').click();" tabindex='1'>foo</div>
+ <div id='div-click-on-demand' onclick="var i=document.createElement('input'); i.type='file'; i.click();" tabindex='1'>foo</div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * This test checks various scenarios and make sure that a file picker is being
+ * shown in all of them (minus a few exceptions).
+ * |testData| defines the tests to do and |launchNextTest| can be used to have
+ * specific behaviour for some tests. Everything else should just work.
+ */
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+var MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+
+// The following lists are from toolkit/content/filepicker.properties which is used by filePicker
+var imageExtensionList = "*.jpe; *.jpg; *.jpeg; *.gif; *.png; *.bmp; *.ico; *.svg; *.svgz; *.tif; *.tiff; *.ai; *.drw; *.pct; *.psp; *.xcf; *.psd; *.raw"
+var audioExtensionList = "*.aac; *.aif; *.flac; *.iff; *.m4a; *.m4b; *.mid; *.midi; *.mp3; *.mpa; *.mpc; *.oga; *.ogg; *.ra; *.ram; *.snd; *.wav; *.wma"
+var videoExtensionList = "*.avi; *.divx; *.flv; *.m4v; *.mkv; *.mov; *.mp4; *.mpeg; *.mpg; *.ogm; *.ogv; *.ogx; *.rm; *.rmvb; *.smil; *.webm; *.wmv; *.xvid"
+
+// [ element name | number of filters | extension list or filter mask | filter index ]
+var testData = [["a", 1, MockFilePicker.filterImages, 1],
+ ["b", 1, MockFilePicker.filterAudio, 1],
+ ["c", 1, MockFilePicker.filterVideo, 1],
+ ["d", 3, imageExtensionList + "; " + audioExtensionList, 1],
+ ["e", 3, imageExtensionList + "; " + videoExtensionList, 1],
+ ["f", 3, audioExtensionList + "; " + videoExtensionList, 1],
+ ["g", 4, imageExtensionList + "; " + audioExtensionList + "; " + videoExtensionList, 1],
+ ["h", 1, MockFilePicker.filterImages, 0],
+ ["i", 1, MockFilePicker.filterVideo, 0],
+ ["j", 1, MockFilePicker.filterAudio, 1],
+ ["k", 3, "*.gif; *.png", 1],
+ ["l", 4, imageExtensionList + "; " + "*.gif; *.png", 1],
+ ["m", 1, "*.gif", 1],
+ ["n", 0, undefined, 0],
+ ["o", 1, "*.test", 1],
+ ["p", 3, "*.gif; *.csv", 1],
+ ["q", 1, "*.gif", 1],
+ ["r", 3, "*.prefix; *.prefixPlusSomething", 1],
+ ["s", 3, "*.xls; *.xlsx", 1],
+ ["t", 4, "*.mp3; *.wav; *.flac", 1],
+ ["u", 3, "*.xls; *.xlsx", 1],
+ ["v", 3, "*.xlsx; *.xls", 1],
+ ["w", 0, undefined, 0],
+ ["x", 3, "*.xls; *.xlsx", 1],
+ ["y", 3, "*.xlsx; *.xls", 1],
+ ["z", 0, undefined, 0],
+ ["A", 1, "*.xlsx", 1],
+ // Note: mix and mix-ref tests extension lists are checked differently: see SimpleTest.executeSoon below
+ ["mix-ref", undefined, undefined, undefined],
+ ["mix", 1, undefined, 1],
+ ["hidden", 0, undefined, 0],
+ ["untrusted-click", 0, undefined, 0],
+ ["prevent-default", 0, undefined, 0, true],
+ ["prevent-default-false", 0, undefined, 0, true],
+ ["right-click", 0, undefined, 0, true],
+ ["middle-click", 0, undefined, 0, true],
+ ["left-click", 0, undefined, 0],
+ ["label-1", 0, undefined, 0],
+ ["label-2", 0, undefined, 0],
+ ["label-3", 0, undefined, 0],
+ ["label-4", 0, undefined, 0],
+ ["button-click", 0, undefined, 0],
+ ["button-down", 0, undefined, 0],
+ ["button-up", 0, undefined, 0],
+ ["div-click", 0, undefined, 0],
+ ["div-click-on-demand", 0, undefined, 0],
+ ];
+
+var currentTest = 0;
+var filterAllAdded;
+var filters;
+var filterIndex;
+var mixRefExtensionList;
+
+// disable popups to make sure that the popup blocker does not interfere
+// with manually opened file pickers.
+SpecialPowers.pushPrefEnv({'set': [["dom.disable_open_during_load", false]]}, runTests);
+
+function launchNextTest() {
+ MockFilePicker.shown = false;
+ filterAllAdded = false;
+ filters = [];
+ filterIndex = 0;
+
+ // Focusing the element will scroll them into view so making sure the clicks
+ // will work.
+ document.getElementById(testData[currentTest][0]).focus();
+
+ if (testData[currentTest][0] == "untrusted-click") {
+ var e = document.createEvent('MouseEvents');
+ e.initEvent('click', true, false);
+ document.getElementById(testData[currentTest][0]).dispatchEvent(e);
+ // All tests that should *NOT* show a file picker.
+ } else if (testData[currentTest][0] == "prevent-default" ||
+ testData[currentTest][0] == "prevent-default-false" ||
+ testData[currentTest][0] == "right-click" ||
+ testData[currentTest][0] == "middle-click") {
+ if (testData[currentTest][0] == "right-click" ||
+ testData[currentTest][0] == "middle-click") {
+ var b = testData[currentTest][0] == "middle-click" ? 1 : 2;
+ synthesizeMouseAtCenter(document.getElementById(testData[currentTest][0]),
+ { button: b });
+ } else {
+ if (testData[currentTest][0] == "prevent-default-false") {
+ document.getElementById(testData[currentTest][0]).onclick = function() {
+ return false;
+ };
+ } else {
+ document.getElementById(testData[currentTest][0]).onclick = function(e) {
+ e.preventDefault();
+ };
+ }
+ document.getElementById(testData[currentTest][0]).click();
+ }
+
+ // Wait a bit and assume we can continue. If the file picker shows later,
+ // behaviour is uncertain but that would be a random green, no big deal...
+ setTimeout(function() {
+ ok(true, "we should be there without a file picker being opened");
+ ++currentTest;
+ launchNextTest();
+ }, 500);
+ } else if (testData[currentTest][0] == 'label-3' ||
+ testData[currentTest][0] == 'label-4') {
+ synthesizeMouse(document.getElementById(testData[currentTest][0]), 5, 5, {});
+ } else if (testData[currentTest][0] == 'button-click' ||
+ testData[currentTest][0] == 'button-down' ||
+ testData[currentTest][0] == 'button-up' ||
+ testData[currentTest][0] == 'div-click' ||
+ testData[currentTest][0] == 'div-click-on-demand') {
+ synthesizeMouseAtCenter(document.getElementById(testData[currentTest][0]), {});
+ } else {
+ document.getElementById(testData[currentTest][0]).click();
+ }
+}
+
+function runTests() {
+ MockFilePicker.appendFilterCallback = function(filepicker, title, val) {
+ filters.push(val);
+ };
+ MockFilePicker.appendFiltersCallback = function(filepicker, val) {
+ if (val === MockFilePicker.filterAll) {
+ filterAllAdded = true;
+ } else {
+ filters.push(val);
+ }
+ };
+ MockFilePicker.showCallback = function(filepicker) {
+ if (testData[currentTest][4]) {
+ ok(false, "we shouldn't have a file picker showing!");
+ return;
+ }
+
+ filterIndex = filepicker.filterIndex;
+ testName = testData[currentTest][0];
+ SimpleTest.executeSoon(function () {
+ ok(MockFilePicker.shown,
+ "File picker show method should have been called (" + testName + ")");
+ ok(filterAllAdded,
+ "filterAll is missing (" + testName + ")");
+ if (testName == "mix-ref") {
+ // Used only for reference for next test: nothing to be tested here
+ mixRefExtensionList = filters[0];
+ if (mixRefExtensionList == undefined) {
+ mixRefExtensionList = "";
+ }
+ } else {
+ if (testName == "mix") {
+ // Mixing mime type and file extension filters ("image/jpeg" and
+ // ".jpg" here) shouldn't restrict the list but only extend it, if file
+ // extension filter isn't a duplicate
+ ok(filters[0].includes(mixRefExtensionList),
+ "Mixing mime types and file extension filters shouldn't restrict extension list: " +
+ mixRefExtensionList + " | " + filters[0]);
+ ok(filters[0].includes("*.jpg"),
+ "Filter should contain '.jpg' extension", filters[0]);
+ } else {
+ is(filters[0], testData[currentTest][2],
+ "Correct filters should have been added (" + testName + ")");
+ is(filters.length, testData[currentTest][1],
+ "appendFilters not called as often as expected (" + testName + ")");
+ }
+ is(filterIndex, testData[currentTest][3],
+ "File picker should show the correct filter index (" + testName + ")");
+ }
+
+ if (++currentTest == testData.length) {
+ MockFilePicker.cleanup();
+ SimpleTest.finish();
+ } else {
+ launchNextTest();
+ }
+ });
+ };
+
+ launchNextTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_list_attribute.html b/dom/html/test/forms/test_input_list_attribute.html
new file mode 100644
index 000000000..ff2be85d0
--- /dev/null
+++ b/dom/html/test/forms/test_input_list_attribute.html
@@ -0,0 +1,253 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=556007
+-->
+<head>
+ <title>Test for Bug 556007</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=556007">Mozilla Bug 556007</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 556007 **/
+
+function test0() {
+ var input = document.createElement("input");
+ ok("list" in input, "list should be an input element IDL attribute");
+}
+
+// Default .list returns null.
+function test1(aContent, aInput) {
+ return null;
+}
+
+// Regular test case.
+function test2(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+
+ aContent.appendChild(aInput);
+ aContent.appendChild(datalist);
+ aInput.setAttribute('list', 'd');
+
+ return datalist;
+}
+
+// If none of the element is in doc.
+function test3(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+
+ aInput.setAttribute('list', 'd');
+
+ return null;
+}
+
+// If one of the element isn't in doc.
+function test4(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+
+ aContent.appendChild(aInput);
+ aInput.setAttribute('list', 'd');
+
+ return null;
+}
+
+// If one of the element isn't in doc.
+function test5(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+
+ aContent.appendChild(datalist);
+ aInput.setAttribute('list', 'd');
+
+ return null;
+}
+
+// If datalist is added before input.
+function test6(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+
+ aContent.appendChild(datalist);
+ aContent.appendChild(aInput);
+ aInput.setAttribute('list', 'd');
+
+ return datalist;
+}
+
+// If setAttribute is set before datalist and input are in doc.
+function test7(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+
+ aInput.setAttribute('list', 'd');
+
+ aContent.appendChild(datalist);
+ aContent.appendChild(aInput);
+
+ return datalist;
+}
+
+// If setAttribute is set before datalist is in doc.
+function test8(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+
+ aContent.appendChild(aInput);
+ aInput.setAttribute('list', 'd');
+
+ aContent.appendChild(datalist);
+
+ return datalist;
+}
+
+// If setAttribute is set before datalist is created.
+function test9(aContent, aInput) {
+ aContent.appendChild(aInput);
+ aInput.setAttribute('list', 'd');
+
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+ aContent.appendChild(datalist);
+
+ return datalist;
+}
+
+// If another datalist is added _after_ the first one, with the same id.
+function test10(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+ var datalist2 = document.createElement("datalist");
+ datalist2.id = 'd';
+
+ aInput.setAttribute('list', 'd');
+ aContent.appendChild(aInput);
+ aContent.appendChild(datalist);
+ aContent.appendChild(datalist2);
+
+ return datalist;
+}
+
+// If another datalist is added _before_ the first one with the same id.
+function test11(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+ var datalist2 = document.createElement("datalist");
+ datalist2.id = 'd';
+
+ aInput.setAttribute('list', 'd');
+ aContent.appendChild(aInput);
+ aContent.appendChild(datalist);
+ aContent.insertBefore(datalist2, datalist);
+
+ return datalist2;
+}
+
+// If datalist changes it's id.
+function test12(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+
+ aInput.setAttribute('list', 'd');
+ aContent.appendChild(aInput);
+ aContent.appendChild(datalist);
+
+ datalist.id = 'foo';
+
+ return null;
+}
+
+// If datalist is removed.
+function test13(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+
+ aInput.setAttribute('list', 'd');
+ aContent.appendChild(aInput);
+ aContent.appendChild(datalist);
+ aContent.removeChild(datalist);
+
+ return null;
+}
+
+// If id contain spaces.
+function test14(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = 'a b c d';
+
+ aInput.setAttribute('list', 'a b c d');
+ aContent.appendChild(aInput);
+ aContent.appendChild(datalist);
+
+ return datalist;
+}
+
+// If id is the empty string.
+function test15(aContent, aInput) {
+ var datalist = document.createElement("datalist");
+ datalist.id = '';
+
+ aInput.setAttribute('list', '');
+ aContent.appendChild(aInput);
+ aContent.appendChild(datalist);
+
+ return null;
+}
+
+// If the id doesn't point to a datalist.
+function test16(aContent, aInput) {
+ var input = document.createElement("input");
+ input.id = 'd';
+
+ aInput.setAttribute('list', 'd');
+ aContent.appendChild(aInput);
+ aContent.appendChild(input);
+
+ return null;
+}
+
+// If the first element with the id isn't a datalist.
+function test17(aContent, aInput) {
+ var input = document.createElement("input");
+ input.id = 'd';
+ var datalist = document.createElement("datalist");
+ datalist.id = 'd';
+
+ aInput.setAttribute('list', 'd');
+ aContent.appendChild(aInput);
+ aContent.appendChild(input);
+ aContent.appendChild(datalist);
+
+ return null;
+}
+
+var tests = [ test1, test2, test3, test4, test5, test6, test7, test8, test9,
+ test10, test11, test12, test13, test14, test15, test16, test17 ];
+
+test0();
+
+for (var test of tests) {
+ var content = document.getElementById('content');
+
+ // Clean-up.
+ content.textContent = '';
+
+ var input = document.createElement("input");
+ var res = test(content, input);
+
+ is(input.list, res, "input.list should be " + res);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_number_data.js b/dom/html/test/forms/test_input_number_data.js
new file mode 100644
index 000000000..0a995010f
--- /dev/null
+++ b/dom/html/test/forms/test_input_number_data.js
@@ -0,0 +1,38 @@
+
+var tests = [
+ { desc: "British English",
+ langTag: "en-GB", inputWithGrouping: "123,456.78",
+ inputWithoutGrouping: "123456.78", value: 123456.78
+ },
+ { desc: "Farsi",
+ langTag: "fa", inputWithGrouping: "Û±Û²Û³Ù¬Û´ÛµÛ¶Ù«Û·Û¸",
+ inputWithoutGrouping: "Û±Û²Û³Û´ÛµÛ¶Ù«Û·Û¸", value: 123456.78
+ },
+ { desc: "French",
+ langTag: "fr-FR", inputWithGrouping: "123 456,78",
+ inputWithoutGrouping: "123456,78", value: 123456.78
+ },
+ { desc: "German",
+ langTag: "de", inputWithGrouping: "123.456,78",
+ inputWithoutGrouping: "123456,78", value: 123456.78
+ },
+ // Extra german test to check that a locale that uses '.' as its grouping
+ // separator doesn't result in it being invalid (due to step mismatch) due
+ // to the de-localization code mishandling numbers that look like other
+ // numbers formatted for English speakers (i.e. treating this as 123.456
+ // instead of 123456):
+ { desc: "German (test 2)",
+ langTag: "de", inputWithGrouping: "123.456",
+ inputWithoutGrouping: "123456", value: 123456
+ },
+ { desc: "Hebrew",
+ langTag: "he", inputWithGrouping: "123,456.78",
+ inputWithoutGrouping: "123456.78", value: 123456.78
+ },
+];
+
+var invalidTests = [
+ // Right now this will pass in a 'de' build, but not in the 'en' build that
+ // are used for testing. See bug .
+ // { desc: "Invalid German", langTag: "de", input: "12.34" }
+];
diff --git a/dom/html/test/forms/test_input_number_focus.html b/dom/html/test/forms/test_input_number_focus.html
new file mode 100644
index 000000000..121485463
--- /dev/null
+++ b/dom/html/test/forms/test_input_number_focus.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1268556
+-->
+<head>
+ <title>Test focus behaviour for &lt;input type='number'&gt;</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1268556">Mozilla Bug 1268556</a>
+<p id="display"></p>
+<div id="content">
+ <input id="input" type="number">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 1268556.
+ * This test checks that when focusing on an input type=number, the focus is
+ * redirected to the anonymous text control, but the document.activeElement
+ * still returns the <input type=number>.
+ **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ test();
+ SimpleTest.finish();
+});
+
+function test() {
+ var number = document.getElementById("input");
+ number.focus();
+
+ // The active element returns the input type=number.
+ var activeElement = document.activeElement;
+ is (activeElement, number, "activeElement should be the number element");
+ is (activeElement.localName, "input", "activeElement should be an input element");
+ is (activeElement.getAttribute("type"), "number", "activeElement should of type number");
+
+ // Use FocusManager to check that the actual focus is on the anonymous
+ // text control.
+ var fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"]
+ .getService(SpecialPowers.Ci.nsIFocusManager);
+ var focusedElement = fm.focusedElement;
+ is (focusedElement.localName, "input", "focusedElement should be an input element");
+ is (focusedElement.getAttribute("type"), "text", "focusedElement should of type text");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_number_key_events.html b/dom/html/test/forms/test_input_number_key_events.html
new file mode 100644
index 000000000..89578541d
--- /dev/null
+++ b/dom/html/test/forms/test_input_number_key_events.html
@@ -0,0 +1,244 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=935506
+-->
+<head>
+ <title>Test key events for number control</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=935506">Mozilla Bug 935506</a>
+<p id="display"></p>
+<div id="content">
+ <input id="input" type="number">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 935506
+ * This test checks how the value of <input type=number> changes in response to
+ * key events while it is in various states.
+ **/
+SimpleTest.waitForExplicitFinish();
+// Turn off Spatial Navigation because it hijacks arrow keydown events:
+SimpleTest.waitForFocus(function() {
+ SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() {
+ test();
+ SimpleTest.finish();
+ });
+});
+const defaultMinimum = "NaN";
+const defaultMaximum = "NaN";
+const defaultStep = 1;
+
+// Helpers:
+// For the sake of simplicity, we do not currently support fractional value,
+// step, etc.
+
+function getMinimum(element) {
+ return Number(element.min || defaultMinimum);
+}
+
+function getMaximum(element) {
+ return Number(element.max || defaultMaximum);
+}
+
+function getDefaultValue(element) {
+ return 0;
+}
+
+function getValue(element) {
+ return Number(element.value || getDefaultValue(element));
+}
+
+function getStep(element) {
+ if (element.step == "any") {
+ return "any";
+ }
+ var step = Number(element.step || defaultStep);
+ return step <= 0 ? defaultStep : step;
+}
+
+function getStepBase(element) {
+ return Number(element.getAttribute("min") || "NaN") ||
+ Number(element.getAttribute("value") || "NaN") || 0;
+}
+
+function hasStepMismatch(element) {
+ var value = element.value;
+ if (value == "") {
+ value = 0;
+ }
+ var step = getStep(element);
+ if (step == "any") {
+ return false;
+ }
+ return ((value - getStepBase(element)) % step) != 0;
+}
+
+function floorModulo(x, y) {
+ return (x - y * Math.floor(x / y));
+}
+
+function expectedValueAfterStepUpOrDown(stepFactor, element) {
+ var value = getValue(element);
+ if (isNaN(value)) {
+ value = 0;
+ }
+ var step = getStep(element);
+ if (step == "any") {
+ step = 1;
+ }
+
+ var minimum = getMinimum(element);
+ var maximum = getMaximum(element);
+ if (!isNaN(maximum)) {
+ // "max - (max - stepBase) % step" is the nearest valid value to max.
+ maximum = maximum - floorModulo(maximum - getStepBase(element), step);
+ }
+
+ // Cases where we are clearly going in the wrong way.
+ // We don't use ValidityState because we can be higher than the maximal
+ // allowed value and still not suffer from range overflow in the case of
+ // of the value specified in @max isn't in the step.
+ if ((value <= minimum && stepFactor < 0) ||
+ (value >= maximum && stepFactor > 0)) {
+ return value;
+ }
+
+ if (hasStepMismatch(element) &&
+ value != minimum && value != maximum) {
+ if (stepFactor > 0) {
+ value -= floorModulo(value - getStepBase(element), step);
+ } else if (stepFactor < 0) {
+ value -= floorModulo(value - getStepBase(element), step);
+ value += step;
+ }
+ }
+
+ value += step * stepFactor;
+
+ // When stepUp() is called and the value is below minimum, we should clamp on
+ // minimum unless stepUp() moves us higher than minimum.
+ if (element.validity.rangeUnderflow && stepFactor > 0 &&
+ value <= minimum) {
+ value = minimum;
+ } else if (element.validity.rangeOverflow && stepFactor < 0 &&
+ value >= maximum) {
+ value = maximum;
+ } else if (stepFactor < 0 && !isNaN(minimum)) {
+ value = Math.max(value, minimum);
+ } else if (stepFactor > 0 && !isNaN(maximum)) {
+ value = Math.min(value, maximum);
+ }
+
+ return value;
+}
+
+function expectedValAfterKeyEvent(key, element) {
+ return expectedValueAfterStepUpOrDown(key == "VK_UP" ? 1 : -1, element);
+}
+
+function test() {
+ var elem = document.getElementById("input");
+ elem.focus();
+
+ elem.min = -5;
+ elem.max = 5;
+ elem.step = 2;
+ var defaultValue = 0;
+ var oldVal, expectedVal;
+
+ for (key of ["VK_UP", "VK_DOWN"]) {
+ // Start at middle:
+ oldVal = elem.value = -1;
+ expectedVal = expectedValAfterKeyEvent(key, elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test " + key + " for number control with value set between min/max (" + oldVal + ")");
+
+ // Same again:
+ expectedVal = expectedValAfterKeyEvent(key, elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control");
+
+ // Start at maximum:
+ oldVal = elem.value = elem.max;
+ expectedVal = expectedValAfterKeyEvent(key, elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the maximum (" + oldVal + ")");
+
+ // Same again:
+ expectedVal = expectedValAfterKeyEvent(key, elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control");
+
+ // Start at minimum:
+ oldVal = elem.value = elem.min;
+ expectedVal = expectedValAfterKeyEvent(key, elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the minimum (" + oldVal + ")");
+
+ // Same again:
+ expectedVal = expectedValAfterKeyEvent(key, elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control");
+
+ // Test preventDefault():
+ elem.addEventListener("keypress", function(evt) {
+ evt.preventDefault();
+ elem.removeEventListener("keypress", arguments.callee, false);
+ }, false);
+ oldVal = elem.value = 0;
+ expectedVal = 0;
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test " + key + " for number control where scripted preventDefault() should prevent the value changing");
+
+ // Test step="any" behavior:
+ var oldStep = elem.step;
+ elem.step = "any";
+ oldVal = elem.value = 0;
+ expectedVal = expectedValAfterKeyEvent(key, elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the midpoint and step='any' (" + oldVal + ")");
+ elem.step = oldStep; // restore
+
+ // Test that invalid input blocks UI initiated stepping:
+ oldVal = elem.value = "";
+ elem.select();
+ sendString("abc");
+ synthesizeKey(key, {});
+ is(elem.value, "", "Test " + key + " does nothing when the input is invalid");
+
+ // Test that no value does not block UI initiated stepping:
+ oldVal = elem.value = "";
+ elem.setAttribute("required", "required");
+ elem.select();
+ expectedVal = expectedValAfterKeyEvent(key, elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test " + key + " for number control with value set to the empty string and with the 'required' attribute set");
+
+ // Same again:
+ expectedVal = expectedValAfterKeyEvent(key, elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test repeat of " + key + " for number control");
+
+ // Reset 'required' attribute:
+ elem.removeAttribute("required");
+ }
+
+ // Test that key events are correctly dispatched
+ elem.max = "";
+ elem.value = "";
+ sendString("7837281");
+ is(elem.value, "7837281", "Test keypress event dispatch for number control");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_number_l10n.html b/dom/html/test/forms/test_input_number_l10n.html
new file mode 100644
index 000000000..4d46f7a80
--- /dev/null
+++ b/dom/html/test/forms/test_input_number_l10n.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=844744
+-->
+<head>
+ <title>Test localization of number control input</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="test_input_number_data.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=844744">Mozilla Bug 844744</a>
+<p id="display"></p>
+<div id="content">
+ <input id="input" type="number" step="any">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 844744
+ * This test checks that localized input that is typed into <input type=number>
+ * is correctly handled.
+ **/
+SimpleTest.waitForExplicitFinish();
+
+SimpleTest.waitForFocus(function() {
+ startTests();
+ SimpleTest.finish();
+});
+
+var elem;
+
+function runTest(test) {
+ elem.lang = test.langTag;
+ elem.value = 0;
+ elem.focus();
+ elem.select();
+ sendString(test.inputWithGrouping);
+ is(elem.value, String(test.value), "Test " + test.desc + " ('" + test.langTag +
+ "') localization with grouping separator");
+ elem.value = 0;
+ elem.select();
+ sendString(test.inputWithoutGrouping);
+ is(elem.value, String(test.value), "Test " + test.desc + " ('" + test.langTag +
+ "') localization without grouping separator");
+}
+
+function runInvalidInputTest(test) {
+ elem.lang = test.langTag;
+ elem.value = 0;
+ elem.focus();
+ elem.select();
+ sendString(test.input);
+ is(elem.value, "", "Test " + test.desc + " ('" + test.langTag +
+ "') with invalid input: " + test.input);
+}
+
+function startTests() {
+ elem = document.getElementById("input");
+ for (var test of tests) {
+ runTest(test, elem);
+ }
+ for (var test of invalidTests) {
+ runInvalidInputTest(test, elem);
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_number_mouse_events.html b/dom/html/test/forms/test_input_number_mouse_events.html
new file mode 100644
index 000000000..45f310761
--- /dev/null
+++ b/dom/html/test/forms/test_input_number_mouse_events.html
@@ -0,0 +1,196 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=935501
+-->
+<head>
+ <title>Test mouse events for number</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <style>
+ input {
+ margin: 0 ! important;
+ border: 0 ! important;
+ padding: 0 ! important;
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=935501">Mozilla Bug 935501</a>
+<p id="display"></p>
+<div id="content">
+ <input id="input" type="number">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 935501
+ * This test checks how the value of <input type=number> changes in response to
+ * various mouse events.
+ **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+SimpleTest.waitForFocus(function() {
+ test();
+});
+
+var input = document.getElementById("input");
+var inputRect = input.getBoundingClientRect();
+
+// Points over the input's spin-up and spin-down buttons (as offsets from the
+// top-left of the input's bounding client rect):
+const SPIN_UP_X = inputRect.width - 3;
+const SPIN_UP_Y = 3;
+const SPIN_DOWN_X = inputRect.width - 3;
+const SPIN_DOWN_Y = inputRect.height - 3;
+
+function test() {
+ input.value = 0;
+
+ // Test click on spin-up button:
+ synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" });
+ is(input.value, "1", "Test step-up on mousedown on spin-up button");
+ synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" });
+ is(input.value, "1", "Test mouseup on spin-up button");
+
+ // Test click on spin-down button:
+ synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" });
+ is(input.value, "0", "Test step-down on mousedown on spin-down button");
+ synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
+ is(input.value, "0", "Test mouseup on spin-down button");
+
+ // Test step="any" behavior:
+ input.value = 0;
+ var oldStep = input.step;
+ input.step = "any";
+ synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" });
+ is(input.value, "1", "Test step-up on mousedown on spin-up button with step='any'");
+ synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" });
+ is(input.value, "1", "Test mouseup on spin-up button with step='any'");
+ synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" });
+ is(input.value, "0", "Test step-down on mousedown on spin-down button with step='any'");
+ synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
+ is(input.value, "0", "Test mouseup on spin-down button with step='any'");
+ input.step = oldStep; // restore
+
+ // Test that preventDefault() works:
+ function preventDefault(e) {
+ e.preventDefault();
+ }
+ input.value = 1;
+ input.addEventListener("mousedown", preventDefault, false);
+ synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, {});
+ is(input.value, "1", "Test that preventDefault() works for click on spin-up button");
+ synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, {});
+ is(input.value, "1", "Test that preventDefault() works for click on spin-down button");
+ input.removeEventListener("mousedown", preventDefault, false);
+
+ // Run the spin tests:
+ runNextSpinTest();
+}
+
+function runNextSpinTest() {
+ var test = spinTests.shift();
+ if (!test) {
+ SimpleTest.finish();
+ return;
+ }
+ test();
+}
+
+const SETTIMEOUT_DELAY = 500;
+
+var spinTests = [
+ // Test spining when the mouse button is kept depressed on the spin-up
+ // button, then moved over the spin-down button:
+ function() {
+ var inputEventCount = 0;
+ input.value = 0;
+ input.addEventListener("input", function(evt) {
+ ++inputEventCount;
+ if (inputEventCount == 3) {
+ is(input.value, "3", "Testing spin-up button");
+ synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousemove" });
+ } else if (inputEventCount == 6) {
+ is(input.value, "0", "Testing spin direction is reversed after mouse moves from spin-up button to spin-down button");
+ input.removeEventListener("input", arguments.callee, false);
+ synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
+ runNextSpinTest();
+ }
+ }, false);
+ synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" });
+ },
+
+ // Test spining when the mouse button is kept depressed on the spin-down
+ // button, then moved over the spin-up button:
+ function() {
+ var inputEventCount = 0;
+ input.value = 0;
+ input.addEventListener("input", function(evt) {
+ ++inputEventCount;
+ if (inputEventCount == 3) {
+ is(input.value, "-3", "Testing spin-down button");
+ synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousemove" });
+ } else if (inputEventCount == 6) {
+ is(input.value, "0", "Testing spin direction is reversed after mouse moves from spin-down button to spin-up button");
+ input.removeEventListener("input", arguments.callee, false);
+ synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mouseup" });
+ runNextSpinTest();
+ }
+ }, false);
+ synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" });
+ },
+
+ // Test that the spin is stopped when the mouse button is depressod on the
+ // spin-up button, then moved outside both buttons once the spin starts:
+ function() {
+ var inputEventCount = 0;
+ input.value = 0;
+ input.addEventListener("input", function(evt) {
+ ++inputEventCount;
+ if (inputEventCount == 3) {
+ synthesizeMouse(input, -1, -1, { type: "mousemove" });
+ var eventHandler = arguments.callee;
+ setTimeout(function() {
+ is(input.value, "3", "Testing moving the mouse outside the spin buttons stops the spin");
+ is(inputEventCount, 3, "Testing moving the mouse outside the spin buttons stops the spin input events");
+ input.removeEventListener("input", eventHandler, false);
+ synthesizeMouse(input, -1, -1, { type: "mouseup" });
+ runNextSpinTest();
+ }, SETTIMEOUT_DELAY);
+ }
+ }, false);
+ synthesizeMouse(input, SPIN_UP_X, SPIN_UP_Y, { type: "mousedown" });
+ },
+
+ // Test that changing the input type in the middle of a spin cancels the spin:
+ function() {
+ var inputEventCount = 0;
+ input.value = 0;
+ input.addEventListener("input", function(evt) {
+ ++inputEventCount;
+ if (inputEventCount == 3) {
+ input.type = "text"
+ var eventHandler = arguments.callee;
+ setTimeout(function() {
+ is(input.value, "-3", "Testing changing input type during a spin stops the spin");
+ is(inputEventCount, 3, "Testing changing input type during a spin stops the spin input events");
+ input.removeEventListener("input", eventHandler, false);
+ synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mouseup" });
+ input.type = "number"; // restore
+ runNextSpinTest();
+ }, SETTIMEOUT_DELAY);
+ }
+ }, false);
+ synthesizeMouse(input, SPIN_DOWN_X, SPIN_DOWN_Y, { type: "mousedown" });
+ }
+];
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_number_rounding.html b/dom/html/test/forms/test_input_number_rounding.html
new file mode 100644
index 000000000..16bc8ec52
--- /dev/null
+++ b/dom/html/test/forms/test_input_number_rounding.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=783607
+-->
+<head>
+ <title>Test rounding behaviour for &lt;input type='number'&gt;</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=783607">Mozilla Bug 783607</a>
+<p id="display"></p>
+<div id="content">
+ <input id=number type=number value=0 step=0.01 max=1>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 783607.
+ * This test checks that when <input type=number> has fractional step values,
+ * the values that a content author will see in their script will not have
+ * ugly rounding errors.
+ **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ test();
+ SimpleTest.finish();
+});
+
+/**
+ * We can _NOT_ generate these values by looping and simply incrementing a
+ * variable by 0.01 and stringifying it, since we'll end up with strings like
+ * "0.060000000000000005" due to the inability of binary floating point numbers
+ * to accurately represent decimal values.
+ */
+var stepVals = [
+ "0", "0.01", "0.02", "0.03", "0.04", "0.05", "0.06", "0.07", "0.08", "0.09",
+ "0.1", "0.11", "0.12", "0.13", "0.14", "0.15", "0.16", "0.17", "0.18", "0.19",
+ "0.2", "0.21", "0.22", "0.23", "0.24", "0.25", "0.26", "0.27", "0.28", "0.29",
+ "0.3", "0.31", "0.32", "0.33", "0.34", "0.35", "0.36", "0.37", "0.38", "0.39",
+ "0.4", "0.41", "0.42", "0.43", "0.44", "0.45", "0.46", "0.47", "0.48", "0.49",
+ "0.5", "0.51", "0.52", "0.53", "0.54", "0.55", "0.56", "0.57", "0.58", "0.59",
+ "0.6", "0.61", "0.62", "0.63", "0.64", "0.65", "0.66", "0.67", "0.68", "0.69",
+ "0.7", "0.71", "0.72", "0.73", "0.74", "0.75", "0.76", "0.77", "0.78", "0.79",
+ "0.8", "0.81", "0.82", "0.83", "0.84", "0.85", "0.86", "0.87", "0.88", "0.89",
+ "0.9", "0.91", "0.92", "0.93", "0.94", "0.95", "0.96", "0.97", "0.98", "0.99",
+ "1"
+];
+
+var pgUpDnVals = [
+ "0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1"
+];
+
+function test() {
+ var elem = document.getElementById("number");
+
+ elem.focus();
+
+ /**
+ * TODO:
+ * When <input type='number'> widget will have a widge we should test PAGE_UP,
+ * PAGE_DOWN, UP and DOWN keys. For the moment, there is no widget so those
+ * keys do not have any effect.
+ * The tests using those keys as marked as todo_is() hoping that at least part
+ * of them will fail when the widget will be implemented.
+ */
+
+/* No other implementations implement this, so we don't either, for now.
+ Seems like it might be nice though.
+
+ for (var i = 1; i < pgUpDnVals.length; ++i) {
+ synthesizeKey("VK_PAGE_UP", {});
+ todo_is(elem.value, pgUpDnVals[i], "Test VK_PAGE_UP");
+ is(elem.validity.valid, true, "Check element is valid for value " + pgUpDnVals[i]);
+ }
+
+ for (var i = pgUpDnVals.length - 2; i >= 0; --i) {
+ synthesizeKey("VK_PAGE_DOWN", {});
+ // TODO: this condition is there because the todo_is() below would pass otherwise.
+ if (stepVals[i] == 0) { continue; }
+ todo_is(elem.value, pgUpDnVals[i], "Test VK_PAGE_DOWN");
+ is(elem.validity.valid, true, "Check element is valid for value " + pgUpDnVals[i]);
+ }
+*/
+
+ for (var i = 1; i < stepVals.length; ++i) {
+ synthesizeKey("VK_UP", {});
+ is(elem.value, stepVals[i], "Test VK_UP");
+ is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]);
+ }
+
+ for (var i = stepVals.length - 2; i >= 0; --i) {
+ synthesizeKey("VK_DOWN", {});
+ // TODO: this condition is there because the todo_is() below would pass otherwise.
+ if (stepVals[i] == 0) { continue; }
+ is(elem.value, stepVals[i], "Test VK_DOWN");
+ is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]);
+ }
+
+ for (var i = 1; i < stepVals.length; ++i) {
+ elem.stepUp();
+ is(elem.value, stepVals[i], "Test stepUp()");
+ is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]);
+ }
+
+ for (var i = stepVals.length - 2; i >= 0; --i) {
+ elem.stepDown();
+ is(elem.value, stepVals[i], "Test stepDown()");
+ is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]);
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_number_validation.html b/dom/html/test/forms/test_input_number_validation.html
new file mode 100644
index 000000000..5f551337b
--- /dev/null
+++ b/dom/html/test/forms/test_input_number_validation.html
@@ -0,0 +1,143 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=827161
+-->
+<head>
+ <title>Test validation of number control input</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="test_input_number_data.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=827161">Mozilla Bug 827161</a>
+<p id="display"></p>
+<div id="content">
+ <input id="input" type="number" step="0.01" oninvalid="invalidEventHandler(event);">
+ <input id="requiredinput" type="number" step="0.01" required
+ oninvalid="invalidEventHandler(event);">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 827161.
+ * This test checks that validation works correctly for <input type=number>.
+ **/
+SimpleTest.waitForExplicitFinish();
+
+SimpleTest.waitForFocus(function() {
+ startTests();
+ SimpleTest.finish();
+});
+
+var elem;
+
+function runTest(test) {
+ elem.lang = test.langTag;
+
+ gInvalid = false; // reset
+ var desc = `${test.desc} (lang='${test.langTag}', id='${elem.id}')`;
+ elem.value = 0;
+ elem.focus();
+ elem.select();
+ sendString(test.inputWithGrouping);
+ checkIsValid(elem, `${desc} with grouping separator`);
+ sendChar("a");
+ checkIsInvalid(elem, `${desc} with grouping separator`);
+
+ gInvalid = false; // reset
+ elem.value = 0;
+ elem.select();
+ sendString(test.inputWithoutGrouping);
+ checkIsValid(elem, `${desc} without grouping separator`);
+ sendChar("a");
+ checkIsInvalid(elem, `${desc} without grouping separator`);
+}
+
+function runInvalidInputTest(test) {
+ elem.lang = test.langTag;
+
+ gInvalid = false; // reset
+ var desc = `${test.desc} (lang='${test.langTag}', id='${elem.id}')`;
+ elem.value = 0;
+ elem.focus();
+ elem.select();
+ sendString(test.input);
+ checkIsInvalid(elem, `${desc} with invalid input ${test.input}`);
+}
+
+function startTests() {
+ elem = document.getElementById("input");
+ for (var test of tests) {
+ runTest(test);
+ }
+ for (var test of invalidTests) {
+ runInvalidInputTest(test);
+ }
+ elem = document.getElementById("requiredinput");
+ for (var test of tests) {
+ runTest(test);
+ }
+
+ gInvalid = false; // reset
+ elem.value = "";
+ checkIsInvalidEmptyValue(elem, "empty value");
+}
+
+var gInvalid = false;
+
+function invalidEventHandler(e)
+{
+ is(e.type, "invalid", "Invalid event type should be 'invalid'");
+ gInvalid = true;
+}
+
+function checkIsValid(element, infoStr)
+{
+ ok(!element.validity.badInput,
+ "Element should not suffer from bad input for " + infoStr);
+ ok(element.validity.valid, "Element should be valid for " + infoStr);
+ ok(element.checkValidity(), "checkValidity() should return true for " + infoStr);
+ ok(!gInvalid, "The invalid event should not have been thrown for " + infoStr);
+ is(element.validationMessage, '',
+ "Validation message should be the empty string for " + infoStr);
+ ok(element.matches(":valid"), ":valid pseudo-class should apply for " + infoStr);
+}
+
+function checkIsInvalid(element, infoStr)
+{
+ ok(element.validity.badInput,
+ "Element should suffer from bad input for " + infoStr);
+ if (element.id == "requiredinput") {
+ ok(element.validity.valueMissing,
+ "Element should suffer from value missing for " + infoStr);
+ }
+ ok(!element.validity.valid, "Element should not be valid for " + infoStr);
+ ok(!element.checkValidity(), "checkValidity() should return false for " + infoStr);
+ ok(gInvalid, "The invalid event should have been thrown for " + infoStr);
+ is(element.validationMessage, "Please enter a number.",
+ "Validation message is not the expected message for " + infoStr);
+ ok(element.matches(":invalid"), ":invalid pseudo-class should apply for " + infoStr);
+}
+
+function checkIsInvalidEmptyValue(element, infoStr)
+{
+ ok(!element.validity.badInput,
+ "Element should not suffer from bad input for " + infoStr);
+ ok(element.validity.valueMissing,
+ "Element should suffer from value missing for " + infoStr);
+ ok(!element.validity.valid, "Element should not be valid for " + infoStr);
+ ok(!element.checkValidity(), "checkValidity() should return false for " + infoStr);
+ ok(gInvalid, "The invalid event should have been thrown for " + infoStr);
+ is(element.validationMessage, "Please enter a number.",
+ "Validation message is not the expected message for " + infoStr);
+ ok(element.matches(":invalid"), ":invalid pseudo-class should apply for " + infoStr);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_radio_indeterminate.html b/dom/html/test/forms/test_input_radio_indeterminate.html
new file mode 100644
index 000000000..aa7ca21bf
--- /dev/null
+++ b/dom/html/test/forms/test_input_radio_indeterminate.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=885359
+-->
+<head>
+ <title>Test for Bug 885359</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885359">Mozilla Bug 343444</a>
+<p id="display"></p>
+<form>
+ <input type="radio" id='radio1'/><br/>
+
+ <input type="radio" id="g1radio1" name="group1"/>
+ <input type="radio" id="g1radio2" name="group1"/></br>
+ <input type="radio" id="g1radio3" name="group1"/></br>
+
+ <input type="radio" id="g2radio1" name="group2"/>
+ <input type="radio" id="g2radio2" name="group2" checked/></br>
+</form>
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var radio1 = document.getElementById("radio1");
+var g1radio1 = document.getElementById("g1radio1");
+var g1radio2 = document.getElementById("g1radio2");
+var g1radio3 = document.getElementById("g1radio3");
+var g2radio1 = document.getElementById("g2radio1");
+var g2radio2 = document.getElementById("g2radio2");
+
+SimpleTest.waitForFocus(function() {
+ test();
+ SimpleTest.finish();
+});
+
+function verifyIndeterminateState(aElement, aIsIndeterminate, aMessage) {
+ is(aElement.mozMatchesSelector(':indeterminate'), aIsIndeterminate, aMessage);
+}
+
+function test() {
+ // Initial State.
+ verifyIndeterminateState(radio1, true,
+ "Unchecked radio in its own group (no name attribute)");
+ verifyIndeterminateState(g1radio1, true, "No selected radio in its group");
+ verifyIndeterminateState(g1radio2, true, "No selected radio in its group");
+ verifyIndeterminateState(g1radio3, true, "No selected radio in its group");
+ verifyIndeterminateState(g2radio1, false, "Selected radio in its group");
+ verifyIndeterminateState(g2radio2, false, "Selected radio in its group");
+
+ // Selecting radio buttion.
+ g1radio1.checked = true;
+ verifyIndeterminateState(g1radio1, false,
+ "Selecting a radio should affect all radios in the group");
+ verifyIndeterminateState(g1radio2, false,
+ "Selecting a radio should affect all radios in the group");
+ verifyIndeterminateState(g1radio3, false,
+ "Selecting a radio should affect all radios in the group");
+
+ // Changing the selected radio button.
+ g1radio3.checked = true;
+ verifyIndeterminateState(g1radio1, false,
+ "Selecting a radio should affect all radios in the group");
+ verifyIndeterminateState(g1radio2, false,
+ "Selecting a radio should affect all radios in the group");
+ verifyIndeterminateState(g1radio3, false,
+ "Selecting a radio should affect all radios in the group");
+
+ // Deselecting radio button.
+ g2radio2.checked = false;
+ verifyIndeterminateState(g2radio1, true,
+ "Deselecting a radio should affect all radios in the group");
+ verifyIndeterminateState(g2radio2, true,
+ "Deselecting a radio should affect all radios in the group");
+
+ // Move a selected radio button to another group.
+ g1radio3.name = "group2";
+
+ // The radios' state in the original group becomes indeterminated.
+ verifyIndeterminateState(g1radio1, true,
+ "Removing a radio from a group should affect all radios in the group");
+ verifyIndeterminateState(g1radio2, true,
+ "Removing a radio from a group should affect all radios in the group");
+
+ // The radios' state in the new group becomes determinated.
+ verifyIndeterminateState(g1radio3, false,
+ "Adding a radio from a group should affect all radios in the group");
+ verifyIndeterminateState(g2radio1, false,
+ "Adding a radio from a group should affect all radios in the group");
+ verifyIndeterminateState(g2radio2, false,
+ "Adding a radio from a group should affect all radios in the group");
+
+ // Change input type to 'text'.
+ g1radio3.type = "text";
+ verifyIndeterminateState(g1radio3, false,
+ "Input type text does not have an indeterminate state");
+ verifyIndeterminateState(g2radio1, true,
+ "Changing input type should affect all radios in the group");
+ verifyIndeterminateState(g2radio2, true,
+ "Changing input type should affect all radios in the group");
+}
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/forms/test_input_radio_radiogroup.html b/dom/html/test/forms/test_input_radio_radiogroup.html
new file mode 100644
index 000000000..86dd212b8
--- /dev/null
+++ b/dom/html/test/forms/test_input_radio_radiogroup.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=343444
+-->
+<head>
+ <title>Test for Bug 343444</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=343444">Mozilla Bug 343444</a>
+<p id="display"></p>
+<form>
+ <fieldset id="testradio">
+ <input type="radio" name="testradio" id="start"></input>
+ <input type="text" name="testradio"></input>
+ <input type="text" name="testradio"></input>
+ <input type="radio" name="testradio"></input>
+ <input type="text" name="testradio"></input>
+ <input type="radio" name="testradio"></input>
+ <input type="text" name="testradio"></input>
+ <input type="radio" name="testradio"></input>
+ <input type="radio" name="testradio"></input>
+ <input type="text" name="testradio"></input>
+ </fieldset>
+
+ <fieldset>
+ <input type="radio" name="testtwo" id="start2"></input>
+ <input type="radio" name="testtwo"></input>
+ <input type="radio" name="error" id="testtwo"></input>
+ <input type="radio" name="testtwo" id="end"></input>
+ </fieldset>
+
+ <fieldset>
+ <input type="radio" name="testthree" id="start3"></input>
+ <input type="radio" name="errorthree" id="testthree"></input>
+ </fieldset>
+</form>
+<script class="testbody" type="text/javascript">
+/** Test for Bug 343444 **/
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, startTest);
+function startTest() {
+ document.getElementById("start").focus();
+ var count=0;
+ while (count < 2) {
+ sendKey("DOWN");
+ is(document.activeElement.type, "radio", "radioGroup should ignore non-radio input fields");
+ if (document.activeElement.id == "start") {
+ count++;
+ }
+ }
+
+ document.getElementById("start2").focus();
+ count = 0;
+ while (count < 3) {
+ is(document.activeElement.name, "testtwo",
+ "radioGroup should only contain elements with the same @name")
+ sendKey("DOWN");
+ count++;
+ }
+
+ document.getElementById("start3").focus();
+ sendKey("DOWN");
+ is(document.activeElement.name, "testthree", "we don't have an infinite-loop");
+ SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/forms/test_input_radio_required.html b/dom/html/test/forms/test_input_radio_required.html
new file mode 100644
index 000000000..e1ba42914
--- /dev/null
+++ b/dom/html/test/forms/test_input_radio_required.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id={BUGNUMBER}
+-->
+<head>
+ <title>Test for Bug 1100535</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1100535">Mozilla Bug 1100535</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<form>
+ <input type="radio" name="a">
+</form>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+ var input = document.querySelector("input");
+ input.setAttribute("required", "x");
+ input.setAttribute("required", "y");
+ is(document.forms[0].checkValidity(), false);
+ input.required = false;
+ is(document.forms[0].checkValidity(), true);
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_range_attr_order.html b/dom/html/test/forms/test_input_range_attr_order.html
new file mode 100644
index 000000000..3d3d6d6f7
--- /dev/null
+++ b/dom/html/test/forms/test_input_range_attr_order.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=841941
+-->
+<head>
+ <title>Test @min/@max/@step order for range</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841941">Mozilla Bug 841941</a>
+<p id="display"></p>
+<div id="content">
+ <input type=range value=2 max=1.5 step=0.5>
+ <input type=range value=2 step=0.5 max=1.5>
+ <input type=range value=2 max=1.5 step=0.5>
+ <input type=range value=2 step=0.5 max=1.5>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 841941
+ * This test checks that the order in which @min/@max/@step are specified in
+ * markup makes no difference to the value that <input type=range> will be
+ * given. Basically this checks that sanitization of the value does not occur
+ * until after the parser has finished with the element.
+ */
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ test();
+ SimpleTest.finish();
+});
+
+function test() {
+ var ranges = document.querySelectorAll("input[type=range]");
+ for (var i = 0; i < ranges.length; i++) {
+ is(ranges.item(i).value, "1.5", "Check sanitization order for range " + i);
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_range_key_events.html b/dom/html/test/forms/test_input_range_key_events.html
new file mode 100644
index 000000000..efb1f7e4b
--- /dev/null
+++ b/dom/html/test/forms/test_input_range_key_events.html
@@ -0,0 +1,210 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=843725
+-->
+<head>
+ <title>Test key events for range</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=843725">Mozilla Bug 843725</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 843725
+ * This test checks how the value of <input type=range> changes in response to
+ * various key events while it is in various states.
+ **/
+SimpleTest.waitForExplicitFinish();
+
+// Turn off Spatial Navigation because it hijacks arrow keydown events:
+SimpleTest.waitForFocus(function() {
+ SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() {
+ test();
+ SimpleTest.finish();
+ });
+});
+
+const defaultMinimum = 0;
+const defaultMaximum = 100;
+const defaultStep = 1;
+
+// Helpers:
+// For the sake of simplicity, we do not currently support fractional value,
+// step, etc.
+
+function minimum(element) {
+ return Number(element.min || defaultMinimum);
+}
+
+function maximum(element) {
+ return Number(element.max || defaultMaximum);
+}
+
+function range(element) {
+ var max = maximum(element);
+ var min = minimum(element);
+ if (max < min) {
+ return 0;
+ }
+ return max - min;
+}
+
+function defaultValue(element) {
+ return minimum(element) + range(element)/2;
+}
+
+function value(element) {
+ return Number(element.value || defaultValue(element));
+}
+
+function step(element) {
+ var step = Number(element.step || defaultStep);
+ return step <= 0 ? defaultStep : step;
+}
+
+function clampToRange(value, element) {
+ var min = minimum(element);
+ var max = maximum(element);
+ if (max < min) {
+ return min;
+ }
+ if (value < min) {
+ return min;
+ }
+ if (value > max) {
+ return max;
+ }
+ return value;
+}
+
+// Functions used to specify expected test results:
+
+function valuePlusStep(element) {
+ return clampToRange(value(element) + step(element), element);
+}
+
+function valueMinusStep(element) {
+ return clampToRange(value(element) - step(element), element);
+}
+
+/**
+ * Returns the current value of the range plus whichever is greater of either
+ * 10% of the range or its current step value, clamped to the range's minimum/
+ * maximum. The reason for using the step if it is greater than 10% of the
+ * range is because otherwise the PgUp/PgDn keys would do nothing in that case.
+ */
+function valuePlusTenPctOrStep(element) {
+ var tenPct = range(element)/10;
+ var stp = step(element);
+ return clampToRange(value(element) + Math.max(tenPct, stp), element);
+}
+
+function valueMinusTenPctOrStep(element) {
+ var tenPct = range(element)/10;
+ var stp = step(element);
+ return clampToRange(value(element) - Math.max(tenPct, stp), element);
+}
+
+// Test table:
+
+const LTR = "ltr";
+const RTL = "rtl";
+
+var testTable = [
+ ["VK_LEFT", LTR, valueMinusStep],
+ ["VK_LEFT", RTL, valuePlusStep],
+ ["VK_RIGHT", LTR, valuePlusStep],
+ ["VK_RIGHT", RTL, valueMinusStep],
+ ["VK_UP", LTR, valuePlusStep],
+ ["VK_UP", RTL, valuePlusStep],
+ ["VK_DOWN", LTR, valueMinusStep],
+ ["VK_DOWN", RTL, valueMinusStep],
+ ["VK_PAGE_UP", LTR, valuePlusTenPctOrStep],
+ ["VK_PAGE_UP", RTL, valuePlusTenPctOrStep],
+ ["VK_PAGE_DOWN", LTR, valueMinusTenPctOrStep],
+ ["VK_PAGE_DOWN", RTL, valueMinusTenPctOrStep],
+ ["VK_HOME", LTR, minimum],
+ ["VK_HOME", RTL, minimum],
+ ["VK_END", LTR, maximum],
+ ["VK_END", RTL, maximum],
+]
+
+function test() {
+ var elem = document.createElement("input");
+ elem.type = "range";
+
+ var content = document.getElementById("content");
+ content.appendChild(elem);
+ elem.focus();
+
+ for (test of testTable) {
+ var [key, dir, expectedFunc] = test;
+ var oldVal, expectedVal;
+
+ elem.step = "2";
+ elem.style.direction = dir;
+ var flush = document.body.clientWidth;
+
+ // Start at middle:
+ elem.value = oldVal = defaultValue(elem);
+ expectedVal = expectedFunc(elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with value set to the midpoint (" + oldVal + ")");
+
+ // Same again:
+ expectedVal = expectedFunc(elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range");
+
+ // Start at maximum:
+ elem.value = oldVal = maximum(elem);
+ expectedVal = expectedFunc(elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with value set to the maximum (" + oldVal + ")");
+
+ // Same again:
+ expectedVal = expectedFunc(elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range");
+
+ // Start at minimum:
+ elem.value = oldVal = minimum(elem);
+ expectedVal = expectedFunc(elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with value set to the minimum (" + oldVal + ")");
+
+ // Same again:
+ expectedVal = expectedFunc(elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range");
+
+ // Test for a step value that is greater than 10% of the range:
+ elem.step = 20;
+ elem.value = 60;
+ expectedVal = expectedFunc(elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test " + key + " for " + dir + " range with a step that is greater than 10% of the range (step=" + elem.step + ")");
+
+ // Same again:
+ expectedVal = expectedFunc(elem);
+ synthesizeKey(key, {});
+ is(elem.value, String(expectedVal), "Test repeat of " + key + " for " + dir + " range");
+
+ // reset step:
+ elem.step = 2;
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_range_mouse_and_touch_events.html b/dom/html/test/forms/test_input_range_mouse_and_touch_events.html
new file mode 100644
index 000000000..4073fe139
--- /dev/null
+++ b/dom/html/test/forms/test_input_range_mouse_and_touch_events.html
@@ -0,0 +1,199 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=846380
+-->
+<head>
+ <title>Test mouse and touch events for range</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <style>
+ /* synthesizeMouse and synthesizeFunc uses getBoundingClientRect. We set
+ * the following properties to avoid fractional values in the rect returned
+ * by getBoundingClientRect in order to avoid rounding that would occur
+ * when event coordinates are internally converted to be relative to the
+ * top-left of the element. (Such rounding would make it difficult to
+ * predict exactly what value the input should take on for events at
+ * certain coordinates.)
+ */
+ input { margin: 0 ! important; width: 200px ! important; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=846380">Mozilla Bug 846380</a>
+<p id="display"></p>
+<div id="content">
+ <input id="range" type="range">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 846380
+ * This test checks how the value of <input type=range> changes in response to
+ * various mouse and touch events.
+ **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ test(synthesizeMouse, "click", "mousedown", "mousemove", "mouseup");
+ test(synthesizeTouch, "tap", "touchstart", "touchmove", "touchend");
+ SimpleTest.finish();
+});
+
+const MIDDLE_OF_RANGE = "50";
+const MINIMUM_OF_RANGE = "0";
+const MAXIMUM_OF_RANGE = "100";
+const QUARTER_OF_RANGE = "25";
+const THREE_QUARTERS_OF_RANGE = "75";
+
+function flush() {
+ // Flush style, specifically to flush the 'direction' property so that the
+ // browser uses the new value for thumb positioning.
+ var flush = document.body.clientWidth;
+}
+
+function test(synthesizeFunc, clickOrTap, startName, moveName, endName) {
+ var elem = document.getElementById("range");
+ elem.focus();
+ flush();
+
+ var width = parseFloat(window.getComputedStyle(elem).width);
+ var height = parseFloat(window.getComputedStyle(elem).height);
+ var borderLeft = parseFloat(window.getComputedStyle(elem).borderLeftWidth);
+ var borderTop = parseFloat(window.getComputedStyle(elem).borderTopWidth);
+ var paddingLeft = parseFloat(window.getComputedStyle(elem).paddingLeft);
+ var paddingTop = parseFloat(window.getComputedStyle(elem).paddingTop);
+
+ // Extrema for mouse/touch events:
+ var midY = height / 2 + borderTop + paddingTop;
+ var minX = borderLeft + paddingLeft;
+ var midX = minX + width / 2;
+ var maxX = minX + width;
+
+ // Test click/tap in the middle of the range:
+ elem.value = QUARTER_OF_RANGE;
+ synthesizeFunc(elem, midX, midY, {});
+ is(elem.value, MIDDLE_OF_RANGE, "Test " + clickOrTap + " in middle of range");
+
+ // Test mouse/touch dragging of ltr range:
+ elem.value = QUARTER_OF_RANGE;
+ synthesizeFunc(elem, midX, midY, { type: startName });
+ is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range");
+ synthesizeFunc(elem, minX, midY, { type: moveName });
+ is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to left of ltr range");
+
+ synthesizeFunc(elem, maxX, midY, { type: moveName });
+ is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to right of ltr range (" + moveName + ")");
+
+ synthesizeFunc(elem, maxX, midY, { type: endName });
+ is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to right of ltr range (" + endName + ")");
+
+ // Test mouse/touch dragging of rtl range:
+ elem.value = QUARTER_OF_RANGE;
+ elem.style.direction = "rtl";
+ flush();
+ synthesizeFunc(elem, midX, midY, { type: startName });
+ is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of rtl range");
+ synthesizeFunc(elem, minX, midY, { type: moveName });
+ is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to left of rtl range");
+
+ synthesizeFunc(elem, maxX, midY, { type: moveName });
+ is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to right of rtl range (" + moveName + ")");
+
+ synthesizeFunc(elem, maxX, midY, { type: endName });
+ is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to right of rtl range (" + endName + ")");
+
+ elem.style.direction = "ltr"; // reset direction
+ flush();
+
+ // Test mouse/touch capturing by moving pointer to a position outside the range:
+ elem.value = QUARTER_OF_RANGE;
+ synthesizeFunc(elem, midX, midY, { type: startName });
+ is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range");
+ synthesizeFunc(elem, maxX+100, midY, { type: moveName });
+ is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to position outside range (" + moveName + ")");
+
+ synthesizeFunc(elem, maxX+100, midY, { type: endName });
+ is(elem.value, MAXIMUM_OF_RANGE, "Test dragging of range to position outside range (" + endName + ")");
+
+ // Test mouse/touch capturing by moving pointer to a position outside a rtl range:
+ elem.value = QUARTER_OF_RANGE;
+ elem.style.direction = "rtl";
+ flush();
+ synthesizeFunc(elem, midX, midY, { type: startName });
+ is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of rtl range");
+ synthesizeFunc(elem, maxX+100, midY, { type: moveName });
+ is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to position outside range (" + moveName + ")");
+
+ synthesizeFunc(elem, maxX+100, midY, { type: endName });
+ is(elem.value, MINIMUM_OF_RANGE, "Test dragging of range to position outside range (" + endName + ")");
+
+ elem.style.direction = "ltr"; // reset direction
+ flush();
+
+ // Test mouse/touch events with modifiers are ignored:
+ var modifiers = ["shiftKey", "ctrlKey", "altKey", "metaKey", "accelKey", "altGrKey", "fnKey", "osKey"];
+ for (var modifier of modifiers) {
+ elem.value = QUARTER_OF_RANGE;
+ var eventParams = {};
+ eventParams[modifier] = true;
+ synthesizeFunc(elem, midX, midY, eventParams);
+ is(elem.value, QUARTER_OF_RANGE, "Test " + clickOrTap + " in the middle of range with " + modifier + " modifier key is ignored");
+ }
+
+ // Test that preventDefault() works:
+ function preventDefault(e) {
+ e.preventDefault();
+ }
+ elem.value = QUARTER_OF_RANGE;
+ elem.addEventListener(startName, preventDefault, false);
+ synthesizeFunc(elem, midX, midY, {});
+ is(elem.value, QUARTER_OF_RANGE, "Test that preventDefault() works");
+ elem.removeEventListener(startName, preventDefault, false);
+
+ // Test that changing the input type in the middle of a drag cancels the drag:
+ elem.value = QUARTER_OF_RANGE;
+ synthesizeFunc(elem, midX, midY, { type: startName });
+ is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range");
+ elem.type = "text";
+ is(elem.value, QUARTER_OF_RANGE, "Test that changing the input type cancels a drag");
+ synthesizeFunc(elem, midX, midY, { type: endName });
+ is(elem.value, QUARTER_OF_RANGE, "Test that changing the input type cancels a drag (after " + endName + ")");
+ elem.type = "range";
+
+ // Check that we do not drag when the mousedown/touchstart occurs outside the range:
+ elem.value = QUARTER_OF_RANGE;
+ synthesizeFunc(elem, maxX+100, midY, { type: startName });
+ is(elem.value, QUARTER_OF_RANGE, "Test " + startName + " outside range doesn't change its value");
+ synthesizeFunc(elem, midX, midY, { type: moveName });
+ is(elem.value, QUARTER_OF_RANGE, "Test dragging is not occurring when " + startName + " was outside range");
+
+ synthesizeFunc(elem, midX, midY, { type: endName });
+ is(elem.value, QUARTER_OF_RANGE, "Test dragging is not occurring when " + startName + " was outside range");
+
+ elem.focus(); // RESTORE FOCUS SO WE GET THE FOCUSED STYLE FOR TESTING OR ELSE minX/midX/maxX may be wrong!
+
+ // Check what happens when a value changing key is pressed during a drag:
+ elem.value = QUARTER_OF_RANGE;
+ synthesizeFunc(elem, midX, midY, { type: startName });
+ is(elem.value, MIDDLE_OF_RANGE, "Test " + startName + " in middle of range");
+ synthesizeKey("VK_HOME", {});
+ // The VK_HOME tests are disabled until I can figure out why they fail on Android -jwatt
+ //is(elem.value, MINIMUM_OF_RANGE, "Test VK_HOME during a drag sets the value to the minimum of the range");
+ synthesizeFunc(elem, midX+100, midY, { type: moveName });
+ is(elem.value, MAXIMUM_OF_RANGE, "Test " + moveName + " outside range after key press that occurred during a drag changes the value");
+ synthesizeFunc(elem, midX, midY, { type: moveName });
+ is(elem.value, MIDDLE_OF_RANGE, "Test " + moveName + " in middle of range");
+ synthesizeKey("VK_HOME", {});
+ //is(elem.value, MINIMUM_OF_RANGE, "Test VK_HOME during a drag sets the value to the minimum of the range (second time)");
+ synthesizeFunc(elem, maxX+100, midY, { type: endName });
+ is(elem.value, MAXIMUM_OF_RANGE, "Test " + endName + " outside range after key press that occurred during a drag changes the value");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_range_rounding.html b/dom/html/test/forms/test_input_range_rounding.html
new file mode 100644
index 000000000..dfbca36ce
--- /dev/null
+++ b/dom/html/test/forms/test_input_range_rounding.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=853525
+-->
+<head>
+ <title>Test key events for range</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=853525">Mozilla Bug 853525</a>
+<p id="display"></p>
+<div id="content">
+ <input id=range type=range value=0 step=0.01 max=1>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/**
+ * Test for Bug 853525
+ * This test checks that when <input type=range> has fractional step values,
+ * the values that a content author will see in their script will not have
+ * ugly rounding errors.
+ **/
+SimpleTest.waitForExplicitFinish();
+// Turn off Spatial Navigation because it hijacks arrow keydown events:
+SimpleTest.waitForFocus(function() {
+ SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() {
+ test();
+ SimpleTest.finish();
+ });
+});
+
+/**
+ * We can _NOT_ generate these values by looping and simply incrementing a
+ * variable by 0.01 and stringifying it, since we'll end up with strings like
+ * "0.060000000000000005" due to the inability of binary floating point numbers
+ * to accurately represent decimal values.
+ */
+var stepVals = [
+ "0", "0.01", "0.02", "0.03", "0.04", "0.05", "0.06", "0.07", "0.08", "0.09",
+ "0.1", "0.11", "0.12", "0.13", "0.14", "0.15", "0.16", "0.17", "0.18", "0.19",
+ "0.2", "0.21", "0.22", "0.23", "0.24", "0.25", "0.26", "0.27", "0.28", "0.29",
+ "0.3", "0.31", "0.32", "0.33", "0.34", "0.35", "0.36", "0.37", "0.38", "0.39",
+ "0.4", "0.41", "0.42", "0.43", "0.44", "0.45", "0.46", "0.47", "0.48", "0.49",
+ "0.5", "0.51", "0.52", "0.53", "0.54", "0.55", "0.56", "0.57", "0.58", "0.59",
+ "0.6", "0.61", "0.62", "0.63", "0.64", "0.65", "0.66", "0.67", "0.68", "0.69",
+ "0.7", "0.71", "0.72", "0.73", "0.74", "0.75", "0.76", "0.77", "0.78", "0.79",
+ "0.8", "0.81", "0.82", "0.83", "0.84", "0.85", "0.86", "0.87", "0.88", "0.89",
+ "0.9", "0.91", "0.92", "0.93", "0.94", "0.95", "0.96", "0.97", "0.98", "0.99",
+ "1"
+];
+
+var pgUpDnVals = [
+ "0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "1"
+];
+
+function test() {
+ var elem = document.getElementById("range");
+
+ elem.focus();
+
+ for (var i = 1; i < pgUpDnVals.length; ++i) {
+ synthesizeKey("VK_PAGE_UP", {});
+ is(elem.value, pgUpDnVals[i], "Test VK_PAGE_UP");
+ is(elem.validity.valid, true, "Check element is valid for value " + pgUpDnVals[i]);
+ }
+
+ for (var i = pgUpDnVals.length - 2; i >= 0; --i) {
+ synthesizeKey("VK_PAGE_DOWN", {});
+ is(elem.value, pgUpDnVals[i], "Test VK_PAGE_DOWN");
+ is(elem.validity.valid, true, "Check element is valid for value " + pgUpDnVals[i]);
+ }
+
+ for (var i = 1; i < stepVals.length; ++i) {
+ synthesizeKey("VK_UP", {});
+ is(elem.value, stepVals[i], "Test VK_UP");
+ is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]);
+ }
+
+ for (var i = stepVals.length - 2; i >= 0; --i) {
+ synthesizeKey("VK_DOWN", {});
+ is(elem.value, stepVals[i], "Test VK_DOWN");
+ is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]);
+ }
+
+ for (var i = 1; i < stepVals.length; ++i) {
+ elem.stepUp();
+ is(elem.value, stepVals[i], "Test stepUp()");
+ is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]);
+ }
+
+ for (var i = stepVals.length - 2; i >= 0; --i) {
+ elem.stepDown();
+ is(elem.value, stepVals[i], "Test stepDown()");
+ is(elem.validity.valid, true, "Check element is valid for value " + stepVals[i]);
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_sanitization.html b/dom/html/test/forms/test_input_sanitization.html
new file mode 100644
index 000000000..cd9877fdf
--- /dev/null
+++ b/dom/html/test/forms/test_input_sanitization.html
@@ -0,0 +1,565 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=549475
+-->
+<head>
+ <title>Test for Bug 549475</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=549475">Mozilla Bug 549475</a>
+<p id="display"></p>
+<pre id="test">
+<div id='content'>
+ <form>
+ </form>
+</div>
+<script type="application/javascript">
+
+SimpleTest.requestLongerTimeout(2);
+
+/**
+ * This files tests the 'value sanitization algorithm' for the various input
+ * types. Note that an input's value is affected by more than just its type's
+ * value sanitization algorithm; e.g. some type=range has actions that the user
+ * agent must perform to change the element's value to avoid underflow/overflow
+ * and step mismatch (when possible). We specifically avoid triggering these
+ * other actions here so that this test only tests the value sanitization
+ * algorithm for the various input types.
+ *
+ * XXXjwatt splitting out testing of the value sanitization algorithm and
+ * "other things" that affect .value makes it harder to know what we're testing
+ * and what we've missed, because what's included in the value sanitization
+ * algorithm and what's not is different from input type to input type. It
+ * seems to me it would be better to have a test (maybe one per type) focused
+ * on testing .value for permutations of all other inputs that can affect it.
+ * The value sanitization algorithm is just an internal spec concept after all.
+ */
+
+// We buffer up the results of sets of sub-tests, and avoid outputting log
+// entries for them all if they all pass. Otherwise, we have an enormous amount
+// of test output.
+
+var delayedTests = [];
+var anyFailedDelayedTests = false;
+
+function delayed_is(actual, expected, description)
+{
+ var result = actual == expected;
+ delayedTests.push({ actual: actual, expected: expected, description: description });
+ if (!result) {
+ anyFailedDelayedTests = true;
+ }
+}
+
+function flushDelayedTests(description)
+{
+ if (anyFailedDelayedTests) {
+ info("Outputting individual results for \"" + description + "\" due to failures in subtests");
+ for (var test of delayedTests) {
+ is(test.actual, test.expected, test.description);
+ }
+ } else {
+ ok(true, description + " (" + delayedTests.length + " subtests)");
+ }
+ delayedTests = [];
+ anyFailedDelayedTests = false;
+}
+
+// We are excluding "file" because it's too different from the other types.
+// And it has no sanitizing algorithm.
+var inputTypes =
+[
+ "text", "password", "search", "tel", "hidden", "checkbox", "radio",
+ "submit", "image", "reset", "button", "email", "url", "number", "date",
+ "time", "range", "color", "month", "week", "datetime-local"
+];
+
+var valueModeValue =
+[
+ "text", "search", "url", "tel", "email", "password", "date", "datetime",
+ "month", "week", "time", "datetime-local", "number", "range", "color",
+];
+
+function sanitizeDate(aValue)
+{
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-date-string
+ function getNumbersOfDaysInMonth(aMonth, aYear) {
+ if (aMonth === 2) {
+ return (aYear % 400 === 0 || (aYear % 100 != 0 && aYear % 4 === 0)) ? 29 : 28;
+ }
+ return (aMonth === 1 || aMonth === 3 || aMonth === 5 || aMonth === 7 ||
+ aMonth === 8 || aMonth === 10 || aMonth === 12) ? 31 : 30;
+ }
+
+ var match = /^([0-9]{4,})-([0-9]{2})-([0-9]{2})$/.exec(aValue);
+ if (!match) {
+ return "";
+ }
+ var year = Number(match[1]);
+ if (year === 0) {
+ return "";
+ }
+ var month = Number(match[2]);
+ if (month > 12 || month < 1) {
+ return "";
+ }
+ var day = Number(match[3]);
+ return 1 <= day && day <= getNumbersOfDaysInMonth(month, year) ? aValue : "";
+}
+
+function sanitizeTime(aValue)
+{
+ // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-time-string
+ var match = /^([0-9]{2}):([0-9]{2})(.*)$/.exec(aValue);
+ if (!match) {
+ return "";
+ }
+ var hours = match[1];
+ if (hours < 0 || hours > 23) {
+ return "";
+ }
+ var minutes = match[2];
+ if (minutes < 0 || minutes > 59) {
+ return "";
+ }
+ var other = match[3];
+ if (other == "") {
+ return aValue;
+ }
+ match = /^:([0-9]{2})(.*)$/.exec(other);
+ if (!match) {
+ return "";
+ }
+ var seconds = match[1];
+ if (seconds < 0 || seconds > 59) {
+ return "";
+ }
+ var other = match[2];
+ if (other == "") {
+ return aValue;
+ }
+ match = /^.([0-9]{1,3})$/.exec(other);
+ if (!match) {
+ return "";
+ }
+ return aValue;
+}
+
+function sanitizeDateTimeLocal(aValue)
+{
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-local-date-and-time-string
+ if (aValue.length < 16) {
+ return "";
+ }
+
+ var separator = aValue[10];
+ if (separator != "T" && separator != " ") {
+ return "";
+ }
+
+ var [date, time] = aValue.split(separator);
+ if (!sanitizeDate(date)) {
+ return "";
+ }
+
+ if (!sanitizeTime(time)) {
+ return "";
+ }
+
+ // Normalize datetime-local string.
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-normalised-local-date-and-time-string
+ if (separator == " ") {
+ aValue = date + "T" + time;
+ }
+
+ if (aValue.length == 16) {
+ return aValue;
+ }
+
+ if (aValue.length > 19) {
+ var milliseconds = aValue.substring(20);
+ if (Number(milliseconds) != 0) {
+ return aValue;
+ }
+ aValue = aValue.slice(0, 19);
+ }
+
+ var seconds = aValue.substring(17);
+ if (Number(seconds) != 0) {
+ return aValue;
+ }
+ aValue = aValue.slice(0, 16);
+
+ return aValue;
+}
+
+function sanitizeValue(aType, aValue)
+{
+ // http://www.whatwg.org/html/#value-sanitization-algorithm
+ switch (aType) {
+ case "text":
+ case "password":
+ case "search":
+ case "tel":
+ return aValue.replace(/[\n\r]/g, "");
+ case "url":
+ case "email":
+ return aValue.replace(/[\n\r]/g, "").replace(/^[\u0020\u0009\t\u000a\u000c\u000d]+|[\u0020\u0009\t\u000a\u000c\u000d]+$/g, "");
+ case "number":
+ return isNaN(Number(aValue)) ? "" : aValue;
+ case "range":
+ var defaultMinimum = 0;
+ var defaultMaximum = 100;
+ var value = Number(aValue);
+ if (isNaN(value)) {
+ return ((defaultMaximum - defaultMinimum)/2).toString(); // "50"
+ }
+ if (value < defaultMinimum) {
+ return defaultMinimum.toString();
+ }
+ if (value > defaultMaximum) {
+ return defaultMaximum.toString();
+ }
+ return aValue;
+ case "date":
+ return sanitizeDate(aValue);
+ case "time":
+ return sanitizeTime(aValue);
+ case "month":
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-month-string
+ var match = /^([0-9]{4,})-([0-9]{2})$/.exec(aValue);
+ if (!match) {
+ return "";
+ }
+ var year = Number(match[1]);
+ if (year === 0) {
+ return "";
+ }
+ var month = Number(match[2]);
+ if (month > 12 || month < 1) {
+ return "";
+ }
+ return aValue;
+ case "week":
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-week-string
+ function isLeapYear(aYear) {
+ return ((aYear % 4 == 0) && (aYear % 100 != 0)) || (aYear % 400 == 0);
+ }
+ function getDayofWeek(aYear, aMonth, aDay) { /* 0 = Sunday */
+ // Tomohiko Sakamoto algorithm.
+ var monthTable = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4];
+ aYear -= Number(aMonth < 3);
+
+ return (aYear + parseInt(aYear / 4) - parseInt(aYear / 100) +
+ parseInt(aYear / 400) + monthTable[aMonth - 1] + aDay) % 7;
+ }
+ function getMaximumWeekInYear(aYear) {
+ var day = getDayofWeek(aYear, 1, 1);
+ return day == 4 || (day == 3 && isLeapYear(aYear)) ? 53 : 52;
+ }
+
+ var match = /^([0-9]{4,})-W([0-9]{2})$/.exec(aValue);
+ if (!match) {
+ return "";
+ }
+ var year = Number(match[1]);
+ if (year === 0) {
+ return "";
+ }
+ var week = Number(match[2]);
+ if (week > 53 || month < 1) {
+ return "";
+ }
+ return 1 <= week && week <= getMaximumWeekInYear(year) ? aValue : "";
+ case "datetime-local":
+ return sanitizeDateTimeLocal(aValue);
+ case "color":
+ return /^#[0-9A-Fa-f]{6}$/.exec(aValue) ? aValue.toLowerCase() : "#000000";
+ default:
+ return aValue;
+ }
+}
+
+function checkSanitizing(element, inputTypeDescription)
+{
+ var testData =
+ [
+ // For text, password, search, tel, email:
+ "\n\rfoo\n\r",
+ "foo\n\rbar",
+ " foo ",
+ " foo\n\r bar ",
+ // For url:
+ "\r\n foobar \n\r",
+ "\u000B foo \u000B",
+ "\u000A foo \u000A",
+ "\u000C foo \u000C",
+ "\u000d foo \u000d",
+ "\u0020 foo \u0020",
+ " \u0009 foo \u0009 ",
+ // For number and range:
+ "42",
+ "13.37",
+ "1.234567898765432",
+ "12foo",
+ "1e2",
+ "3E42",
+ // For date:
+ "1970-01-01",
+ "1234-12-12",
+ "1234567890-01-02",
+ "2012-12-31",
+ "2012-02-29",
+ "2000-02-29",
+ "1234",
+ "1234-",
+ "12345",
+ "1234-01",
+ "1234-012",
+ "1234-01-",
+ "12-12",
+ "999-01-01",
+ "1234-56-78-91",
+ "1234-567-78",
+ "1234--7-78",
+ "abcd-12-12",
+ "thisinotadate",
+ "2012-13-01",
+ "1234-12-42",
+ " 2012-13-01",
+ " 123-01-01",
+ "2012- 3-01",
+ "12- 10- 01",
+ " 12-0-1",
+ "2012-3-001",
+ "2012-12-00",
+ "2012-12-1r",
+ "2012-11-31",
+ "2011-02-29",
+ "2100-02-29",
+ "a2000-01-01",
+ "2000a-01-0'",
+ "20aa00-01-01",
+ "2000a2000-01-01",
+ "2000-1-1",
+ "2000-1-01",
+ "2000-01-1",
+ "2000-01-01 ",
+ "2000- 01-01",
+ "-1970-01-01",
+ "0000-00-00",
+ "0001-00-00",
+ "0000-01-01",
+ "1234-12 12",
+ "1234 12-12",
+ "1234 12 12",
+ // For time:
+ "1",
+ "10",
+ "10:",
+ "10:1",
+ "21:21",
+ ":21:21",
+ "-21:21",
+ " 21:21",
+ "21-21",
+ "21:21:",
+ "21:211",
+ "121:211",
+ "21:21 ",
+ "00:00",
+ "-1:00",
+ "24:00",
+ "00:60",
+ "01:01",
+ "23:59",
+ "99:99",
+ "8:30",
+ "19:2",
+ "19:a2",
+ "4c:19",
+ "10:.1",
+ "1.:10",
+ "13:37:42",
+ "13:37.42",
+ "13:37:42 ",
+ "13:37:42.",
+ "13:37:61.",
+ "13:37:00",
+ "13:37:99",
+ "13:37:b5",
+ "13:37:-1",
+ "13:37:.1",
+ "13:37:1.",
+ "13:37:42.001",
+ "13:37:42.001",
+ "13:37:42.abc",
+ "13:37:42.00c",
+ "13:37:42.a23",
+ "13:37:42.12e",
+ "13:37:42.1e1",
+ "13:37:42.e11",
+ "13:37:42.1",
+ "13:37:42.99",
+ "13:37:42.0",
+ "13:37:42.00",
+ "13:37:42.000",
+ "13:37:42.-1",
+ "13:37:42.1.1",
+ "13:37:42.1,1",
+ "13:37:42.",
+ "foo12:12",
+ "13:37:42.100000000000",
+ // For color
+ "#00ff00",
+ "#000000",
+ "red",
+ "#0f0",
+ "#FFFFAA",
+ "FFAABB",
+ "fFAaBb",
+ "FFAAZZ",
+ "ABCDEF",
+ "#7654321",
+ // For month
+ "1970-01",
+ "1234-12",
+ "123456789-01",
+ "2013-13",
+ "0000-00",
+ "2015-00",
+ "0001-01",
+ "1-1",
+ "888-05",
+ "2013-3",
+ "2013-may",
+ "2000-1a",
+ "2013-03-13",
+ "december",
+ "abcdef",
+ "12",
+ " 2013-03",
+ "2013 - 03",
+ "2013 03",
+ "2013/03",
+ // For week
+ "1970-W01",
+ "1970-W53",
+ "1964-W53",
+ "1900-W10",
+ "2004-W53",
+ "2065-W53",
+ "2099-W53",
+ "2010-W53",
+ "2016-W30",
+ "1900-W3",
+ "2016-w30",
+ "2016-30",
+ "16-W30",
+ "2016-Week30",
+ "2000-100",
+ "0000-W01",
+ "00-W01",
+ "123456-W05",
+ "1985-W100",
+ "week",
+ // For datetime-local
+ "1970-01-01T00:00",
+ "1970-01-01Z12:00",
+ "1970-01-01 00:00:00",
+ "1970-01-01T00:00:00.0",
+ "1970-01-01T00:00:00.00",
+ "1970-01-01T00:00:00.000",
+ "1970-01-01 00:00:00.20",
+ "1234567-01-01T12:00",
+ "2016-13-01T12:00",
+ "2016-12-32T12:00",
+ "2016-11-08 15:40:30.0",
+ "2016-11-08T15:40:30.00",
+ "2016-11-07T17:30:10",
+ "2016-12-1T12:45",
+ "2016-12-01T12:45:30.123456",
+ "2016-12-01T24:00",
+ "2016-12-01T12:88:30",
+ "2016-12-01T12:30:99",
+ "2016-12-01T12:30:100",
+ "2016-12-01",
+ "2016-12-01T",
+ "2016-Dec-01T00:00",
+ "12-05-2016T00:00",
+ "datetime-local"
+ ];
+
+ for (value of testData) {
+ element.setAttribute('value', value);
+ delayed_is(element.value, sanitizeValue(type, value),
+ "The value has not been correctly sanitized for type=" + type);
+ delayed_is(element.getAttribute('value'), value,
+ "The content value should not have been sanitized");
+
+ if (type in valueModeValue) {
+ element.setAttribute('value', 'tulip');
+ element.value = value;
+ delayed_is(element.value, sanitizeValue(type, value),
+ "The value has not been correctly sanitized for type=" + type);
+ delayed_is(element.getAttribute('value'), 'tulip',
+ "The content value should not have been sanitized");
+ }
+
+ element.setAttribute('value', '');
+ form.reset();
+ element.type = 'checkbox'; // We know this type has no sanitizing algorithm.
+ element.setAttribute('value', value);
+ delayed_is(element.value, value, "The value should not have been sanitized");
+ element.type = type;
+ delayed_is(element.value, sanitizeValue(type, value),
+ "The value has not been correctly sanitized for type=" + type);
+ delayed_is(element.getAttribute('value'), value,
+ "The content value should not have been sanitized");
+
+ element.setAttribute('value', '');
+ form.reset();
+ element.setAttribute('value', value);
+ form.reset();
+ delayed_is(element.value, sanitizeValue(type, value),
+ "The value has not been correctly sanitized for type=" + type);
+ delayed_is(element.getAttribute('value'), value,
+ "The content value should not have been sanitized");
+
+ // Cleaning-up.
+ element.setAttribute('value', '');
+ form.reset();
+ }
+
+ flushDelayedTests(inputTypeDescription);
+}
+
+for (type of inputTypes) {
+ var form = document.forms[0];
+ var element = document.createElement("input");
+ element.style.display = "none";
+ element.type = type;
+ form.appendChild(element);
+
+ checkSanitizing(element, "type=" + type + ", no frame, no editor");
+
+ element.style.display = "";
+ checkSanitizing(element, "type=" + type + ", frame, no editor");
+
+ element.focus();
+ element.blur();
+ checkSanitizing(element, "type=" + type + ", frame, editor");
+
+ element.style.display = "none";
+ checkSanitizing(element, "type=" + type + ", no frame, editor");
+
+ form.removeChild(element);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html b/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html
new file mode 100644
index 000000000..829daa8c9
--- /dev/null
+++ b/dom/html/test/forms/test_input_textarea_set_value_no_scroll.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=829606
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 829606</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript;version=1.7">
+
+ /** Test for Bug 829606 **/
+ /*
+ * This test checks that setting .value on an text field (input or textarea)
+ * doesn't scroll the field to its beginning.
+ */
+
+ SimpleTest.waitForExplicitFinish();
+
+ var gTestRunner = null;
+
+ function test(aElementName)
+ {
+ var element = document.getElementsByTagName(aElementName)[0];
+ element.focus();
+
+ var baseSnapshot = snapshotWindow(window);
+
+ // This is a sanity check.
+ var s2 = snapshotWindow(window);
+ var results = compareSnapshots(baseSnapshot, snapshotWindow(window), true);
+ ok(results[0], "sanity check: screenshots should be the same");
+
+ element.selectionStart = element.selectionEnd = element.value.length;
+
+ setTimeout(function() {
+ synthesizeKey('f', {});
+
+ var selectionAtTheEndSnapshot = snapshotWindow(window);
+ results = compareSnapshots(baseSnapshot, selectionAtTheEndSnapshot, false);
+ ok(results[0], "after appending a character, string should have changed");
+
+ element.value = element.value;
+ var tmpSnapshot = snapshotWindow(window);
+
+ results = compareSnapshots(baseSnapshot, tmpSnapshot, false);
+ ok(results[0], "re-settig the value should change nothing");
+
+ results = compareSnapshots(selectionAtTheEndSnapshot, tmpSnapshot, true);
+ ok(results[0], "re-settig the value should change nothing");
+
+ element.selectionStart = element.selectionEnd = 0;
+ element.blur();
+
+ gTestRunner.next();
+ }, 0);
+ }
+
+ // This test checks that when a textarea has a long list of values and the
+ // textarea's value is then changed, the values are shown correctly.
+ function testCorrectUpdateOnScroll()
+ {
+ var textarea = document.createElement('textarea');
+ textarea.rows = 5;
+ textarea.cols = 10;
+ textarea.value = 'a\nb\nc\nd';
+ document.getElementById('content').appendChild(textarea);
+
+ var baseSnapshot = snapshotWindow(window);
+
+ textarea.value = '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n';
+ textarea.selectionStart = textarea.selectionEnd = textarea.value.length;
+
+ var fullSnapshot = snapshotWindow(window);
+ var results = compareSnapshots(baseSnapshot, fullSnapshot, false);
+ ok(results[0], "sanity check: screenshots should not be the same");
+
+ textarea.value = 'a\nb\nc\nd';
+
+ var tmpSnapshot = snapshotWindow(window);
+ results = compareSnapshots(baseSnapshot, tmpSnapshot, true);
+ ok(results[0], "textarea view should look like the beginning");
+
+ setTimeout(function() {
+ gTestRunner.next();
+ }, 0);
+ }
+
+ function runTest()
+ {
+ test('input');
+ yield undefined;
+ test('textarea');
+ yield undefined;
+ testCorrectUpdateOnScroll();
+ yield undefined;
+ SimpleTest.finish();
+ yield undefined;
+ }
+
+ gTestRunner = runTest();
+
+ SimpleTest.waitForFocus(function() {
+ gTestRunner.next();
+ });;
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=829606">Mozilla Bug 829606</a>
+<p id="display"></p>
+<div id="content">
+ <textarea rows='1' cols='5' style='-moz-appearance:none;'>this is a \n long text</textarea>
+ <input size='5' value="this is a very long text" style='-moz-appearance:none;'>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_time_focus_blur_events.html b/dom/html/test/forms/test_input_time_focus_blur_events.html
new file mode 100644
index 000000000..483741477
--- /dev/null
+++ b/dom/html/test/forms/test_input_time_focus_blur_events.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1301306
+-->
+<head>
+<title>Test for Bug 1301306</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1301306">Mozilla Bug 722599</a>
+<p id="display"></p>
+<div id="content">
+<input type="time" id="input_time" onfocus="++focusEvent" onblur="++blurEvent"
+ onfocusin="++focusInEvent" onfocusout="++focusOutEvent">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/**
+ * Test for Bug 1301306.
+ * This test checks that when moving inside the time input element, e.g. jumping
+ * through the inner text boxes, does not fire extra focus/blur events.
+ **/
+
+var focusEvent = 0;
+var focusInEvent = 0;
+var focusOutEvent = 0;
+var blurEvent = 0;
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ test();
+ SimpleTest.finish();
+});
+
+function test() {
+ var time = document.getElementById("input_time");
+ time.focus();
+ is(focusEvent, 1, "time input element should have dispatched focus event.");
+ is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+ is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
+ is(blurEvent, 0, "time input element should not have dispatched blur event.");
+
+ // Move around inside the input element's input box.
+ synthesizeKey("VK_TAB", {});
+ is(focusEvent, 1, "time input element should not have dispatched focus event.");
+ is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+ is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
+ is(blurEvent, 0, "time input element should not have dispatched blur event.");
+
+ synthesizeKey("VK_RIGHT", {});
+ is(focusEvent, 1, "time input element should not have dispatched focus event.");
+ is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+ is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
+ is(blurEvent, 0, "time input element should not have dispatched blur event.");
+
+ synthesizeKey("VK_LEFT", {});
+ is(focusEvent, 1, "time input element should not have dispatched focus event.");
+ is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+ is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
+ is(blurEvent, 0, "time input element should not have dispatched blur event.");
+
+ synthesizeKey("VK_RIGHT", {});
+ is(focusEvent, 1, "time input element should not have dispatched focus event.");
+ is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+ is(focusOutEvent, 0, "time input element should not have dispatched focusout event.");
+ is(blurEvent, 0, "time input element should not have dispatched blur event.");
+
+ time.blur();
+ is(focusEvent, 1, "time input element should not have dispatched focus event.");
+ is(focusInEvent, 1, "time input element should have dispatched focusin event.");
+ is(focusOutEvent, 1, "time input element should not have dispatched focusout event.");
+ is(blurEvent, 1, "time input element should have dispatched blur event.");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_time_key_events.html b/dom/html/test/forms/test_input_time_key_events.html
new file mode 100644
index 000000000..755db38ff
--- /dev/null
+++ b/dom/html/test/forms/test_input_time_key_events.html
@@ -0,0 +1,197 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1288591
+-->
+<head>
+ <title>Test key events for time control</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <meta charset="UTF-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1288591">Mozilla Bug 1288591</a>
+<p id="display"></p>
+<div id="content">
+ <input id="input" type="time">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+// Turn off Spatial Navigation because it hijacks arrow keydown events:
+SimpleTest.waitForFocus(function() {
+ SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, function() {
+ test();
+ SimpleTest.finish();
+ });
+});
+
+var testData = [
+ /**
+ * keys: keys to send to the input element.
+ * initialVal: initial value set to the input element.
+ * expectedVal: expected value of the input element after sending the keys.
+ */
+ {
+ // Type 1030 and select AM.
+ keys: ["1030", "VK_DOWN"],
+ initialVal: "",
+ expectedVal: "10:30"
+ },
+ {
+ // Type 3 in the hour field will automatically advance to the minute field.
+ keys: ["330", "VK_DOWN"],
+ initialVal: "",
+ expectedVal: "03:30"
+ },
+ {
+ // Type 5 in the hour field will automatically advance to the minute field.
+ // Type 7 in the minute field will automatically advance to the AM/PM field.
+ keys: ["57", "VK_DOWN"],
+ initialVal: "",
+ expectedVal: "05:07"
+ },
+ {
+ // Advance to AM/PM field and change to PM.
+ keys: ["VK_TAB", "VK_TAB", "VK_DOWN"],
+ initialVal: "10:30",
+ expectedVal: "22:30"
+ },
+ {
+ // Right key should do the same thing as TAB key.
+ keys: ["VK_RIGHT", "VK_RIGHT", "VK_DOWN"],
+ initialVal: "10:30",
+ expectedVal: "22:30"
+ },
+ {
+ // Advance to minute field then back to hour field and decrement.
+ keys: ["VK_RIGHT", "VK_LEFT", "VK_DOWN"],
+ initialVal: "10:30",
+ expectedVal: "09:30"
+ },
+ {
+ // Focus starts on the first field, hour in this case, and increment.
+ keys: ["VK_UP"],
+ initialVal: "16:00",
+ expectedVal: "17:00"
+ },
+ {
+ // Advance to minute field and decrement.
+ keys: ["VK_TAB", "VK_DOWN"],
+ initialVal: "16:00",
+ expectedVal: "16:59"
+ },
+ {
+ // Advance to minute field and increment.
+ keys: ["VK_TAB", "VK_UP"],
+ initialVal: "16:59",
+ expectedVal: "16:00"
+ },
+ {
+ // PageUp on hour field increments hour by 3.
+ keys: ["VK_PAGE_UP"],
+ initialVal: "05:00",
+ expectedVal: "08:00"
+ },
+ {
+ // PageDown on hour field decrements hour by 3.
+ keys: ["VK_PAGE_DOWN"],
+ initialVal: "05:00",
+ expectedVal: "02:00"
+ },
+ {
+ // PageUp on minute field increments minute by 10.
+ keys: ["VK_TAB", "VK_PAGE_UP"],
+ initialVal: "14:00",
+ expectedVal: "14:10"
+ },
+ {
+ // PageDown on minute field decrements minute by 10.
+ keys: ["VK_TAB", "VK_PAGE_DOWN"],
+ initialVal: "14:00",
+ expectedVal: "14:50"
+ },
+ {
+ // Home key on hour field sets it to the minimum hour, which is 1 in 12-hour
+ // clock.
+ keys: ["VK_HOME"],
+ initialVal: "03:10",
+ expectedVal: "01:10"
+ },
+ {
+ // End key on hour field sets it to the maximum hour, which is 12 in 12-hour
+ // clock.
+ keys: ["VK_END"],
+ initialVal: "03:10",
+ expectedVal: "00:10"
+ },
+ {
+ // Home key on minute field sets it to the minimum minute, which is 0.
+ keys: ["VK_TAB", "VK_HOME"],
+ initialVal: "19:30",
+ expectedVal: "19:00"
+ },
+ {
+ // End key on minute field sets it to the minimum minute, which is 59.
+ keys: ["VK_TAB", "VK_END"],
+ initialVal: "19:30",
+ expectedVal: "19:59"
+ },
+ // Second field will show up when needed.
+ {
+ // PageUp on second field increments second by 10.
+ keys: ["VK_TAB", "VK_TAB", "VK_PAGE_UP"],
+ initialVal: "08:10:10",
+ expectedVal: "08:10:20"
+ },
+ {
+ // PageDown on second field increments second by 10.
+ keys: ["VK_TAB", "VK_TAB", "VK_PAGE_DOWN"],
+ initialVal: "08:10:10",
+ expectedVal: "08:10:00"
+ },
+ {
+ // Home key on second field sets it to the minimum second, which is 0.
+ keys: ["VK_TAB", "VK_TAB", "VK_HOME"],
+ initialVal: "16:00:30",
+ expectedVal: "16:00:00"
+ },
+ {
+ // End key on second field sets it to the minimum second, which is 59.
+ keys: ["VK_TAB", "VK_TAB", "VK_END"],
+ initialVal: "16:00:30",
+ expectedVal: "16:00:59"
+ },
+];
+
+function sendKeys(aKeys) {
+ for (let i = 0; i < aKeys.length; i++) {
+ let key = aKeys[i];
+ if (key.startsWith("VK")) {
+ synthesizeKey(key, {});
+ } else {
+ sendString(key);
+ }
+ }
+}
+
+function test() {
+ var elem = document.getElementById("input");
+
+ for (let { keys, initialVal, expectedVal } of testData) {
+ elem.focus();
+ elem.value = initialVal;
+ sendKeys(keys);
+ elem.blur();
+ is(elem.value, expectedVal,
+ "Test with " + keys + ", result should be " + expectedVal);
+ elem.value = "";
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_types_pref.html b/dom/html/test/forms/test_input_types_pref.html
new file mode 100644
index 000000000..243836f34
--- /dev/null
+++ b/dom/html/test/forms/test_input_types_pref.html
@@ -0,0 +1,114 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=764481
+-->
+<head>
+ <title>Test for Bug 764481</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=764481">Mozilla Bug 764481</a>
+<p id="display"></p>
+<div id="content" style="display: none" >
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+ var input = document.createElement("input");
+
+ var testData = [
+ {
+ prefs: [["dom.forms.number", false]],
+ inputType: "number",
+ expectedType: "text"
+ }, {
+ prefs: [["dom.forms.number", true]],
+ inputType: "number",
+ expectedType: "number"
+ }, {
+ prefs: [["dom.forms.color", false]],
+ inputType: "color",
+ expectedType: "text"
+ }, {
+ prefs: [["dom.forms.color", true]],
+ inputType: "color",
+ expectedType: "color"
+ }, {
+ prefs: [["dom.experimental_forms", false], ["dom.forms.datepicker", false],
+ ["dom.forms.datetime", false]],
+ inputType: "date",
+ expectedType: "text"
+ }, {
+ prefs: [["dom.experimental_forms", true], ["dom.forms.datepicker", false],
+ ["dom.forms.datetime", false]],
+ inputType: "date",
+ expectedType: "date"
+ }, {
+ prefs: [["dom.experimental_forms", false], ["dom.forms.datepicker", true],
+ ["dom.forms.datetime", false]],
+ inputType: "date",
+ expectedType: "date"
+ }, {
+ prefs: [["dom.experimental_forms", false], ["dom.forms.datepicker", false],
+ ["dom.forms.datetime", true]],
+ inputType: "date",
+ expectedType: "date"
+ }, {
+ prefs: [["dom.forms.datetime", false]],
+ inputType: "month",
+ expectedType: "text"
+ }, {
+ prefs: [["dom.forms.datetime", true]],
+ inputType: "month",
+ expectedType: "month"
+ }, {
+ prefs: [["dom.forms.datetime", false]],
+ inputType: "week",
+ expectedType: "text"
+ }, {
+ prefs: [["dom.forms.datetime", true]],
+ inputType: "week",
+ expectedType: "week"
+ }, {
+ prefs: [["dom.forms.datetime", false]],
+ inputType: "datetime-local",
+ expectedType: "text"
+ }, {
+ prefs: [["dom.forms.datetime", true]],
+ inputType: "datetime-local",
+ expectedType: "datetime-local"
+ }
+ ];
+
+ function testInputTypePreference(aData) {
+ return SpecialPowers.pushPrefEnv({'set': aData.prefs})
+ .then(() => {
+ // Change the type of input to text and then back to the tested input type,
+ // so that HTMLInputElement::ParseAttribute gets called with the pref enabled.
+ input.type = "text";
+ input.type = aData.inputType;
+ is(input.type, aData.expectedType, "input type should be '" +
+ aData.expectedType + "'' when pref " + aData.prefs + " is set");
+ is(input.getAttribute('type'), aData.inputType,
+ "input 'type' attribute should not change");
+ });
+ }
+
+ SimpleTest.waitForExplicitFinish();
+
+ let promise = Promise.resolve();
+ for (let i = 0; i < testData.length; i++) {
+ let data = testData[i];
+ promise = promise.then(() => testInputTypePreference(data));
+ }
+
+ promise.catch(error => ok(false, "Promise reject: " + error))
+ .then(() => SimpleTest.finish());
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_typing_sanitization.html b/dom/html/test/forms/test_input_typing_sanitization.html
new file mode 100644
index 000000000..0896f19df
--- /dev/null
+++ b/dom/html/test/forms/test_input_typing_sanitization.html
@@ -0,0 +1,260 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=765772
+-->
+<head>
+ <title>Test for Bug 765772</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=">Mozilla Bug 765772</a>
+<p id="display"></p>
+<iframe name="submit_frame" style="visibility: hidden;"></iframe>
+<div id="content">
+ <form id='f' target="submit_frame" action="foo">
+ <input name=i id="i" step='any' >
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+
+/*
+ * This test checks that when a user types in some input types, it will not be
+ * in a state where the value will be un-sanitized and usable (by a script).
+ */
+
+var input = document.getElementById('i');
+var form = document.getElementById('f');
+var submitFrame = document.getElementsByTagName('iframe')[0];
+var testData = [];
+var gCurrentTest = null;
+var gValidData = [];
+var gInvalidData = [];
+
+function submitForm() {
+ form.submit();
+}
+
+function sendKeyEventToSubmitForm() {
+ sendKey("return");
+}
+
+function urlify(aStr) {
+ return aStr.replace(/:/g, '%3A');
+}
+
+function runTestsForNextInputType()
+{
+ try {
+ testRunner.next();
+ } catch (e) {
+ if (e.toString() == '[object StopIteration]') {
+ SimpleTest.finish();
+ } else {
+ throw StopIteration;
+ }
+ }
+}
+
+function checkValueSubmittedIsValid()
+{
+ is(frames['submit_frame'].location.href,
+ 'http://mochi.test:8888/tests/dom/html/test/forms/foo?i='
+ + urlify(gValidData[valueIndex++]),
+ "The submitted value should not have been sanitized");
+
+ input.value = "";
+
+ if (valueIndex >= gValidData.length) {
+ if (gCurrentTest.canHaveBadInputValidityState) {
+ // Don't run the submission tests on the invalid input if submission
+ // will be blocked by invalid input.
+ runTestsForNextInputType();
+ return;
+ }
+ valueIndex = 0;
+ submitFrame.onload = checkValueSubmittedIsInvalid;
+ testData = gInvalidData;
+ }
+ testSubmissions();
+}
+
+function checkValueSubmittedIsInvalid()
+{
+ is(frames['submit_frame'].location.href,
+ 'http://mochi.test:8888/tests/dom/html/test/forms/foo?i=',
+ "The submitted value should have been sanitized");
+
+ valueIndex++;
+ input.value = "";
+
+ if (valueIndex >= gInvalidData.length) {
+ if (submitMethod == sendKeyEventToSubmitForm) {
+ runTestsForNextInputType();
+ return;
+ }
+ valueIndex = 0;
+ submitMethod = sendKeyEventToSubmitForm;
+ submitFrame.onload = checkValueSubmittedIsValid;
+ testData = gValidData;
+ }
+ testSubmissions();
+}
+
+function testSubmissions() {
+ input.focus();
+ sendString(testData[valueIndex]);
+ submitMethod();
+}
+
+var valueIndex = 0;
+var submitMethod = submitForm;
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest()
+{
+ SimpleTest.requestLongerTimeout(4);
+
+ var data = [
+ {
+ type: 'number',
+ canHaveBadInputValidityState: true,
+ validData: [
+ "42",
+ "-42", // should work for negative values
+ "42.1234",
+ "123.123456789123", // double precision
+ "1e2", // e should be usable
+ "2e1",
+ "1e-1", // value after e can be negative
+ "1E2", // E can be used instead of e
+ ],
+ invalidData: [
+ "e",
+ "e2",
+ "1e0.1",
+ "foo",
+ "42,13", // comma can't be used as a decimal separator
+ ]
+ },
+ {
+ type: 'date',
+ validData: [
+ '0001-01-01',
+ '2012-12-21',
+ '2013-01-28',
+ '100000-01-01',
+ ],
+ invalidData: [
+ '1-01-01',
+ 'a',
+ '-',
+ '2012-01',
+ '2013-01-1',
+ '1011-23-21',
+ '1000-12-99',
+ ]
+ },
+ {
+ type: 'month',
+ validData: [
+ '0001-01',
+ '2012-12',
+ '100000-01',
+ ],
+ invalidData: [
+ '1-01',
+ '-',
+ 'december',
+ '2012-dec',
+ '2012/12',
+ '2012-99',
+ '2012-1',
+ ]
+ },
+ {
+ type: 'week',
+ validData: [
+ '0001-W01',
+ '1970-W53',
+ '100000-W52',
+ '2016-W30',
+ ],
+ invalidData: [
+ '1-W01',
+ 'week',
+ '2016-30',
+ '2010-W80',
+ '2000/W30',
+ '1985-W00',
+ '1000-W'
+ ]
+ },
+ {
+ type: 'datetime-local',
+ validData: [
+ '0001-01-01T00:00',
+ '2016-11-07T16:45',
+ '2016-11-07T16:45:30',
+ '2016-11-07T16:45:30.10',
+ '2016-11-07T16:45:00.111',
+ ],
+ invalidData: [
+ '1-01-01T00:00',
+ '1970-01-01T9:30',
+ '2016/11/07T16:45',
+ '2016-11-07T16.45',
+ 'T',
+ 'datetime-local'
+ ]
+ },
+ ];
+
+ for (test of data) {
+ gCurrentTest = test;
+
+ input.type = test.type;
+ gValidData = test.validData;
+ gInvalidData = test.invalidData;
+
+ for (data of gValidData) {
+ input.value = "";
+ input.focus();
+ sendString(data);
+ input.blur();
+ is(input.value, data, "valid user input should not be sanitized");
+ }
+
+ for (data of gInvalidData) {
+ input.value = "";
+ input.focus();
+ sendString(data);
+ input.blur();
+ is(input.value, "", "invalid user input should be sanitized");
+ }
+
+ input.value = '';
+
+ testData = gValidData;
+ valueIndex = 0;
+ submitFrame.onload = checkValueSubmittedIsValid;
+ testSubmissions();
+ yield undefined;
+ }
+}
+
+var testRunner = runTest();
+
+addLoadEvent(function () {
+ testRunner.next();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_untrusted_key_events.html b/dom/html/test/forms/test_input_untrusted_key_events.html
new file mode 100644
index 000000000..b356316ce
--- /dev/null
+++ b/dom/html/test/forms/test_input_untrusted_key_events.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for untrusted DOM KeyboardEvent on input element</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content">
+ <input id="input">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runNextTest, window);
+
+const kTests = [
+ { type: "text", value: "foo", key: "b", expectedNewValue: "foo" },
+ { type: "number", value: "123", key: "4", expectedNewValue: "123" },
+ { type: "number", value: "123", key: KeyEvent.DOM_VK_UP, expectedNewValue: "123" },
+ { type: "number", value: "123", key: KeyEvent.DOM_VK_DOWN, expectedNewValue: "123" },
+];
+
+function sendUntrustedKeyEvent(eventType, keyCode, target) {
+ var evt = document.createEvent("KeyboardEvent");
+ var canBubbleArg = true;
+ var cancelableArg = true;
+ var viewArg = document.defaultView;
+ var ctrlKeyArg = false;
+ var altKeyArg = false;
+ var shiftKeyArg = false;
+ var metaKeyArg = false;
+ var keyCodeArg = keyCode;
+ var charCodeArg = 0;
+ evt.initKeyEvent(eventType, canBubbleArg, cancelableArg, viewArg,
+ ctrlKeyArg, altKeyArg, shiftKeyArg, metaKeyArg,
+ keyCodeArg, charCodeArg);
+ target.dispatchEvent(evt);
+}
+
+var input = document.getElementById("input");
+
+var gotEvents = {};
+
+function handleEvent(event) {
+ gotEvents[event.type] = true;
+}
+
+input.addEventListener("keydown", handleEvent, false);
+input.addEventListener("keyup", handleEvent, false);
+input.addEventListener("keypress", handleEvent, false);
+
+var previousTest = null;
+
+function runNextTest() {
+ if (previousTest) {
+ var msg = "For <input " + "type=" + previousTest.type + ">, ";
+ is(gotEvents.keydown, true, msg + "checking got keydown");
+ is(gotEvents.keyup, true, msg + "checking got keyup");
+ is(gotEvents.keypress, true, msg + "checking got keypress");
+ is(input.value, previousTest.expectedNewValue, msg + "checking element " +
+ " after being sent '" + previousTest.key + "' key events");
+ }
+
+ // reset flags
+ gotEvents.keydown = false;
+ gotEvents.keyup = false;
+ gotEvents.keypress = false;
+
+
+ var test = kTests.shift();
+ if (!test) {
+ SimpleTest.finish();
+ return; // We're all done
+ }
+
+ input.type = test.type;
+ input.focus(); // make sure we still have focus after type change
+ input.value = test.value;
+
+ sendUntrustedKeyEvent("keydown", test.key, input);
+ sendUntrustedKeyEvent("keyup", test.key, input);
+ sendUntrustedKeyEvent("keypress", test.key, input);
+
+ previousTest = test;
+
+ SimpleTest.executeSoon(runNextTest);
+};
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_input_url.html b/dom/html/test/forms/test_input_url.html
new file mode 100644
index 000000000..b335f5983
--- /dev/null
+++ b/dom/html/test/forms/test_input_url.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Tests for &lt;input type='url'&gt; validity</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <input type='url' id='i' oninvalid='invalidEventHandler(event);'>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Tests for <input type='url'> validity **/
+
+// More checks are done in test_bug551670.html.
+
+var gInvalid = false;
+
+function invalidEventHandler(e)
+{
+ is(e.type, "invalid", "Invalid event type should be invalid");
+ gInvalid = true;
+}
+
+function checkValidURL(element)
+{
+ gInvalid = false;
+ ok(!element.validity.typeMismatch,
+ "Element should not suffer from type mismatch");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "Element should be valid");
+ ok(!gInvalid, "The invalid event should not have been thrown");
+ is(element.validationMessage, '',
+ "Validation message should be the empty string");
+ ok(element.matches(":valid"), ":valid pseudo-class should apply");
+}
+
+function checkInvalidURL(element)
+{
+ gInvalid = false;
+ ok(element.validity.typeMismatch,
+ "Element should suffer from type mismatch");
+ ok(!element.validity.valid, "Element should not be valid");
+ ok(!element.checkValidity(), "Element should not be valid");
+ ok(gInvalid, "The invalid event should have been thrown");
+ is(element.validationMessage, "Please enter a URL.",
+ "Validation message should be related to invalid URL");
+ ok(element.matches(":invalid"),
+ ":invalid pseudo-class should apply");
+}
+
+var url = document.getElementById('i');
+
+var values = [
+ // [ value, validity ]
+ // The empty string should be considered as valid.
+ [ "", true ],
+ [ "foo", false ],
+ [ "http://mozilla.com/", true ],
+ [ "http://mozilla.com", true ],
+ [ "http://mozil\nla\r.com/", true ],
+ [ " http://mozilla.com/ ", true ],
+ [ "\r http://mozilla.com/ \n", true ],
+ [ "file:///usr/bin/tulip", true ],
+ [ "../../bar.html", false ],
+ [ "http://mozillá.org", true ],
+ [ "https://mózillä.org", true ],
+ [ "http://mózillä.órg", true ],
+ [ "ht://mózillä.órg", true ],
+ [ "httŭ://mózillä.órg", false ],
+];
+
+values.forEach(function([value, valid]) {
+ url.value = value;
+
+ if (valid) {
+ checkValidURL(url);
+ } else {
+ checkInvalidURL(url);
+ }
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_interactive_content_in_label.html b/dom/html/test/forms/test_interactive_content_in_label.html
new file mode 100644
index 000000000..3df64eae2
--- /dev/null
+++ b/dom/html/test/forms/test_interactive_content_in_label.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=229925
+-->
+<head>
+ <title>Test for Bug 229925</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=229925">Mozilla Bug 229925</a>
+<p id="display"></p>
+<form action="#">
+ <label>
+ <span id="text">label</span>
+ <input type="button" id="target" value="target">
+
+ <a class="yes" href="#">a</a>
+ <audio class="yes" controls></audio>
+ <button class="yes">button</button>
+ <details class="yes">details</details>
+ <embed class="yes">embed</embed>
+ <iframe class="yes" src="data:text/plain," style="width: 16px; height: 16px;"></iframe>
+ <img class="yes" src="data:image/png," usemap="#map">
+ <input class="yes" type="text" size="4">
+ <keygen class="yes">
+ <label class="yes">label</label>
+ <object class="yes" usemap="#map">object</object>
+ <select class="yes"><option>select</option></select>
+ <textarea class="yes" cols="1" rows="1"></textarea>
+ <video class="yes" controls></video>
+
+ <a class="no">a</a>
+ <audio class="no"></audio>
+ <img class="no" src="data:image/png,">
+ <input class="no" type="hidden">
+ <object class="no">object</object>
+ <video class="no"></video>
+
+ <span class="no" tabindex="1">tabindex</span>
+ <audio class="no" tabindex="1"></audio>
+ <img class="no" src="data:image/png," tabindex="1">
+ <input class="no" type="hidden" tabindex="1">
+ <object class="no" tabindex="1">object</object>
+ <video class="no" tabindex="1"></video>
+ </label>
+</form>
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 229925 **/
+
+var target = document.getElementById("target");
+
+var yes_nodes = Array.from(document.getElementsByClassName("yes"));
+
+var no_nodes = Array.from(document.getElementsByClassName("no"));
+
+var target_clicked = false;
+target.addEventListener("click", function() {
+ target_clicked = true;
+});
+
+var node;
+for (node of yes_nodes) {
+ target_clicked = false;
+ node.click();
+ is(target_clicked, false, "mouse click on interactive content " + node.nodeName + " shouldn't dispatch event to label target");
+}
+
+for (node of no_nodes) {
+ target_clicked = false;
+ node.click();
+ is(target_clicked, true, "mouse click on non interactive content " + node.nodeName + " should dispatch event to label target");
+}
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/forms/test_label_control_attribute.html b/dom/html/test/forms/test_label_control_attribute.html
new file mode 100644
index 000000000..66b761c93
--- /dev/null
+++ b/dom/html/test/forms/test_label_control_attribute.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=562932
+-->
+<head>
+ <title>Test for Bug 562932</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=562932">Mozilla Bug 562932</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <!-- No @for, we have to check the content -->
+ <label id='l1'><input id='i1'></label>
+ <label id='l2'><input id='i2'><input></label>
+ <label id='l3'></label>
+ <label id='l4a'><fieldset id='f'>foo</fieldset></label>
+ <label id='l4b'><label id='l4c'><input id='i3'></label></label>
+ <label id='l4d'><label id='l4e'><input id='i3b'></label><input></label>
+
+ <!-- With @for, we do no check the content -->
+ <label id='l5' for='i1'></label>
+ <label id='l6' for='i4'></label>
+ <label id='l7' for='i4'><input></label>
+ <label id='l8' for='i1 i2'></label>
+ <label id='l9' for='i1 i2'><input></label>
+ <label id='l10' for='f'></label>
+ <label id='l11' for='i4'></label>
+ <label id='l12' for='i5'></label>
+ <label id='l13' for=''><input></label>
+ <!-- <label id='l14'> is created in script -->
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 562932 **/
+
+function checkControl(aLabelId, aElementId, aMsg)
+{
+ var element = null;
+
+ if (aElementId != null) {
+ element = document.getElementById(aElementId);
+ }
+
+ is(document.getElementById(aLabelId).control, element, aMsg);
+}
+
+ok('control' in document.createElement('label'),
+ "label element should have a control IDL attribute");
+
+checkControl('l1', 'i1', "label control should be the first form element");
+checkControl('l2', 'i2', "label control should be the first form element");
+checkControl('l3', null, "label control should be null when there is no child");
+checkControl('l4a', null, "label control should be null when there is no \
+ labelable form element child");
+checkControl('l4b', 'i3', "label control should be the first labelable element \
+ in tree order");
+checkControl('l4c', 'i3', "label control should be the first labelable element \
+ in tree order");
+checkControl('l4d', 'i3b', "label control should be the first labelable element \
+ in tree order");
+checkControl('l4e', 'i3b', "label control should be the first labelable element \
+ in tree order");
+checkControl('l5', 'i1', "label control should be the id in @for");
+checkControl('l6', null,
+ "label control should be null if the id in @for is not valid");
+checkControl('l7', null,
+ "label control should be null if the id in @for is not valid");
+checkControl('l8', null,
+ "label control should be null if there are more than one id in @for");
+checkControl('l9', null,
+ "label control should be null if there are more than one id in @for");
+checkControl('l10', null, "label control should be null if the id in @for \
+ is not an id from a labelable form element");
+
+var inputOutOfDocument = document.createElement('input');
+inputOutOfDocument.id = 'i4';
+checkControl('l11', null, "label control should be null if the id in @for \
+ is not an id from an element in the document");
+
+var inputInDocument = document.createElement('input');
+inputInDocument.id = 'i5';
+document.getElementById('content').appendChild(inputInDocument);
+checkControl('l12', 'i5', "label control should be the id in @for");
+
+checkControl('l13', null, "label control should be null if the id in @for \
+ is empty");
+
+var labelOutOfDocument = document.createElement('label');
+labelOutOfDocument.htmlFor = 'i1';
+is(labelOutOfDocument.control, null, "out of document label shouldn't \
+ labelize a form control");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_label_input_controls.html b/dom/html/test/forms/test_label_input_controls.html
new file mode 100644
index 000000000..6dee2a5bb
--- /dev/null
+++ b/dom/html/test/forms/test_label_input_controls.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=597650
+-->
+<head>
+ <title>Test for Bug 597650</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=597650">Mozilla Bug 597650</a>
+ <p id="display"></p>
+ <div id="content">
+ <label id="l">
+ <input id="h"></input>
+ <input type="text" id="i"></input>
+ </label>
+ <label id="lh" for="h"></label>
+ </div>
+ <pre id="test">
+ <script class="testbody" type="text/javascript">
+ /** Test for Bug 597650 **/
+ label = document.getElementById("l");
+ labelForH = document.getElementById("lh");
+ inputI = document.getElementById("i");
+ inputH = document.getElementById("h");
+
+ var labelableTypes = ["text", "search", "tel", "url", "email", "password",
+ "datetime", "date", "month", "week", "time",
+ "number", "range", "color", "checkbox", "radio",
+ "file", "submit", "image", "reset", "button"];
+ var nonLabelableTypes = ["hidden"];
+
+ for (var i in labelableTypes) {
+ test(labelableTypes[i], true);
+ }
+
+ for (var i in nonLabelableTypes) {
+ test(nonLabelableTypes[i], false);
+ }
+
+ function test(type, isLabelable) {
+ inputH.type = type;
+ if (isLabelable) {
+ testControl(label, inputH, type, true);
+ testControl(labelForH, inputH, type, true);
+ } else {
+ testControl(label, inputI, type, false);
+ testControl(labelForH, null, type, false);
+
+ inputH.type = "text";
+ testControl(label, inputH, "text", true);
+ testControl(labelForH, inputH, "text", true);
+
+ inputH.type = type;
+ testControl(label, inputI, type, false);
+ testControl(labelForH, null, type, false);
+
+ label.removeChild(inputH);
+ testControl(label, inputI, "text", true);
+
+ var element = document.createElement('input');
+ element.type = type;
+ label.insertBefore(element, inputI);
+ testControl(label, inputI, "text", true);
+ }
+ }
+
+ function testControl(label, control, type, labelable) {
+ if (labelable) {
+ is(label.control, control, "Input controls of type " + type
+ + " should be labeled");
+ } else {
+ is(label.control, control, "Input controls of type " + type
+ + " should be ignored by <label>");
+ }
+ }
+ </script>
+ </pre>
+ </body>
+</html>
+
diff --git a/dom/html/test/forms/test_max_attribute.html b/dom/html/test/forms/test_max_attribute.html
new file mode 100644
index 000000000..4007cfad6
--- /dev/null
+++ b/dom/html/test/forms/test_max_attribute.html
@@ -0,0 +1,437 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=635499
+-->
+<head>
+ <title>Test for Bug 635499</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 635499 **/
+
+var data = [
+ { type: 'hidden', apply: false },
+ { type: 'text', apply: false },
+ { type: 'search', apply: false },
+ { type: 'tel', apply: false },
+ { type: 'url', apply: false },
+ { type: 'email', apply: false },
+ { type: 'password', apply: false },
+ { type: 'date', apply: true },
+ { type: 'month', apply: true },
+ { type: 'week', apply: true },
+ { type: 'time', apply: true },
+ // TODO: temporary set to false until bug 888331 is fixed.
+ { type: 'datetime-local', apply: false },
+ { type: 'number', apply: true },
+ { type: 'range', apply: true },
+ { type: 'color', apply: false },
+ { type: 'checkbox', apply: false },
+ { type: 'radio', apply: false },
+ { type: 'file', apply: false },
+ { type: 'submit', apply: false },
+ { type: 'image', apply: false },
+ { type: 'reset', apply: false },
+ { type: 'button', apply: false },
+];
+
+var input = document.createElement("input");
+document.getElementById('content').appendChild(input);
+
+/**
+ * @aValidity - boolean indicating whether the element is expected to be valid
+ * (aElement.validity.valid is true) or not. The value passed is ignored and
+ * overridden with true if aApply is false.
+ * @aApply - boolean indicating whether the min/max attributes apply to this
+ * element type.
+ * @aRangeApply - A boolean that's set to true if the current input type is a
+ * "[candidate] for constraint validation" and it "[has] range limitations"
+ * per http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html#selector-in-range
+ * (in other words, one of the pseudo classes :in-range and :out-of-range
+ * should apply (which, depends on aValidity)).
+ * Else (neither :in-range or :out-of-range should match) set to false.
+ */
+function checkValidity(aElement, aValidity, aApply, aRangeApply)
+{
+ aValidity = aApply ? aValidity : true;
+
+ is(aElement.validity.valid, aValidity,
+ "element validity should be " + aValidity);
+ is(aElement.validity.rangeOverflow, !aValidity,
+ "element overflow status should be " + !aValidity);
+ var overflowMsg =
+ (aElement.type == "date" || aElement.type == "time" ||
+ aElement.type == "month" || aElement.type == "week") ?
+ ("Please select a value that is no later than " + aElement.max + ".") :
+ ("Please select a value that is no more than " + aElement.max + ".");
+ is(aElement.validationMessage,
+ aValidity ? "" : overflowMsg, "Checking range overflow validation message");
+
+ is(aElement.matches(":valid"), aElement.willValidate && aValidity,
+ (aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply");
+ is(aElement.matches(":invalid"), aElement.willValidate && !aValidity,
+ (aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply");
+
+ if (!aRangeApply) {
+ ok(!aElement.matches(":in-range"), ":in-range should not match");
+ ok(!aElement.matches(":out-of-range"),
+ ":out-of-range should not match");
+ } else {
+ is(aElement.matches(":in-range"), aValidity,
+ ":in-range matches status should be " + aValidity);
+ is(aElement.matches(":out-of-range"), !aValidity,
+ ":out-of-range matches status should be " + !aValidity);
+ }
+}
+
+for (var test of data) {
+ input.type = test.type;
+ var apply = test.apply;
+
+ // The element should be valid. Range should not apply when @min and @max are
+ // undefined, except if the input type is 'range' (since that type has a
+ // default minimum and maximum).
+ if (input.type == 'range') {
+ checkValidity(input, true, apply, true);
+ } else {
+ checkValidity(input, true, apply, false);
+ }
+ checkValidity(input, true, apply, test.type == 'range');
+
+ switch (input.type) {
+ case 'hidden':
+ case 'text':
+ case 'search':
+ case 'password':
+ case 'url':
+ case 'tel':
+ case 'email':
+ case 'number':
+ case 'checkbox':
+ case 'radio':
+ case 'file':
+ case 'submit':
+ case 'reset':
+ case 'button':
+ case 'image':
+ case 'color':
+ input.max = '-1';
+ break;
+ case 'date':
+ input.max = '2012-06-27';
+ break;
+ case 'time':
+ input.max = '02:20';
+ break;
+ case 'range':
+ // range is special, since setting max to -1 will make it invalid since
+ // it's default would then be 0, meaning it suffers from overflow.
+ input.max = '-1';
+ checkValidity(input, false, apply, apply);
+ // Now make it something that won't cause an error below:
+ input.max = '10';
+ break;
+ case 'month':
+ input.max = '2016-12';
+ break;
+ case 'week':
+ input.max = '2016-W39';
+ break;
+ case 'datetime-local':
+ // TODO: this is temporary until bug 888331 is fixed.
+ break;
+ default:
+ ok(false, 'please, add a case for this new type (' + input.type + ')');
+ }
+
+ checkValidity(input, true, apply, apply);
+
+ switch (input.type) {
+ case 'text':
+ case 'hidden':
+ case 'search':
+ case 'password':
+ case 'tel':
+ case 'radio':
+ case 'checkbox':
+ case 'reset':
+ case 'button':
+ case 'submit':
+ case 'image':
+ input.value = '0';
+ checkValidity(input, true, apply, apply);
+ break;
+ case 'url':
+ input.value = 'http://mozilla.org';
+ checkValidity(input, true, apply, apply);
+ break;
+ case 'email':
+ input.value = 'foo@bar.com';
+ checkValidity(input, true, apply, apply);
+ break;
+ case 'file':
+ var file = new File([''], '635499_file');
+
+ SpecialPowers.wrap(input).mozSetFileArray([file]);
+ checkValidity(input, true, apply, apply);
+
+ break;
+ case 'date':
+ input.max = '2012-06-27';
+ input.value = '2012-06-26';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2012-06-27';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2012-06-28';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '2012-06-30';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2012-07-05';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '1000-01-01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '20120-01-01';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '0050-01-01';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '0049-01-01';
+ checkValidity(input, true, apply, apply);
+
+ input.max = '';
+ checkValidity(input, true, apply, false);
+
+ input.max = 'foo';
+ checkValidity(input, true, apply, false);
+
+ break;
+ case 'number':
+ input.max = '2';
+ input.value = '1';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '3';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '5';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '42';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '';
+ checkValidity(input, true, apply, false);
+
+ input.max = 'foo';
+ checkValidity(input, true, apply, false);
+
+ // Check that we correctly convert input.max to a double in validationMessage.
+ if (input.type == 'number') {
+ input.max = "4.333333333333333333333333333333333331";
+ input.value = "5";
+ is(input.validationMessage,
+ "Please select a value that is no more than 4.33333333333333.",
+ "validation message");
+ }
+
+ break;
+ case 'range':
+ input.max = '2';
+ input.value = '1';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '3';
+ checkValidity(input, true, apply, apply);
+
+ is(input.value, input.max, "the value should have been set to max");
+
+ input.max = '5';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '42';
+ checkValidity(input, true, apply, apply);
+
+ is(input.value, input.max, "the value should have been set to max");
+
+ input.max = '';
+ checkValidity(input, true, apply, apply);
+
+ input.max = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ // Check that we correctly convert input.max to a double in validationMessage.
+ input.step = 'any';
+ input.min = 5;
+ input.max = 0.66666666666666666666666666666666666
+ input.value = 1;
+ is(input.validationMessage,
+ "Please select a value that is no more than 0.666666666666667.",
+ "validation message")
+
+ break;
+ case 'time':
+ // Don't worry about that.
+ input.step = 'any';
+
+ input.max = '10:10';
+ input.value = '10:09';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '10:10';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '10:10:00';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '10:10:00.000';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '10:11';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '10:10:00.001';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '01:00:00.01';
+ input.value = '01:00:00.001';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '01:00:00';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '01:00:00.1';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '';
+ checkValidity(input, true, apply, false);
+
+ input.max = 'foo';
+ checkValidity(input, true, apply, false);
+
+ break;
+ case 'month':
+ input.value = '2016-06';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2016-12';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2017-01';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '2017-07';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2017-12';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '1000-01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '20160-01';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '0050-01';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '0049-12';
+ checkValidity(input, true, apply, apply);
+
+ input.max = '';
+ checkValidity(input, true, apply, false);
+
+ input.max = 'foo';
+ checkValidity(input, true, apply, false);
+
+ break;
+ case 'week':
+ input.value = '2016-W01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2016-W39';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2017-W01';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '2017-W01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2017-W52';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '1000-W01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2100-W01';
+ checkValidity(input, false, apply, apply);
+
+ input.max = '0050-W01';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '0049-W52';
+ checkValidity(input, true, apply, apply);
+
+ input.max = '';
+ checkValidity(input, true, apply, false);
+
+ input.max = 'foo';
+ checkValidity(input, true, apply, false);
+
+ break;
+ case 'datetime-local':
+ // TODO: this is temporary until bug 888331 is fixed.
+
+ break;
+ }
+
+ // Cleaning up,
+ input.removeAttribute('max');
+ input.value = '';
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_maxlength_attribute.html b/dom/html/test/forms/test_maxlength_attribute.html
new file mode 100644
index 000000000..cfc50b67c
--- /dev/null
+++ b/dom/html/test/forms/test_maxlength_attribute.html
@@ -0,0 +1,129 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=345624
+-->
+<head>
+ <title>Test for Bug 345624</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ input, textarea { background-color: rgb(0,0,0) !important; }
+ :-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; }
+ :-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
+<p id="display"></p>
+<div id="content">
+ <input id='i'>
+ <textarea id='t'></textarea>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 345624 **/
+
+/**
+ * This test is checking only tooLong related features
+ * related to constraint validation.
+ */
+
+function checkTooLongValidity(element)
+{
+ element.value = "foo";
+ ok(!element.validity.tooLong,
+ "Element should not be too long when maxlength is not set");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "The element should be valid");
+
+ element.maxLength = 1;
+ ok(!element.validity.tooLong,
+ "Element should not be too long unless the user edits it");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "The element should be valid");
+
+ element.focus();
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ is(element.value, "fo", "value should have changed");
+ ok(element.validity.tooLong,
+ "Element should be too long after a user edit that does not make it short enough");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+ ok(!element.validity.valid, "Element should be invalid");
+ ok(!element.checkValidity(), "The element should not be valid");
+ is(element.validationMessage,
+ "Please shorten this text to 1 characters or less (you are currently using 2 characters).",
+ "The validation message text is not correct");
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ is(element.value, "f", "value should have changed");
+ ok(!element.validity.tooLong,
+ "Element should not be too long after a user edit makes it short enough");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+
+ element.maxLength = 2;
+ ok(!element.validity.tooLong,
+ "Element should remain valid if maxlength changes but maxlength > length");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+
+ element.maxLength = 1;
+ ok(!element.validity.tooLong,
+ "Element should remain valid if maxlength changes but maxlength = length");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "The element should be valid");
+
+ element.maxLength = 0;
+ ok(element.validity.tooLong,
+ "Element should become invalid if maxlength changes and maxlength < length");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+ ok(!element.validity.valid, "Element should be invalid");
+ ok(!element.checkValidity(), "The element should not be valid");
+ is(element.validationMessage,
+ "Please shorten this text to 0 characters or less (you are currently using 1 characters).",
+ "The validation message text is not correct");
+
+ element.maxLength = 1;
+ ok(!element.validity.tooLong,
+ "Element should become valid if maxlength changes and maxlength = length");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "The element should be valid");
+
+ element.value = "test";
+ ok(!element.validity.tooLong,
+ "Element should stay valid after programmatic edit (even if value is too long)");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "The element should be valid");
+
+ element.setCustomValidity("custom message");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+ is(element.validationMessage, "custom message",
+ "Custom message should be shown instead of too long one");
+}
+
+checkTooLongValidity(document.getElementById('i'));
+checkTooLongValidity(document.getElementById('t'));
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_meter_element.html b/dom/html/test/forms/test_meter_element.html
new file mode 100644
index 000000000..7b9c597ce
--- /dev/null
+++ b/dom/html/test/forms/test_meter_element.html
@@ -0,0 +1,384 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=657938
+-->
+<head>
+ <title>Test for <meter></title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=657938">Mozilla Bug 657938</a>
+<p id="display"></p>
+<iframe name="submit_frame" style="visibility: hidden;"></iframe>
+<div id="content" style="visibility: hidden;">
+ <form id='f' method='get' target='submit_frame' action='foo'>
+ <meter id='m' value=0.5></meter>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for <meter> **/
+
+function checkFormIDLAttribute(aElement)
+{
+ is('form' in aElement, false, "<meter> shouldn't have a form attribute");
+}
+
+function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL)
+{
+ var expectedValueForIDL = aNewValue;
+ var expectedValueForContent = String(aNewValue);
+
+ if (aExpectedValueForIDL !== undefined) {
+ expectedValueForIDL = aExpectedValueForIDL;
+ }
+
+ if (aNewValue != null) {
+ aElement.setAttribute(aAttribute, aNewValue);
+ is(aElement.getAttribute(aAttribute), expectedValueForContent,
+ aAttribute + " content attribute should be " + expectedValueForContent);
+ is(aElement[aAttribute], expectedValueForIDL,
+ aAttribute + " IDL attribute should be " + expectedValueForIDL);
+
+ if (parseFloat(aNewValue) == aNewValue) {
+ aElement[aAttribute] = aNewValue;
+ is(aElement.getAttribute(aAttribute), expectedValueForContent,
+ aAttribute + " content attribute should be " + expectedValueForContent);
+ is(aElement[aAttribute], parseFloat(expectedValueForIDL),
+ aAttribute + " IDL attribute should be " + parseFloat(expectedValueForIDL));
+ }
+ } else {
+ aElement.removeAttribute(aAttribute);
+ is(aElement.getAttribute(aAttribute), null,
+ aAttribute + " content attribute should be null");
+ is(aElement[aAttribute], expectedValueForIDL,
+ aAttribute + " IDL attribute should be " + expectedValueForIDL);
+ }
+}
+
+function checkValueAttribute()
+{
+ var tests = [
+ // value has to be a valid float, its default value is 0.0 otherwise.
+ [ null, 0.0 ],
+ [ 'foo', 0.0 ],
+ // If value < 0.0, 0.0 is used instead.
+ [ -1.0, 0.0 ],
+ // If value >= max, max is used instead (max default value is 1.0).
+ [ 2.0, 1.0 ],
+ [ 1.0, 0.5, 0.5 ],
+ [ 10.0, 5.0, 5.0 ],
+ [ 13.37, 13.37, 42.0 ],
+ // If value <= min, min is used instead (min default value is 0.0).
+ [ 0.5, 1.0, 10.0 ,1.0 ],
+ [ 10.0, 13.37, 42.0 , 13.37],
+ // Regular reflection.
+ [ 0.0 ],
+ [ 0.5 ],
+ [ 1.0 ],
+ // Check double-precision value.
+ [ 0.234567898765432 ],
+ ];
+
+ var element = document.createElement('meter');
+
+ for (var test of tests) {
+ if (test[2]) {
+ element.setAttribute('max', test[2]);
+ }
+
+ if (test[3]) {
+ element.setAttribute('min', test[3]);
+ }
+
+ checkAttribute(element, 'value', test[0], test[1]);
+
+ element.removeAttribute('max');
+ element.removeAttribute('min');
+ }
+}
+
+function checkMinAttribute()
+{
+ var tests = [
+ // min default value is 0.0.
+ [ null, 0.0 ],
+ [ 'foo', 0.0 ],
+ // Regular reflection.
+ [ 0.5 ],
+ [ 1.0 ],
+ [ 2.0 ],
+ // Check double-precision value.
+ [ 0.234567898765432 ],
+ ];
+
+ var element = document.createElement('meter');
+
+ for (var test of tests) {
+ checkAttribute(element, 'min', test[0], test[1]);
+ }
+}
+
+function checkMaxAttribute()
+{
+ var tests = [
+ // max default value is 1.0.
+ [ null, 1.0 ],
+ [ 'foo', 1.0 ],
+ // If value <= min, min is used instead.
+ [ -1.0, 0.0 ],
+ [ 0.0, 0.5, 0.5 ],
+ [ 10.0, 15.0, 15.0 ],
+ [ 42, 42, 13.37 ],
+ // Regular reflection.
+ [ 0.5 ],
+ [ 1.0 ],
+ [ 2.0 ],
+ // Check double-precision value.
+ [ 0.234567898765432 ],
+ ];
+
+ var element = document.createElement('meter');
+
+ for (var test of tests) {
+ if (test[2]) {
+ element.setAttribute('min', test[2]);
+ }
+
+ checkAttribute(element, 'max', test[0], test[1]);
+
+ element.removeAttribute('min');
+ }
+}
+
+function checkLowAttribute()
+{
+ var tests = [
+ // low default value is min (min default value is 0.0).
+ [ null, 0.0 ],
+ [ 'foo', 0.0 ],
+ [ 'foo', 1.0, 1.0],
+ // If low <= min, min is used instead.
+ [ -1.0, 0.0 ],
+ [ 0.0, 0.5, 0.5 ],
+ [ 10.0, 15.0, 15.0, 42.0 ],
+ [ 42.0, 42.0, 13.37, 100.0 ],
+ // If low >= max, max is used instead.
+ [ 2.0, 1.0 ],
+ [ 10.0, 5.0 , 0.5, 5.0 ],
+ [ 13.37, 13.37, 0.0, 42.0 ],
+ // Regular reflection.
+ [ 0.0 ],
+ [ 0.5 ],
+ [ 1.0 ],
+ // Check double-precision value.
+ [ 0.234567898765432 ],
+ ];
+
+ var element = document.createElement('meter');
+
+ for (var test of tests) {
+ if (test[2]) {
+ element.setAttribute('min', test[2]);
+ }
+ if (test[3]) {
+ element.setAttribute('max', test[3]);
+ }
+
+ checkAttribute(element, 'low', test[0], test[1]);
+
+ element.removeAttribute('min');
+ element.removeAttribute('max');
+ }
+}
+
+function checkHighAttribute()
+{
+ var tests = [
+ // high default value is max (max default value is 1.0).
+ [ null, 1.0 ],
+ [ 'foo', 1.0 ],
+ [ 'foo', 42.0, 0.0, 42.0],
+ // If high <= min, min is used instead.
+ [ -1.0, 0.0 ],
+ [ 0.0, 0.5, 0.5 ],
+ [ 10.0, 15.0, 15.0, 42.0 ],
+ [ 42.0, 42.0, 13.37, 100.0 ],
+ // If high >= max, max is used instead.
+ [ 2.0, 1.0 ],
+ [ 10.0, 5.0 , 0.5, 5.0 ],
+ [ 13.37, 13.37, 0.0, 42.0 ],
+ // Regular reflection.
+ [ 0.0 ],
+ [ 0.5 ],
+ [ 1.0 ],
+ // Check double-precision value.
+ [ 0.234567898765432 ],
+ ];
+
+ var element = document.createElement('meter');
+
+ for (var test of tests) {
+ if (test[2]) {
+ element.setAttribute('min', test[2]);
+ }
+ if (test[3]) {
+ element.setAttribute('max', test[3]);
+ }
+
+ checkAttribute(element, 'high', test[0], test[1]);
+
+ element.removeAttribute('min');
+ element.removeAttribute('max');
+ }
+}
+
+function checkOptimumAttribute()
+{
+ var tests = [
+ // opt default value is (max-min)/2 (thus default value is 0.5).
+ [ null, 0.5 ],
+ [ 'foo', 0.5 ],
+ [ 'foo', 2.0, 1.0, 3.0],
+ // If opt <= min, min is used instead.
+ [ -1.0, 0.0 ],
+ [ 0.0, 0.5, 0.5 ],
+ [ 10.0, 15.0, 15.0, 42.0 ],
+ [ 42.0, 42.0, 13.37, 100.0 ],
+ // If opt >= max, max is used instead.
+ [ 2.0, 1.0 ],
+ [ 10.0, 5.0 , 0.5, 5.0 ],
+ [ 13.37, 13.37, 0.0, 42.0 ],
+ // Regular reflection.
+ [ 0.0 ],
+ [ 0.5 ],
+ [ 1.0 ],
+ // Check double-precision value.
+ [ 0.234567898765432 ],
+ ];
+
+ var element = document.createElement('meter');
+
+ for (var test of tests) {
+ if (test[2]) {
+ element.setAttribute('min', test[2]);
+ }
+ if (test[3]) {
+ element.setAttribute('max', test[3]);
+ }
+
+ checkAttribute(element, 'optimum', test[0], test[1]);
+
+ element.removeAttribute('min');
+ element.removeAttribute('max');
+ }
+}
+
+function checkFormListedElement(aElement)
+{
+ is(document.forms[0].elements.length, 0, "the form should have no element");
+}
+
+function checkLabelable(aElement)
+{
+ var content = document.getElementById('content');
+ var label = document.createElement('label');
+
+ content.appendChild(label);
+ label.appendChild(aElement);
+ is(label.control, aElement, "meter should be labelable");
+
+ // Cleaning-up.
+ content.removeChild(label);
+ content.appendChild(aElement);
+}
+
+function checkNotResetableAndFormSubmission(aElement)
+{
+ // Creating an input element to check the submission worked.
+ var form = document.forms[0];
+ var input = document.createElement('input');
+
+ input.name = 'a';
+ input.value = 'tulip';
+ form.appendChild(input);
+
+ // Setting values.
+ aElement.value = 42.0;
+ aElement.max = 100.0;
+
+ document.getElementsByName('submit_frame')[0].addEventListener("load", function() {
+ document.getElementsByName('submit_frame')[0].removeEventListener("load", arguments.callee, false);
+
+ /**
+ * All elements values have been set just before the submission.
+ * The input element value should be in the submit url but the meter
+ * element value should not appear.
+ */
+ is(frames['submit_frame'].location.href,
+ 'http://mochi.test:8888/tests/dom/html/test/forms/foo?a=tulip',
+ "The meter element value should not be submitted");
+
+ checkNotResetable();
+ }, false);
+
+ form.submit();
+}
+
+function checkNotResetable()
+{
+ // Try to reset the form.
+ var form = document.forms[0];
+ var element = document.getElementById('m');
+
+ element.value = 3.0;
+ element.max = 42.0;
+
+ form.reset();
+
+ SimpleTest.executeSoon(function() {
+ is(element.value, 3.0, "meter.value should not have changed");
+ is(element.max, 42.0, "meter.max should not have changed");
+
+ SimpleTest.finish();
+ });
+}
+
+SimpleTest.waitForExplicitFinish();
+
+var m = document.getElementById('m');
+
+ok(m instanceof HTMLMeterElement,
+ "The meter element should be instance of HTMLMeterElement");
+is(m.constructor, HTMLMeterElement,
+ "The meter element constructor should be HTMLMeterElement");
+
+// There is no such attribute.
+checkFormIDLAttribute(m);
+
+checkValueAttribute();
+
+checkMinAttribute();
+
+checkMaxAttribute();
+
+checkLowAttribute();
+
+checkHighAttribute();
+
+checkOptimumAttribute();
+
+checkFormListedElement(m);
+
+checkLabelable(m);
+
+checkNotResetableAndFormSubmission(m);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_meter_pseudo-classes.html b/dom/html/test/forms/test_meter_pseudo-classes.html
new file mode 100644
index 000000000..e11f48a53
--- /dev/null
+++ b/dom/html/test/forms/test_meter_pseudo-classes.html
@@ -0,0 +1,170 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=660238
+-->
+<head>
+ <title>Test for Bug 660238</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=770238">Mozilla Bug 660238</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 660238 **/
+
+function checkOptimum(aElement, aValue, aOptimum, expectedResult)
+{
+ var errorString = expectedResult
+ ? "value attribute should be in the optimum region"
+ : "value attribute should not be in the optimum region";
+
+ aElement.setAttribute('value', aValue);
+ aElement.setAttribute('optimum', aOptimum);
+ is(aElement.matches(":-moz-meter-optimum"),
+ expectedResult, errorString);
+}
+
+function checkSubOptimum(aElement, aValue, aOptimum, expectedResult)
+{
+ var errorString = "value attribute should be in the suboptimal region";
+ if (!expectedResult) {
+ errorString = "value attribute should not be in the suboptimal region";
+ }
+ aElement.setAttribute('value', aValue);
+ aElement.setAttribute('optimum', aOptimum);
+ is(aElement.matches(":-moz-meter-sub-optimum"),
+ expectedResult, errorString);
+}
+
+function checkSubSubOptimum(aElement, aValue, aOptimum, expectedResult)
+{
+ var errorString = "value attribute should be in the sub-suboptimal region";
+ if (!expectedResult) {
+ errorString = "value attribute should not be in the sub-suboptimal region";
+ }
+ aElement.setAttribute('value', aValue);
+ aElement.setAttribute('optimum', aOptimum);
+ is(aElement.matches(":-moz-meter-sub-sub-optimum"),
+ expectedResult, errorString);
+}
+
+function checkMozMatchesSelector()
+{
+ var element = document.createElement('meter');
+ // all tests realised with default values for min and max (0 and 1)
+ // low = 0.3 and high = 0.7
+ element.setAttribute('low', 0.3);
+ element.setAttribute('high', 0.7);
+
+ var tests = [
+ /*
+ * optimum = 0.0 =>
+ * optimum region = [ 0.0, 0.3 [
+ * suboptimal region = [ 0.3, 0.7 ]
+ * sub-suboptimal region = ] 0.7, 1.0 ]
+ */
+ [ 0.0, 0.0, true, false, false ],
+ [ 0.1, 0.0, true, false, false ],
+ [ 0.3, 0.0, false, true, false ],
+ [ 0.5, 0.0, false, true, false ],
+ [ 0.7, 0.0, false, true, false ],
+ [ 0.8, 0.0, false, false, true ],
+ [ 1.0, 0.0, false, false, true ],
+ /*
+ * optimum = 0.1 =>
+ * optimum region = [ 0.0, 0.3 [
+ * suboptimal region = [ 0.3, 0.7 ]
+ * sub-suboptimal region = ] 0.7, 1.0 ]
+ */
+ [ 0.0, 0.1, true, false, false ],
+ [ 0.1, 0.1, true, false, false ],
+ [ 0.3, 0.1, false, true, false ],
+ [ 0.5, 0.1, false, true, false ],
+ [ 0.7, 0.1, false, true, false ],
+ [ 0.8, 0.1, false, false, true ],
+ [ 1.0, 0.1, false, false, true ],
+ /*
+ * optimum = 0.3 =>
+ * suboptimal region = [ 0.0, 0.3 [
+ * optimum region = [ 0.3, 0.7 ]
+ * suboptimal region = ] 0.7, 1.0 ]
+ */
+ [ 0.0, 0.3, false, true, false ],
+ [ 0.1, 0.3, false, true, false ],
+ [ 0.3, 0.3, true, false, false ],
+ [ 0.5, 0.3, true, false, false ],
+ [ 0.7, 0.3, true, false, false ],
+ [ 0.8, 0.3, false, true, false ],
+ [ 1.0, 0.3, false, true, false ],
+ /*
+ * optimum = 0.5 =>
+ * suboptimal region = [ 0.0, 0.3 [
+ * optimum region = [ 0.3, 0.7 ]
+ * suboptimal region = ] 0.7, 1.0 ]
+ */
+ [ 0.0, 0.5, false, true, false ],
+ [ 0.1, 0.5, false, true, false ],
+ [ 0.3, 0.5, true, false, false ],
+ [ 0.5, 0.5, true, false, false ],
+ [ 0.7, 0.5, true, false, false ],
+ [ 0.8, 0.5, false, true, false ],
+ [ 1.0, 0.5, false, true, false ],
+ /*
+ * optimum = 0.7 =>
+ * suboptimal region = [ 0.0, 0.3 [
+ * optimum region = [ 0.3, 0.7 ]
+ * suboptimal region = ] 0.7, 1.0 ]
+ */
+ [ 0.0, 0.7, false, true, false ],
+ [ 0.1, 0.7, false, true, false ],
+ [ 0.3, 0.7, true, false, false ],
+ [ 0.5, 0.7, true, false, false ],
+ [ 0.7, 0.7, true, false, false ],
+ [ 0.8, 0.7, false, true, false ],
+ [ 1.0, 0.7, false, true, false ],
+ /*
+ * optimum = 0.8 =>
+ * sub-suboptimal region = [ 0.0, 0.3 [
+ * suboptimal region = [ 0.3, 0.7 ]
+ * optimum region = ] 0.7, 1.0 ]
+ */
+ [ 0.0, 0.8, false, false, true ],
+ [ 0.1, 0.8, false, false, true ],
+ [ 0.3, 0.8, false, true, false ],
+ [ 0.5, 0.8, false, true, false ],
+ [ 0.7, 0.8, false, true, false ],
+ [ 0.8, 0.8, true, false, false ],
+ [ 1.0, 0.8, true, false, false ],
+ /*
+ * optimum = 1.0 =>
+ * sub-suboptimal region = [ 0.0, 0.3 [
+ * suboptimal region = [ 0.3, 0.7 ]
+ * optimum region = ] 0.7, 1.0 ]
+ */
+ [ 0.0, 1.0, false, false, true ],
+ [ 0.1, 1.0, false, false, true ],
+ [ 0.3, 1.0, false, true, false ],
+ [ 0.5, 1.0, false, true, false ],
+ [ 0.7, 1.0, false, true, false ],
+ [ 0.8, 1.0, true, false, false ],
+ [ 1.0, 1.0, true, false, false ],
+ ];
+
+ for (var test of tests) {
+ checkOptimum(element, test[0], test[1], test[2]);
+ checkSubOptimum(element, test[0], test[1], test[3]);
+ checkSubSubOptimum(element, test[0], test[1], test[4]);
+ }
+}
+
+checkMozMatchesSelector();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_min_attribute.html b/dom/html/test/forms/test_min_attribute.html
new file mode 100644
index 000000000..1258babec
--- /dev/null
+++ b/dom/html/test/forms/test_min_attribute.html
@@ -0,0 +1,437 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=635553
+-->
+<head>
+ <title>Test for Bug 635553</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 635553 **/
+
+var data = [
+ { type: 'hidden', apply: false },
+ { type: 'text', apply: false },
+ { type: 'search', apply: false },
+ { type: 'tel', apply: false },
+ { type: 'url', apply: false },
+ { type: 'email', apply: false },
+ { type: 'password', apply: false },
+ { type: 'date', apply: true },
+ { type: 'month', apply: true },
+ { type: 'week', apply: true },
+ { type: 'time', apply: true },
+ // TODO: temporary set to false until bug 888331 is fixed.
+ { type: 'datetime-local', apply: false },
+ { type: 'number', apply: true },
+ { type: 'range', apply: true },
+ { type: 'color', apply: false },
+ { type: 'checkbox', apply: false },
+ { type: 'radio', apply: false },
+ { type: 'file', apply: false },
+ { type: 'submit', apply: false },
+ { type: 'image', apply: false },
+ { type: 'reset', apply: false },
+ { type: 'button', apply: false },
+];
+
+var input = document.createElement("input");
+document.getElementById('content').appendChild(input);
+
+/**
+ * @aValidity - boolean indicating whether the element is expected to be valid
+ * (aElement.validity.valid is true) or not. The value passed is ignored and
+ * overridden with true if aApply is false.
+ * @aApply - boolean indicating whether the min/max attributes apply to this
+ * element type.
+ * @aRangeApply - A boolean that's set to true if the current input type is a
+ * "[candidate] for constraint validation" and it "[has] range limitations"
+ * per http://www.whatwg.org/specs/web-apps/current-work/multipage/selectors.html#selector-in-range
+ * (in other words, one of the pseudo classes :in-range and :out-of-range
+ * should apply (which, depends on aValidity)).
+ * Else (neither :in-range or :out-of-range should match) set to false.
+ */
+function checkValidity(aElement, aValidity, aApply, aRangeApply)
+{
+ aValidity = aApply ? aValidity : true;
+
+ is(aElement.validity.valid, aValidity,
+ "element validity should be " + aValidity);
+ is(aElement.validity.rangeUnderflow, !aValidity,
+ "element underflow status should be " + !aValidity);
+ var underflowMsg =
+ (aElement.type == "date" || aElement.type == "time" ||
+ aElement.type == "month" || aElement.type == "week") ?
+ ("Please select a value that is no earlier than " + aElement.min + ".") :
+ ("Please select a value that is no less than " + aElement.min + ".");
+ is(aElement.validationMessage,
+ aValidity ? "" : underflowMsg, "Checking range underflow validation message");
+
+ is(aElement.matches(":valid"), aElement.willValidate && aValidity,
+ (aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply");
+ is(aElement.matches(":invalid"), aElement.willValidate && !aValidity,
+ (aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply");
+
+ if (!aRangeApply) {
+ ok(!aElement.matches(":in-range"), ":in-range should not match");
+ ok(!aElement.matches(":out-of-range"),
+ ":out-of-range should not match");
+ } else {
+ is(aElement.matches(":in-range"), aValidity,
+ ":in-range matches status should be " + aValidity);
+ is(aElement.matches(":out-of-range"), !aValidity,
+ ":out-of-range matches status should be " + !aValidity);
+ }
+}
+
+for (var test of data) {
+ input.type = test.type;
+ var apply = test.apply;
+
+ if (test.todo) {
+ todo_is(input.type, test.type, test.type + " isn't implemented yet");
+ continue;
+ }
+
+ // The element should be valid. Range should not apply when @min and @max are
+ // undefined, except if the input type is 'range' (since that type has a
+ // default minimum and maximum).
+ if (input.type == 'range') {
+ checkValidity(input, true, apply, true);
+ } else {
+ checkValidity(input, true, apply, false);
+ }
+
+ switch (input.type) {
+ case 'hidden':
+ case 'text':
+ case 'search':
+ case 'password':
+ case 'url':
+ case 'tel':
+ case 'email':
+ case 'number':
+ case 'checkbox':
+ case 'radio':
+ case 'file':
+ case 'submit':
+ case 'reset':
+ case 'button':
+ case 'image':
+ case 'color':
+ input.min = '999';
+ break;
+ case 'date':
+ input.min = '2012-06-27';
+ break;
+ case 'time':
+ input.min = '20:20';
+ break;
+ case 'range':
+ // range is special, since setting min to 999 will make it invalid since
+ // it's default maximum is 100, its value would be 999, and it would
+ // suffer from overflow.
+ break;
+ case 'month':
+ input.min = '2016-06';
+ break;
+ case 'week':
+ input.min = "2016-W39";
+ break;
+ case 'datetime-local':
+ // TODO: this is temporary until bug 888331 is fixed.
+ break;
+ default:
+ ok(false, 'please, add a case for this new type (' + input.type + ')');
+ }
+
+ // The element should still be valid and range should apply if it can.
+ checkValidity(input, true, apply, apply);
+
+ switch (input.type) {
+ case 'text':
+ case 'hidden':
+ case 'search':
+ case 'password':
+ case 'tel':
+ case 'radio':
+ case 'checkbox':
+ case 'reset':
+ case 'button':
+ case 'submit':
+ case 'image':
+ case 'color':
+ input.value = '0';
+ checkValidity(input, true, apply, apply);
+ break;
+ case 'url':
+ input.value = 'http://mozilla.org';
+ checkValidity(input, true, apply, apply);
+ break;
+ case 'email':
+ input.value = 'foo@bar.com';
+ checkValidity(input, true, apply, apply);
+ break;
+ case 'file':
+ var file = new File([''], '635499_file');
+
+ SpecialPowers.wrap(input).mozSetFileArray([file]);
+ checkValidity(input, true, apply, apply);
+
+ break;
+ case 'date':
+ input.value = '2012-06-28';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2012-06-27';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2012-06-26';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '2012-02-29';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2012-02-28';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '1000-01-01';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '20120-01-01';
+ checkValidity(input, true, apply, apply);
+
+ input.min = '0050-01-01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '0049-01-01';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '';
+ checkValidity(input, true, apply, false);
+
+ input.min = 'foo';
+ checkValidity(input, true, apply, false);
+ break;
+ case 'number':
+ input.min = '0';
+ input.value = '1';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '0';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '-1';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '-1';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '-42';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '';
+ checkValidity(input, true, apply, false);
+
+ input.min = 'foo';
+ checkValidity(input, true, apply, false);
+
+ // Check that we correctly convert input.min to a double in
+ // validationMessage.
+ input.min = "4.333333333333333333333333333333333331";
+ input.value = "2";
+ is(input.validationMessage,
+ "Please select a value that is no less than 4.33333333333333.",
+ "validation message");
+ break;
+ case 'range':
+ input.min = '0';
+ input.value = '1';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '0';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '-1';
+ checkValidity(input, true, apply, apply);
+
+ is(input.value, input.min, "the value should have been set to min");
+
+ input.min = '-1';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '-42';
+ checkValidity(input, true, apply, apply);
+
+ is(input.value, input.min, "the value should have been set to min");
+
+ input.min = '';
+ checkValidity(input, true, apply, true);
+
+ input.min = 'foo';
+ checkValidity(input, true, apply, true);
+
+ // We don't check the conversion of input.min to a double in
+ // validationMessage for 'range' since range will always clamp the value
+ // up to at least the minimum (so we will never see the min in a
+ // validationMessage).
+
+ break;
+ case 'time':
+ // Don't worry about that.
+ input.step = 'any';
+
+ input.min = '20:20';
+ input.value = '20:20:01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '20:20:00';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '10:00';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '20:20:00.001';
+ input.value = '20:20';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '00:00';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '23:59';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '20:20:01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '20:20:00.01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '20:20:00.1';
+ checkValidity(input, true, apply, apply);
+
+ input.min = '00:00:00';
+ input.value = '01:00';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '00:00:00.000';
+ checkValidity(input, true, apply, apply);
+
+ input.min = '';
+ checkValidity(input, true, apply, false);
+
+ input.min = 'foo';
+ checkValidity(input, true, apply, false);
+ break;
+ case 'month':
+ input.value = '2016-07';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2016-06';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2016-05';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '2016-01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2015-12';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '1000-01';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '10000-01';
+ checkValidity(input, true, apply, apply);
+
+ input.min = '0010-01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '0001-01';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '';
+ checkValidity(input, true, apply, false);
+
+ input.min = 'foo';
+ checkValidity(input, true, apply, false);
+ break;
+ case 'week':
+ input.value = '2016-W40';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2016-W39';
+ checkValidity(input, true, apply, apply);
+
+ input.value = 'foo';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2016-W38';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '2016-W01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '2015-W53';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '1000-W01';
+ checkValidity(input, false, apply, apply);
+
+ input.value = '10000-01';
+ checkValidity(input, true, apply, apply);
+
+ input.min = '0010-W01';
+ checkValidity(input, true, apply, apply);
+
+ input.value = '0001-W01';
+ checkValidity(input, false, apply, apply);
+
+ input.min = '';
+ checkValidity(input, true, apply, false);
+
+ input.min = 'foo';
+ checkValidity(input, true, apply, false);
+ break;
+ case 'datetime-local':
+ // TODO: this is temporary until bug 888331 is fixed.
+ break;
+ default:
+ ok(false, 'write tests for ' + input.type);
+ }
+
+ // Cleaning up,
+ input.removeAttribute('min');
+ input.value = '';
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_minlength_attribute.html b/dom/html/test/forms/test_minlength_attribute.html
new file mode 100644
index 000000000..ca3743bd9
--- /dev/null
+++ b/dom/html/test/forms/test_minlength_attribute.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=345624
+-->
+<head>
+ <title>Test for Bug 345624</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ input, textarea { background-color: rgb(0,0,0) !important; }
+ :-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; }
+ :-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
+<p id="display"></p>
+<div id="content">
+ <input id='i'>
+ <textarea id='t'></textarea>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 345624 **/
+
+/**
+ * This test is checking only tooShort related features
+ * related to constraint validation.
+ */
+
+function checkTooShortValidity(element)
+{
+ element.value = "foo";
+ ok(!element.validity.tooShort,
+ "Element should not be too short when minlength is not set");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "The element should be valid");
+
+ element.minLength = 5;
+ ok(!element.validity.tooShort,
+ "Element should not be too short unless the user edits it");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "The element should be valid");
+
+ element.focus();
+
+ synthesizeKey("o", {});
+ is(element.value, "fooo", "value should have changed");
+ ok(element.validity.tooShort,
+ "Element should be too short after a user edit that does not make it short enough");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+ ok(!element.validity.valid, "Element should be invalid");
+ ok(!element.checkValidity(), "The element should not be valid");
+ is(element.validationMessage,
+ "Please use at least 5 characters (you are currently using 4 characters).",
+ "The validation message text is not correct");
+
+ synthesizeKey("o", {});
+ is(element.value, "foooo", "value should have changed");
+ ok(!element.validity.tooShort,
+ "Element should not be too short after a user edit makes it long enough");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+
+ element.minLength = 2;
+ ok(!element.validity.tooShort,
+ "Element should remain valid if minlength changes but minlength < length");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+
+ element.minLength = 1;
+ ok(!element.validity.tooShort,
+ "Element should remain valid if minlength changes but minlength = length");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "The element should be valid");
+
+ element.minLength = 6;
+ ok(element.validity.tooShort,
+ "Element should become invalid if minlength changes and minlength > length");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+ ok(!element.validity.valid, "Element should be invalid");
+ ok(!element.checkValidity(), "The element should not be valid");
+ is(element.validationMessage,
+ "Please use at least 6 characters (you are currently using 5 characters).",
+ "The validation message text is not correct");
+
+ element.minLength = 5;
+ ok(!element.validity.tooShort,
+ "Element should become valid if minlength changes and minlength = length");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "The element should be valid");
+
+ element.value = "test";
+ ok(!element.validity.tooShort,
+ "Element should stay valid after programmatic edit (even if value is too short)");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "The element should be valid");
+
+ element.setCustomValidity("custom message");
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+ is(element.validationMessage, "custom message",
+ "Custom message should be shown instead of too short one");
+}
+
+checkTooShortValidity(document.getElementById('i'));
+checkTooShortValidity(document.getElementById('t'));
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/forms/test_mozistextfield.html b/dom/html/test/forms/test_mozistextfield.html
new file mode 100644
index 000000000..7c5a6bc5a
--- /dev/null
+++ b/dom/html/test/forms/test_mozistextfield.html
@@ -0,0 +1,111 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=565538
+-->
+<head>
+ <title>Test for Bug 565538</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=565538">Mozilla Bug 565538</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 565538 **/
+
+var gElementTestData = [
+/* element result */
+ ['input', true],
+ ['button', false],
+ ['fieldset', false],
+ ['label', false],
+ ['option', false],
+ ['optgroup', false],
+ ['output', false],
+ ['legend', false],
+ ['select', false],
+ ['textarea', false],
+ ['object', false],
+];
+
+var gInputTestData = [
+/* type result */
+ ['password', true],
+ ['tel', true],
+ ['text', true],
+ ['button', false],
+ ['checkbox', false],
+ ['file', false],
+ ['hidden', false],
+ ['reset', false],
+ ['image', false],
+ ['radio', false],
+ ['submit', false],
+ ['search', true],
+ ['email', true],
+ ['url', true],
+ ['number', false],
+ ['range', false],
+ ['date', false],
+ ['time', false],
+ ['color', false],
+ ['month', false],
+ ['week', false],
+ ['datetime-local', false],
+];
+
+function checkMozIsTextFieldDefined(aElement, aResult)
+{
+ var element = document.createElement(aElement);
+
+ var msg = "mozIsTextField should be "
+ if (aResult) {
+ msg += "defined";
+ } else {
+ msg += "undefined";
+ }
+
+ is('mozIsTextField' in element, aResult, msg);
+}
+
+function checkMozIsTextFieldValue(aInput, aResult)
+{
+ is(aInput.mozIsTextField(false), aResult,
+ "mozIsTextField(false) should return " + aResult);
+
+ if (aInput.type == 'password') {
+ ok(!aInput.mozIsTextField(true),
+ "mozIsTextField(true) should return false for password");
+ } else {
+ is(aInput.mozIsTextField(true), aResult,
+ "mozIsTextField(true) should return " + aResult);
+ }
+}
+
+function checkMozIsTextFieldValueTodo(aInput, aResult)
+{
+ todo_is(aInput.mozIsTextField(false), aResult,
+ "mozIsTextField(false) should return " + aResult);
+ todo_is(aInput.mozIsTextField(true), aResult,
+ "mozIsTextField(true) should return " + aResult);
+}
+
+// Check if the method is defined for the correct elements.
+for (data of gElementTestData) {
+ checkMozIsTextFieldDefined(data[0], data[1]);
+}
+
+// Check if the method returns the correct value.
+var input = document.createElement('input');
+for (data of gInputTestData) {
+ input.type = data[0];
+ checkMozIsTextFieldValue(input, data[1]);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_novalidate_attribute.html b/dom/html/test/forms/test_novalidate_attribute.html
new file mode 100644
index 000000000..38b789f5f
--- /dev/null
+++ b/dom/html/test/forms/test_novalidate_attribute.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=556013
+-->
+<head>
+ <title>Test for Bug 556013</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=556013">Mozilla Bug 556013</a>
+<p id="display"></p>
+<iframe style='width:50px; height: 50px;' name='t'></iframe>
+<div id="content">
+ <form target='t' action='data:text/html,' novalidate>
+ <input id='av' required>
+ <input id='a' type='submit'>
+ </form>
+ <form target='t' action='data:text/html,' novalidate>
+ <input id='bv' type='checkbox' required>
+ <button id='b' type='submit'></button>
+ </form>
+ <form target='t' action='data:text/html,' novalidate>
+ <input id='c' required>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 556013 **/
+
+/**
+ * novalidate should prevent form validation, thus not blocking form submission.
+ *
+ * NOTE: if there is no invalidformsubmit observer, the form submission will
+ * never be blocked and this test might be a false-positive but that should not
+ * be a problem.
+ */
+document.forms[0].addEventListener("submit", function(aEvent) {
+ aEvent.target.removeEventListener("submit", arguments.callee, false);
+ ok(true, "novalidate has been correctly used for first form");
+ document.getElementById('b').click();
+}, false);
+
+document.forms[1].addEventListener("submit", function(aEvent) {
+ aEvent.target.removeEventListener("submit", arguments.callee, false);
+ ok(true, "novalidate has been correctly used for second form");
+ var c = document.getElementById('c');
+ c.focus();
+ synthesizeKey("KEY_Enter", { code: "Enter" });
+}, false);
+
+document.forms[2].addEventListener("submit", function(aEvent) {
+ aEvent.target.removeEventListener("submit", arguments.callee, false);
+ ok(true, "novalidate has been correctly used for third form");
+ SimpleTest.executeSoon(SimpleTest.finish);
+}, false);
+
+/**
+ * We have to be sure invalid events are not send too.
+ * They should be sent before the submit event so we can just create a test
+ * failure if we got one. All of them should be catched if sent.
+ * At worst, we got random green which isn't harmful.
+ */
+function invalidHandling(aEvent)
+{
+ aEvent.target.removeEventListener("invalid", invalidHandling, false);
+ ok(false, "invalid event should not be sent");
+}
+
+document.getElementById('av').addEventListener("invalid", invalidHandling, false);
+document.getElementById('bv').addEventListener("invalid", invalidHandling, false);
+document.getElementById('c').addEventListener("invalid", invalidHandling, false);
+
+SimpleTest.waitForExplicitFinish();
+
+// This is going to call all the tests (with a chain reaction).
+SimpleTest.waitForFocus(function() {
+ document.getElementById('a').click();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_option_disabled.html b/dom/html/test/forms/test_option_disabled.html
new file mode 100644
index 000000000..1383b0846
--- /dev/null
+++ b/dom/html/test/forms/test_option_disabled.html
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=759666
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for HTMLOptionElement disabled attribute and pseudo-class</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=759666">Mozilla Bug 759666</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLOptionElement disabled attribute and pseudo-class **/
+
+var testCases = [
+ // Static checks.
+ { html: "<option></option>",
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<option disabled></option>",
+ result: { attr: "", idl: true, pseudo: true } },
+ { html: "<optgroup><option></option></otpgroup>",
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<optgroup><option disabled></option></optgroup>",
+ result: { attr: "", idl: true, pseudo: true } },
+ { html: "<optgroup disabled><option disabled></option></optgroup>",
+ result: { attr: "", idl: true, pseudo: true } },
+ { html: "<optgroup disabled><option></option></optgroup>",
+ result: { attr: null, idl: false, pseudo: true } },
+ { html: "<optgroup><optgroup disabled><option></option></optgroup></optgroup>",
+ result: { attr: null, idl: false, pseudo: true } },
+ { html: "<optgroup disabled><optgroup><option></option></optgroup></optgroup>",
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<optgroup disabled><optgroup><option disabled></option></optgroup></optgroup>",
+ result: { attr: "", idl: true, pseudo: true } },
+
+ // Dynamic checks: changing disable value.
+ { html: "<option></option>",
+ modifier: function(c) { c.querySelector('option').disabled = true; },
+ result: { attr: "", idl: true, pseudo: true } },
+ { html: "<option disabled></option>",
+ modifier: function(c) { c.querySelector('option').disabled = false; },
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<optgroup><option></option></otpgroup>",
+ modifier: function(c) { c.querySelector('optgroup').disabled = true; },
+ result: { attr: null, idl: false, pseudo: true } },
+ { html: "<optgroup><option disabled></option></optgroup>",
+ modifier: function(c) { c.querySelector('option').disabled = false; },
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<optgroup disabled><option disabled></option></optgroup>",
+ modifier: function(c) { c.querySelector('optgroup').disabled = false; },
+ result: { attr: "", idl: true, pseudo: true } },
+ { html: "<optgroup disabled><option disabled></option></optgroup>",
+ modifier: function(c) { c.querySelector('option').disabled = false; },
+ result: { attr: null, idl: false, pseudo: true } },
+ { html: "<optgroup disabled><option disabled></option></optgroup>",
+ modifier: function(c) { c.querySelector('optgroup').disabled = c.querySelector('option').disabled = false; },
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<optgroup disabled><option></option></optgroup>",
+ modifier: function(c) { c.querySelector('optgroup').disabled = false; },
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<optgroup><optgroup disabled><option></option></optgroup></optgroup>",
+ modifier: function(c) { c.querySelector('optgroup[disabled]').disabled = false; },
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<optgroup disabled><optgroup><option></option></optgroup></optgroup>",
+ modifier: function(c) { c.querySelector('optgroup[disabled]').disabled = false; },
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<optgroup disabled><optgroup><option disabled></option></optgroup></optgroup>",
+ modifier: function(c) { c.querySelector('optgroup').disabled = false; },
+ result: { attr: "", idl: true, pseudo: true } },
+ { html: "<optgroup disabled><optgroup><option disabled></option></optgroup></optgroup>",
+ modifier: function(c) { c.querySelector('option').disabled = false; },
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<optgroup disabled><optgroup><option disabled></option></optgroup></optgroup>",
+ modifier: function(c) { c.querySelector('option').disabled = c.querySelector('option').disabled = false; },
+ result: { attr: null, idl: false, pseudo: false } },
+
+ // Dynamic checks: moving option element.
+ { html: "<optgroup id='a'><option></option></optgroup><optgroup id='b'></optgroup>",
+ modifier: function(c) { c.querySelector('#b').appendChild(c.querySelector('option')); },
+ result: { attr: null, idl: false, pseudo: false } },
+ { html: "<optgroup id='a'><option disabled></option></optgroup><optgroup id='b'></optgroup>",
+ modifier: function(c) { c.querySelector('#b').appendChild(c.querySelector('option')); },
+ result: { attr: "", idl: true, pseudo: true } },
+ { html: "<optgroup id='a'><option></option></optgroup><optgroup disabled id='b'></optgroup>",
+ modifier: function(c) { c.querySelector('#b').appendChild(c.querySelector('option')); },
+ result: { attr: null, idl: false, pseudo: true } },
+ { html: "<optgroup disabled id='a'><option></option></optgroup><optgroup id='b'></optgroup>",
+ modifier: function(c) { c.querySelector('#b').appendChild(c.querySelector('option')); },
+ result: { attr: null, idl: false, pseudo: false } },
+];
+
+var content = document.getElementById('content');
+
+testCases.forEach(function(testCase) {
+ var result = testCase.result;
+
+ content.innerHTML = testCase.html;
+
+ if (testCase.modifier !== undefined) {
+ testCase.modifier(content);
+ }
+
+ var option = content.querySelector('option');
+ is(option.getAttribute('disabled'), result.attr, "disabled content attribute value should be " + result.attr);
+ is(option.disabled, result.idl, "disabled idl attribute value should be " + result.idl);
+ is(option.matches(":disabled"), result.pseudo, ":disabled state should be " + result.pseudo);
+ is(option.matches(":enabled"), !result.pseudo, ":enabled state should be " + !result.pseudo);
+
+ content.innerHTML = "";
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_option_index_attribute.html b/dom/html/test/forms/test_option_index_attribute.html
new file mode 100644
index 000000000..5d51d2991
--- /dev/null
+++ b/dom/html/test/forms/test_option_index_attribute.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+See those bugs:
+https://bugzilla.mozilla.org/show_bug.cgi?id=720385
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for option.index</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=720385">Mozilla Bug 720385</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <datalist>
+ <option></option>
+ <option></option>
+ </datalist>
+ <select>
+ <option></option>
+ <foo>
+ <option></option>
+ <optgroup>
+ <option></option>
+ </optgroup>
+ <option></option>
+ </foo>
+ <option></option>
+ </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 720385 **/
+
+var initialIndexes = [ 0, 0, 0, 1, 2, 3, 4 ];
+var options = document.getElementsByTagName('option');
+
+is(options.length, initialIndexes.length,
+ "Must have " + initialIndexes.length +" options");
+
+for (var i=0; i<options.length; ++i) {
+ is(options[i].index, initialIndexes[i], "test");
+}
+
+var o = document.createElement('option');
+is(o.index, 0, "option outside of a document have index=0");
+
+document.body.appendChild(o);
+is(o.index, 0, "option outside of a select have index=0");
+
+var datalist = document.getElementsByTagName('datalist')[0];
+
+datalist.appendChild(o);
+is(o.index, 0, "option outside of a select have index=0");
+
+datalist.removeChild(o);
+is(o.index, 0, "option outside of a select have index=0");
+
+var select = document.getElementsByTagName('select')[0];
+
+select.appendChild(o);
+is(o.index, 5, "option inside a select have an index");
+
+select.removeChild(select.options[0]);
+is(o.index, 4, "option inside a select have an index");
+
+select.insertBefore(o, select.options[0]);
+is(o.index, 0, "option inside a select have an index");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_option_text.html b/dom/html/test/forms/test_option_text.html
new file mode 100644
index 000000000..3afe3e786
--- /dev/null
+++ b/dom/html/test/forms/test_option_text.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>HTMLOptionElement.text</title>
+<link rel=author title=Ms2ger href="mailto:Ms2ger@gmail.com">
+<link rel=help href="http://www.whatwg.org/html/#dom-option-text">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id=log></div>
+<script>
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createElement("font"))
+ .appendChild(document.createTextNode(" font "));
+ assert_equals(option.text, "font");
+}, "option.text should recurse");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElement("script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before after");
+}, "option.text should not recurse into HTML script elements");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before after");
+}, "option.text should not recurse into SVG script elements");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElementNS("http://www.w3.org/1998/Math/MathML", "script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before script after");
+}, "option.text should recurse into MathML script elements");
+test(function() {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(" before "));
+ option.appendChild(document.createElementNS(null, "script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" after "));
+ assert_equals(option.text, "before script after");
+}, "option.text should recurse into null script elements");
+test(function() {
+ var option = document.createElement("option");
+ var span = option.appendChild(document.createElement("span"));
+ span.appendChild(document.createTextNode(" Some "));
+ span.appendChild(document.createElement("script"))
+ .appendChild(document.createTextNode(" script "));
+ option.appendChild(document.createTextNode(" Text "));
+ assert_equals(option.text, "Some Text");
+}, "option.text should work if a child of the option ends with a script");
+</script>
diff --git a/dom/html/test/forms/test_output_element.html b/dom/html/test/forms/test_output_element.html
new file mode 100644
index 000000000..5b4097047
--- /dev/null
+++ b/dom/html/test/forms/test_output_element.html
@@ -0,0 +1,182 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=346485
+-->
+<head>
+ <title>Test for Bug 346485</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="../reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+ frameLoaded = function() {
+ is(frames['submit_frame'].location.href, "about:blank",
+ "Blank frame loaded");
+ }
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=346485">Mozilla Bug 346485</a>
+<p id="display"></p>
+<iframe name="submit_frame" onload="frameLoaded()" style="visibility: hidden;"></iframe>
+<div id="content" style="display: none">
+ <form id='f' method='get' target='submit_frame' action='foo'>
+ <input name='a' id='a'>
+ <input name='b' id='b'>
+ <output id='o' for='a b' name='output-name'>tulip</output>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 346485 **/
+
+function checkNameAttribute(element)
+{
+ is(element.name, "output-name", "Output name IDL attribute is not correct");
+ is(element.getAttribute('name'), "output-name",
+ "Output name content attribute is not correct");
+}
+
+function checkValueAndDefaultValueIDLAttribute(element)
+{
+ is(element.value, element.textContent,
+ "The value IDL attribute should act like the textContent IDL attribute");
+
+ element.value = "foo";
+ is(element.value, "foo", "Value should be 'foo'");
+
+ is(element.defaultValue, "", "Default defaultValue is ''");
+
+ element.defaultValue = "bar";
+ is(element.defaultValue, "bar", "defaultValue should be 'bar'");
+
+ // More complex situation.
+ element.textContent = 'foo';
+ var b = document.createElement('b');
+ b.textContent = 'bar'
+ element.appendChild(b);
+ is(element.value, element.textContent,
+ "The value IDL attribute should act like the textContent IDL attribute");
+}
+
+function checkValueModeFlag(element)
+{
+ /**
+ * The value mode flag is the flag used to know if value should represent the
+ * textContent or the default value.
+ */
+ // value mode flag should be 'value'
+ isnot(element.defaultValue, element.value,
+ "When value is set, defaultValue keeps its value");
+
+ var f = document.getElementById('f');
+ f.reset();
+ // value mode flag should be 'default'
+ is(element.defaultValue, element.value, "When reset, defaultValue=value");
+ is(element.textContent, element.defaultValue,
+ "textContent should contain the defaultValue");
+}
+
+function checkDescendantChanged(element)
+{
+ /**
+ * Whenever a descendant is changed if the value mode flag is value,
+ * the default value should be the textContent value.
+ */
+ element.defaultValue = 'tulip';
+ element.value = 'foo';
+
+ // set value mode flag to 'default'
+ var f = document.getElementById('f');
+ f.reset();
+
+ is(element.textContent, element.defaultValue,
+ "textContent should contain the defaultValue");
+ element.textContent = "bar";
+ is(element.textContent, element.defaultValue,
+ "textContent should contain the defaultValue");
+}
+
+function checkFormIDLAttribute(element)
+{
+ is(element.form, document.getElementById('f'),
+ "form IDL attribute is invalid");
+}
+
+function checkHtmlForIDLAttribute(element)
+{
+ is(String(element.htmlFor), 'a b',
+ "htmlFor IDL attribute should reflect the for content attribute");
+
+ // DOMTokenList is tested in another bug so we just test assignation
+ element.htmlFor.value = 'a b c';
+ is(String(element.htmlFor), 'a b c', "htmlFor should have changed");
+}
+
+function submitForm()
+{
+ // Setting the values for the submit.
+ document.getElementById('o').value = 'foo';
+ document.getElementById('a').value = 'afield';
+ document.getElementById('b').value = 'bfield';
+
+ frameLoaded = checkFormSubmission;
+
+ // This will call checkFormSubmission() which is going to call ST.finish().
+ document.getElementById('f').submit();
+}
+
+function checkFormSubmission()
+{
+ /**
+ * All elements values have been set just before the submission.
+ * The input elements values should be in the submit url but the ouput
+ * element value should not appear.
+ */
+
+ is(frames['submit_frame'].location.href,
+ 'http://mochi.test:8888/tests/dom/html/test/forms/foo?a=afield&b=bfield',
+ "The output element value should not be submitted");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ reflectString({
+ element: document.createElement("output"),
+ attribute: "name",
+ });
+
+ var o = document.getElementsByTagName('output');
+ is(o.length, 1, "There should be one output element");
+
+ o = o[0];
+ ok(o instanceof HTMLOutputElement,
+ "The output should be instance of HTMLOutputElement");
+
+ o = document.getElementById('o');
+ ok(o instanceof HTMLOutputElement,
+ "The output should be instance of HTMLOutputElement");
+
+ is(o.type, "output", "Output type IDL attribute should be 'output'");
+
+ checkNameAttribute(o);
+
+ checkValueAndDefaultValueIDLAttribute(o);
+
+ checkValueModeFlag(o);
+
+ checkDescendantChanged(o);
+
+ checkFormIDLAttribute(o);
+
+ checkHtmlForIDLAttribute(o);
+
+ submitForm();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_pattern_attribute.html b/dom/html/test/forms/test_pattern_attribute.html
new file mode 100644
index 000000000..efa1a1543
--- /dev/null
+++ b/dom/html/test/forms/test_pattern_attribute.html
@@ -0,0 +1,324 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=345512
+-->
+<head>
+ <title>Test for Bug 345512</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ input { background-color: rgb(0,0,0) !important; }
+ input:valid { background-color: rgb(0,255,0) !important; }
+ input:invalid { background-color: rgb(255,0,0) !important; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345512">Mozilla Bug 345512</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <input id='i' pattern="tulip" oninvalid="invalidEventHandler(event);">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 345512 **/
+
+var gInvalid = false;
+
+function invalidEventHandler(e)
+{
+ is(e.type, "invalid", "Invalid event type should be invalid");
+ gInvalid = true;
+}
+
+function completeValidityCheck(element, alwaysValid, isBarred)
+{
+ // Check when pattern matches.
+ if (element.type == 'email') {
+ element.pattern = ".*@bar.com";
+ element.value = "foo@bar.com";
+ } else if (element.type == 'url') {
+ element.pattern = "http://.*\\.com$";
+ element.value = "http://mozilla.com";
+ } else if (element.type == 'file') {
+ element.pattern = "foo";
+ SpecialPowers.wrap(element).mozSetFileArray([new File(["foo"], "foo")]);
+ } else {
+ element.pattern = "foo";
+ element.value = "foo";
+ }
+
+ checkValidPattern(element, true, isBarred);
+
+ // Check when pattern does not match.
+
+ if (element.type == 'email') {
+ element.pattern = ".*@bar.com";
+ element.value = "foo@foo.com";
+ } else if (element.type == 'url') {
+ element.pattern = "http://.*\\.com$";
+ element.value = "http://mozilla.org";
+ } else if (element.type == 'file') {
+ element.pattern = "foo";
+ SpecialPowers.wrap(element).mozSetFileArray([new File(["bar"], "bar")]);
+ } else {
+ element.pattern = "foo";
+ element.value = "bar";
+ }
+
+ if (!alwaysValid) {
+ checkInvalidPattern(element, true);
+ } else {
+ checkValidPattern(element, true, isBarred);
+ }
+}
+
+function checkValidPattern(element, completeCheck, isBarred)
+{
+ if (completeCheck) {
+ gInvalid = false;
+
+ ok(!element.validity.patternMismatch,
+ "Element should not suffer from pattern mismatch");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "Element should be valid");
+ ok(!gInvalid, "Invalid event shouldn't have been thrown");
+ is(element.validationMessage, '',
+ "Validation message should be the empty string");
+ if (element.type != 'radio' && element.type != 'checkbox') {
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ isBarred ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)",
+ "The pseudo-class is not correctly applied");
+ }
+ } else {
+ ok(!element.validity.patternMismatch,
+ "Element should not suffer from pattern mismatch");
+ }
+}
+
+function checkInvalidPattern(element, completeCheck)
+{
+ if (completeCheck) {
+ gInvalid = false;
+
+ ok(element.validity.patternMismatch,
+ "Element should suffer from pattern mismatch");
+ ok(!element.validity.valid, "Element should not be valid");
+ ok(!element.checkValidity(), "Element should not be valid");
+ ok(gInvalid, "Invalid event should have been thrown");
+ is(element.validationMessage,
+ "Please match the requested format.",
+ "Validation message is not valid");
+ } else {
+ ok(element.validity.patternMismatch,
+ "Element should suffer from pattern mismatch");
+ }
+
+ if (element.type != 'radio' && element.type != 'checkbox') {
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+ }
+}
+
+function checkSyntaxError(element)
+{
+ ok(!element.validity.patternMismatch,
+ "On SyntaxError, element should not suffer");
+}
+
+function checkPatternValidity(element)
+{
+ element.pattern = "foo";
+
+ element.value = '';
+ checkValidPattern(element);
+
+ element.value = "foo";
+ checkValidPattern(element);
+
+ element.value = "bar";
+ checkInvalidPattern(element);
+
+ element.value = "foobar";
+ checkInvalidPattern(element);
+
+ element.value = "foofoo";
+ checkInvalidPattern(element);
+
+ element.pattern = "foo\"bar";
+ element.value = "foo\"bar";
+ checkValidPattern(element);
+
+ element.value = 'foo"bar';
+ checkValidPattern(element);
+
+ element.pattern = "foo'bar";
+ element.value = "foo\'bar";
+ checkValidPattern(element);
+
+ element.pattern = "foo\\(bar";
+ element.value = "foo(bar";
+ checkValidPattern(element);
+
+ element.value = "foo";
+ checkInvalidPattern(element);
+
+ element.pattern = "foo\\)bar";
+ element.value = "foo)bar";
+ checkValidPattern(element);
+
+ element.value = "foo";
+ checkInvalidPattern(element);
+
+ // Check for 'i' flag disabled. Should be case sensitive.
+ element.value = "Foo";
+ checkInvalidPattern(element);
+
+ // We can't check for the 'g' flag because we only test, we don't execute.
+ // We can't check for the 'm' flag because .value shouldn't contain line breaks.
+
+ // We need '\\\\' because '\\' will produce '\\' and we want to escape the '\'
+ // for the regexp.
+ element.pattern = "foo\\\\bar";
+ element.value = "foo\\bar";
+ checkValidPattern(element);
+
+ // We may want to escape the ' in the pattern, but this is a SyntaxError
+ // when unicode flag is set.
+ element.pattern = "foo\\'bar";
+ element.value = "foo'bar";
+ checkSyntaxError(element);
+ element.value = "baz";
+ checkSyntaxError(element);
+
+ // We should check the pattern attribute do not pollute |RegExp.lastParen|.
+ is(RegExp.lastParen, "", "RegExp.lastParen should be the empty string");
+
+ element.pattern = "(foo)";
+ element.value = "foo";
+ checkValidPattern(element);
+ is(RegExp.lastParen, "", "RegExp.lastParen should be the empty string");
+
+ // That may sound weird but the empty string is a valid pattern value.
+ element.pattern = "";
+ element.value = "";
+ checkValidPattern(element);
+
+ element.value = "foo";
+ checkInvalidPattern(element);
+
+ // Checking some complex patterns. As we are using js regexp mechanism, these
+ // tests doesn't aim to test the regexp mechanism.
+ element.pattern = "\\d{2}\\s\\d{2}\\s\\d{4}"
+ element.value = "01 01 2010"
+ checkValidPattern(element);
+
+ element.value = "01/01/2010"
+ checkInvalidPattern(element);
+
+ element.pattern = "[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z_+])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,9}";
+ element.value = "foo@bar.com";
+ checkValidPattern(element);
+
+ element.value = "...@bar.com";
+ checkInvalidPattern(element);
+
+ element.pattern = "^(?:\\w{3,})$";
+ element.value = "foo";
+ checkValidPattern(element);
+
+ element.value = "f";
+ checkInvalidPattern(element);
+
+ // If @title is specified, it should be added in the validation message.
+ if (element.type == 'email') {
+ element.pattern = "foo@bar.com"
+ element.value = "bar@foo.com";
+ } else if (element.type == 'url') {
+ element.pattern = "http://mozilla.com";
+ element.value = "http://mozilla.org";
+ } else {
+ element.pattern = "foo";
+ element.value = "bar";
+ }
+ element.title = "this is an explanation of the regexp";
+ is(element.validationMessage,
+ "Please match the requested format: " + element.title + ".",
+ "Validation message is not valid");
+ element.title = "";
+ is(element.validationMessage,
+ "Please match the requested format.",
+ "Validation message is not valid");
+
+ element.pattern = "foo";
+ if (element.type == 'email') {
+ element.value = "bar@foo.com";
+ } else if (element.type == 'url') {
+ element.value = "http://mozilla.org";
+ } else {
+ element.value = "bar";
+ }
+ checkInvalidPattern(element);
+
+ element.removeAttribute('pattern');
+ checkValidPattern(element, true);
+
+ // Unicode pattern
+ for (var pattern of ["\\u{1F438}{2}", "\u{1F438}{2}",
+ "\\uD83D\\uDC38{2}", "\uD83D\uDC38{2}",
+ "\u{D83D}\u{DC38}{2}"]) {
+ element.pattern = pattern;
+
+ element.value = "\u{1F438}\u{1F438}";
+ checkValidPattern(element);
+
+ element.value = "\uD83D\uDC38\uD83D\uDC38";
+ checkValidPattern(element);
+
+ element.value = "\uD83D\uDC38\uDC38";
+ checkInvalidPattern(element);
+ }
+
+ element.pattern = "\\u{D83D}\\u{DC38}{2}";
+
+ element.value = "\u{1F438}\u{1F438}";
+ checkInvalidPattern(element);
+
+ element.value = "\uD83D\uDC38\uD83D\uDC38";
+ checkInvalidPattern(element);
+
+ element.value = "\uD83D\uDC38\uDC38";
+ checkInvalidPattern(element);
+}
+
+var input = document.getElementById('i');
+
+// |validTypes| are the types which accept @pattern
+// and |invalidTypes| are the ones which do not accept it.
+var validTypes = Array('text', 'password', 'search', 'tel', 'email', 'url');
+var barredTypes = Array('hidden', 'reset', 'button');
+var invalidTypes = Array('checkbox', 'radio', 'file', 'number', 'range', 'date',
+ 'time', 'color', 'submit', 'image', 'month', 'week',
+ 'datetime-local');
+
+for (type of validTypes) {
+ input.type = type;
+ completeValidityCheck(input, false);
+ checkPatternValidity(input);
+}
+
+for (type of barredTypes) {
+ input.type = type;
+ completeValidityCheck(input, true, true);
+}
+
+for (type of invalidTypes) {
+ input.type = type;
+ completeValidityCheck(input, true);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_progress_element.html b/dom/html/test/forms/test_progress_element.html
new file mode 100644
index 000000000..bb1f801b2
--- /dev/null
+++ b/dom/html/test/forms/test_progress_element.html
@@ -0,0 +1,314 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=514437
+https://bugzilla.mozilla.org/show_bug.cgi?id=633913
+-->
+<head>
+ <title>Test for progress element content and layout</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=514437">Mozilla Bug 514437</a>
+and
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=633913">Mozilla Bug 633913</a>
+<p id="display"></p>
+<iframe name="submit_frame" style="visibility: hidden;"></iframe>
+<div id="content" style="visibility: hidden;">
+ <form id='f' method='get' target='submit_frame' action='foo'>
+ <progress id='p'></progress>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.expectAssertions(0, 1);
+
+/** Test for progress element content and layout **/
+
+function checkFormIDLAttribute(aElement)
+{
+ is("form" in aElement, false, "<progress> shouldn't have a form attribute");
+}
+
+function checkAttribute(aElement, aAttribute, aNewValue, aExpectedValueForIDL)
+{
+ var expectedValueForIDL = aNewValue;
+ var expectedValueForContent = String(aNewValue);
+
+ if (aExpectedValueForIDL !== undefined) {
+ expectedValueForIDL = aExpectedValueForIDL;
+ }
+
+ if (aNewValue != null) {
+ aElement.setAttribute(aAttribute, aNewValue);
+ is(aElement.getAttribute(aAttribute), expectedValueForContent,
+ aAttribute + " content attribute should be " + expectedValueForContent);
+ is(aElement[aAttribute], expectedValueForIDL,
+ aAttribute + " IDL attribute should be " + expectedValueForIDL);
+
+ if (parseFloat(aNewValue) == aNewValue) {
+ aElement[aAttribute] = aNewValue;
+ is(aElement.getAttribute(aAttribute), expectedValueForContent,
+ aAttribute + " content attribute should be " + expectedValueForContent);
+ is(aElement[aAttribute], parseFloat(expectedValueForIDL),
+ aAttribute + " IDL attribute should be " + parseFloat(expectedValueForIDL));
+ }
+ } else {
+ aElement.removeAttribute(aAttribute);
+ is(aElement.getAttribute(aAttribute), null,
+ aAttribute + " content attribute should be null");
+ is(aElement[aAttribute], expectedValueForIDL,
+ aAttribute + " IDL attribute should be " + expectedValueForIDL);
+ }
+}
+
+function checkValueAttribute()
+{
+ var tests = [
+ // value has to be a valid float, its default value is 0.0 otherwise.
+ [ null, 0.0 ],
+ [ 'fo', 0.0 ],
+ // If value < 0.0, 0.0 is used instead.
+ [ -1.0, 0.0 ],
+ // If value >= max, max is used instead (max default value is 1.0).
+ [ 2.0, 1.0 ],
+ [ 1.0, 0.5, 0.5 ],
+ [ 10.0, 5.0, 5.0 ],
+ [ 13.37, 13.37, 42.0 ],
+ // Regular reflection.
+ [ 0.0 ],
+ [ 0.5 ],
+ [ 1.0 ],
+ // Check double-precision value.
+ [ 0.234567898765432 ],
+ ];
+
+ var element = document.createElement('progress');
+
+ for (var test of tests) {
+ if (test[2]) {
+ element.setAttribute('max', test[2]);
+ }
+
+ checkAttribute(element, 'value', test[0], test[1]);
+
+ element.removeAttribute('max');
+ }
+}
+
+function checkMaxAttribute()
+{
+ var tests = [
+ // max default value is 1.0.
+ [ null, 1.0 ],
+ // If value <= 0.0, 1.0 is used instead.
+ [ 0.0, 1.0 ],
+ [ -1.0, 1.0 ],
+ // Regular reflection.
+ [ 0.5 ],
+ [ 1.0 ],
+ [ 2.0 ],
+ // Check double-precision value.
+ [ 0.234567898765432 ],
+ ];
+
+ var element = document.createElement('progress');
+
+ for (var test of tests) {
+ checkAttribute(element, 'max', test[0], test[1]);
+ }
+}
+
+function checkPositionAttribute()
+{
+ function checkPositionValue(aElement, aValue, aMax, aExpected) {
+ if (aValue != null) {
+ aElement.setAttribute('value', aValue);
+ } else {
+ aElement.removeAttribute('value');
+ }
+
+ if (aMax != null) {
+ aElement.setAttribute('max', aMax);
+ } else {
+ aElement.removeAttribute('max');
+ }
+
+ is(aElement.position, aExpected, "position IDL attribute should be " + aExpected);
+ }
+
+ var tests = [
+ // value has to be defined (indeterminate state).
+ [ null, null, -1.0 ],
+ [ null, 1.0, -1.0 ],
+ // value has to be defined to a valid float (indeterminate state).
+ [ 'foo', 1.0, -1.0 ],
+ // If value < 0.0, 0.0 is used instead.
+ [ -1.0, 1.0, 0.0 ],
+ // If value >= max, max is used instead.
+ [ 2.0, 1.0, 1.0 ],
+ // If max isn't present, max is set to 1.0.
+ [ 1.0, null, 1.0 ],
+ // If max isn't a valid float, max is set to 1.0.
+ [ 1.0, 'foo', 1.0 ],
+ // If max isn't > 0, max is set to 1.0.
+ [ 1.0, -1.0, 1.0 ],
+ // A few simple and valid values.
+ [ 0.0, 1.0, 0.0 ],
+ [ 0.1, 1.0, 0.1/1.0 ],
+ [ 0.1, 2.0, 0.1/2.0 ],
+ [ 10, 50, 10/50 ],
+ // Values implying .position is a double.
+ [ 1.0, 3.0, 1.0/3.0 ],
+ [ 0.1, 0.7, 0.1/0.7 ],
+ ];
+
+ var element = document.createElement('progress');
+
+ for (var test of tests) {
+ checkPositionValue(element, test[0], test[1], test[2], test[3]);
+ }
+}
+
+function checkIndeterminatePseudoClass()
+{
+ function checkIndeterminate(aElement, aValue, aMax, aIndeterminate) {
+ if (aValue != null) {
+ aElement.setAttribute('value', aValue);
+ } else {
+ aElement.removeAttribute('value');
+ }
+
+ if (aMax != null) {
+ aElement.setAttribute('max', aMax);
+ } else {
+ aElement.removeAttribute('max');
+ }
+
+ is(aElement.matches("progress:indeterminate"), aIndeterminate,
+ "<progress> indeterminate state should be " + aIndeterminate);
+ }
+
+ var tests = [
+ // Indeterminate state: (value is undefined, or not a float)
+ // value has to be defined (indeterminate state).
+ [ null, null, true ],
+ [ null, 1.0, true ],
+ [ 'foo', 1.0, true ],
+ // Determined state:
+ [ -1.0, 1.0, false ],
+ [ 2.0, 1.0, false ],
+ [ 1.0, null, false ],
+ [ 1.0, 'foo', false ],
+ [ 1.0, -1.0, false ],
+ [ 0.0, 1.0, false ],
+ ];
+
+ var element = document.createElement('progress');
+
+ for (var test of tests) {
+ checkIndeterminate(element, test[0], test[1], test[2]);
+ }
+}
+
+function checkFormListedElement(aElement)
+{
+ is(document.forms[0].elements.length, 0, "the form should have no element");
+}
+
+function checkLabelable(aElement)
+{
+ var content = document.getElementById('content');
+ var label = document.createElement('label');
+
+ content.appendChild(label);
+ label.appendChild(aElement);
+ is(label.control, aElement, "progress should be labelable");
+
+ // Cleaning-up.
+ content.removeChild(label);
+ content.appendChild(aElement);
+}
+
+function checkNotResetableAndFormSubmission(aElement)
+{
+ // Creating an input element to check the submission worked.
+ var form = document.forms[0];
+ var input = document.createElement('input');
+
+ input.name = 'a';
+ input.value = 'tulip';
+ form.appendChild(input);
+
+ // Setting values.
+ aElement.value = 42.0;
+ aElement.max = 100.0;
+
+ document.getElementsByName('submit_frame')[0].addEventListener("load", function() {
+ document.getElementsByName('submit_frame')[0].removeEventListener("load", arguments.callee, false);
+
+ /**
+ * All elements values have been set just before the submission.
+ * The input element value should be in the submit url but the progress
+ * element value should not appear.
+ */
+ is(frames['submit_frame'].location.href,
+ 'http://mochi.test:8888/tests/dom/html/test/forms/foo?a=tulip',
+ "The progress element value should not be submitted");
+
+ checkNotResetable();
+ }, false);
+
+ form.submit();
+}
+
+function checkNotResetable()
+{
+ // Try to reset the form.
+ var form = document.forms[0];
+ var element = document.getElementById('p');
+
+ element.value = 3.0;
+ element.max = 42.0;
+
+ form.reset();
+
+ SimpleTest.executeSoon(function() {
+ is(element.value, 3.0, "progress.value should not have changed");
+ is(element.max, 42.0, "progress.max should not have changed");
+
+ SimpleTest.finish();
+ });
+}
+
+SimpleTest.waitForExplicitFinish();
+
+var p = document.getElementById('p');
+
+ok(p instanceof HTMLProgressElement,
+ "The progress element should be instance of HTMLProgressElement");
+is(p.constructor, HTMLProgressElement,
+ "The progress element constructor should be HTMLProgressElement");
+
+checkFormIDLAttribute(p);
+
+checkValueAttribute();
+
+checkMaxAttribute();
+
+checkPositionAttribute();
+
+checkIndeterminatePseudoClass();
+
+checkFormListedElement(p);
+
+checkLabelable(p);
+
+checkNotResetableAndFormSubmission(p);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_radio_in_label.html b/dom/html/test/forms/test_radio_in_label.html
new file mode 100644
index 000000000..1676c9819
--- /dev/null
+++ b/dom/html/test/forms/test_radio_in_label.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=229925
+-->
+<head>
+ <title>Test for Bug 229925</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=229925">Mozilla Bug 229925</a>
+<p id="display"></p>
+<form>
+ <label>
+ <span id="s1">LABEL</span>
+ <input type="radio" name="rdo" value="1" id="r1" onmousedown="document.body.appendChild(document.createTextNode('down'));">
+ <input type="radio" name="rdo" value="2" id="r2" checked="checked">
+ </label>
+</form>
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 229925 **/
+SimpleTest.waitForExplicitFinish();
+var r1 = document.getElementById("r1");
+var r2 = document.getElementById("r2");
+var s1 = document.getElementById("s1");
+SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, startTest);
+function startTest() {
+ r1.click();
+ ok(r1.checked,
+ "The first radio input element should be checked by clicking the element");
+ r2.click();
+ ok(r2.checked,
+ "The second radio input element should be checked by clicking the element");
+ s1.click();
+ ok(r1.checked,
+ "The first radio input element should be checked by clicking other element");
+
+ r1.focus();
+ synthesizeKey("VK_LEFT", {});
+ ok(r2.checked,
+ "The second radio input element should be checked by key");
+ synthesizeKey("VK_LEFT", {});
+ ok(r1.checked,
+ "The first radio input element should be checked by key");
+ SimpleTest.finish();
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_radio_radionodelist.html b/dom/html/test/forms/test_radio_radionodelist.html
new file mode 100644
index 000000000..7f915bba9
--- /dev/null
+++ b/dom/html/test/forms/test_radio_radionodelist.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=779723
+-->
+<head>
+ <title>Test for Bug 779723</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=779723">Mozilla Bug 779723</a>
+<p id="display"></p>
+<form>
+ <input type="checkbox" name="rdo" value="0" id="r0" checked="checked">
+ <input type="radio" name="rdo" id="r1">
+ <input type="radio" name="rdo" id="r2" value="2">
+</form>
+<script class="testbody" type="text/javascript">
+/** Test for Bug 779723 **/
+
+var rdoList = document.forms[0].elements.namedItem('rdo');
+is(rdoList.value, "", "The value attribute should be empty");
+
+document.getElementById('r2').checked = true;
+ok(rdoList.value, "2", "The value attribute should be 2");
+
+document.getElementById('r1').checked = true;
+ok(rdoList.value, "on", "The value attribute should be on");
+
+document.getElementById('r1').value = 1;
+ok(rdoList.value, "1", "The value attribute should be 1");
+
+is(rdoList.value, document.getElementById('r1').value,
+ "The value attribute should be equal to the first checked radio input element's value");
+ok(!document.getElementById('r2').checked,
+ "The second radio input element should not be checked");
+
+rdoList.value = '2';
+is(rdoList.value, document.getElementById('r2').value,
+ "The value attribute should be equal to the second radio input element's value");
+ok(document.getElementById('r2').checked,
+ "The second radio input element should be checked");
+
+rdoList.value = '3';
+is(rdoList.value, document.getElementById('r2').value,
+ "The value attribute should be the second radio input element's value");
+ok(document.getElementById('r2').checked,
+ "The second radio input element should be checked");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/forms/test_reportValidation_preventDefault.html b/dom/html/test/forms/test_reportValidation_preventDefault.html
new file mode 100644
index 000000000..034bb2ed2
--- /dev/null
+++ b/dom/html/test/forms/test_reportValidation_preventDefault.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1088761
+-->
+<head>
+ <title>Test for Bug 1088761</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ input, textarea, fieldset, button, select, keygen, output, object { background-color: rgb(0,0,0) !important; }
+ :valid { background-color: rgb(0,255,0) !important; }
+ :invalid { background-color: rgb(255,0,0) !important; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1088761">Mozilla Bug 1088761</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <fieldset id='f' oninvalid="invalidEventHandler(event, true);"></fieldset>
+ <input id='i' required oninvalid="invalidEventHandler(event, true);">
+ <button id='b' oninvalid="invalidEventHandler(event, true);"></button>
+ <select id='s' required oninvalid="invalidEventHandler(event, true);"></select>
+ <textarea id='t' required oninvalid="invalidEventHandler(event, true);"></textarea>
+ <output id='o' oninvalid="invalidEventHandler(event, true);"></output>
+ <keygen id='k' oninvalid="invalidEventHandler(event, true);"></keygen>
+ <object id='obj' oninvalid="invalidEventHandler(event, true);"></object>
+</div>
+<div id="content2" style="display: none">
+ <fieldset id='f2' oninvalid="invalidEventHandler(event, false);"></fieldset>
+ <input id='i2' required oninvalid="invalidEventHandler(event, false);">
+ <button id='b2' oninvalid="invalidEventHandler(event, false);"></button>
+ <select id='s2' required oninvalid="invalidEventHandler(event, false);"></select>
+ <textarea id='t2' required oninvalid="invalidEventHandler(event, false);"></textarea>
+ <output id='o2' oninvalid="invalidEventHandler(event, false);"></output>
+ <keygen id='k2' oninvalid="invalidEventHandler(event, false);"></keygen>
+ <object id='obj2' oninvalid="invalidEventHandler(event, false);"></object>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1088761 **/
+
+var gInvalid = false;
+
+function invalidEventHandler(aEvent, isPreventDefault)
+{
+ if (isPreventDefault) {
+ aEvent.preventDefault();
+ }
+
+ is(aEvent.type, "invalid", "Invalid event type should be invalid");
+ ok(!aEvent.bubbles, "Invalid event should not bubble");
+ ok(aEvent.cancelable, "Invalid event should be cancelable");
+ gInvalid = true;
+}
+
+function checkReportValidityForInvalid(element)
+{
+ gInvalid = false;
+ ok(!element.reportValidity(), "reportValidity() should return false when the element is not valid");
+ ok(gInvalid, "Invalid event should have been handled");
+}
+
+function checkReportValidityForValid(element)
+{
+ gInvalid = false;
+ ok(element.reportValidity(), "reportValidity() should return true when the element is valid");
+ ok(!gInvalid, "Invalid event shouldn't have been handled");
+}
+
+checkReportValidityForInvalid(document.getElementById('i'));
+checkReportValidityForInvalid(document.getElementById('s'));
+checkReportValidityForInvalid(document.getElementById('t'));
+
+checkReportValidityForInvalid(document.getElementById('i2'));
+checkReportValidityForInvalid(document.getElementById('s2'));
+checkReportValidityForInvalid(document.getElementById('t2'));
+
+checkReportValidityForValid(document.getElementById('o'));
+checkReportValidityForValid(document.getElementById('k'));
+checkReportValidityForValid(document.getElementById('obj'));
+checkReportValidityForValid(document.getElementById('f'));
+
+checkReportValidityForValid(document.getElementById('o2'));
+checkReportValidityForValid(document.getElementById('k2'));
+checkReportValidityForValid(document.getElementById('obj2'));
+checkReportValidityForValid(document.getElementById('f2'));
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_required_attribute.html b/dom/html/test/forms/test_required_attribute.html
new file mode 100644
index 000000000..1f9d76cf1
--- /dev/null
+++ b/dom/html/test/forms/test_required_attribute.html
@@ -0,0 +1,382 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=345822
+-->
+<head>
+ <title>Test for Bug 345822</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345822">Mozilla Bug 345822</a>
+<p id="display"></p>
+<div id="content">
+ <form>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 345822 **/
+
+function checkNotSufferingFromBeingMissing(element, doNotApply)
+{
+ ok(!element.validity.valueMissing,
+ "Element should not suffer from value missing");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "Element should be valid");
+ is(element.validationMessage, "",
+ "Validation message should be the empty string");
+
+ if (doNotApply) {
+ ok(!element.matches(':valid'), ":valid should not apply");
+ ok(!element.matches(':invalid'), ":invalid should not apply");
+ ok(!element.matches(':-moz-ui-valid'), ":-moz-ui-valid should not apply");
+ ok(!element.matches(':-moz-ui-invalid'), ":-moz-ui-invalid should not apply");
+ } else {
+ ok(element.matches(':valid'), ":valid should apply");
+ ok(!element.matches(':invalid'), ":invalid should not apply");
+ ok(element.matches(':-moz-ui-valid'), ":-moz-ui-valid should apply");
+ ok(!element.matches(':-moz-ui-invalid'), ":-moz-ui-invalid should not apply");
+ }
+}
+
+function checkSufferingFromBeingMissing(element, hasMozUIInvalid)
+{
+ ok(element.validity.valueMissing, "Element should suffer from value missing");
+ ok(!element.validity.valid, "Element should not be valid");
+ ok(!element.checkValidity(), "Element should not be valid");
+
+ if (element.type == 'checkbox')
+ {
+ is(element.validationMessage,
+ "Please check this box if you want to proceed.",
+ "Validation message is wrong");
+ }
+ else if (element.type == 'radio')
+ {
+ is(element.validationMessage,
+ "Please select one of these options.",
+ "Validation message is wrong");
+ }
+ else if (element.type == 'file')
+ {
+ is(element.validationMessage,
+ "Please select a file.",
+ "Validation message is wrong");
+ }
+ else if (element.type == 'number')
+ {
+ is(element.validationMessage,
+ "Please enter a number.",
+ "Validation message is wrong");
+ }
+ else // text fields
+ {
+ is(element.validationMessage,
+ "Please fill out this field.",
+ "Validation message is wrong");
+ }
+
+ ok(!element.matches(':valid'), ":valid should apply");
+ ok(element.matches(':invalid'), ":invalid should not apply");
+ ok(!element.matches(':-moz-ui-valid'), ":-moz-ui-valid should not apply");
+ is(element.matches(':-moz-ui-invalid'), hasMozUIInvalid, ":-moz-ui-invalid expected state is " + hasMozUIInvalid);
+}
+
+function checkTextareaRequiredValidity()
+{
+ var element = document.createElement('textarea');
+ document.forms[0].appendChild(element);
+
+ SpecialPowers.wrap(element).value = '';
+ element.required = false;
+ checkNotSufferingFromBeingMissing(element);
+
+ element.required = true;
+ checkSufferingFromBeingMissing(element, true);
+
+ element.readOnly = true;
+ checkNotSufferingFromBeingMissing(element, true);
+
+ element.readOnly = false;
+ checkSufferingFromBeingMissing(element, true);
+
+ SpecialPowers.wrap(element).value = 'foo';
+ checkNotSufferingFromBeingMissing(element);
+
+ SpecialPowers.wrap(element).value = '';
+ checkSufferingFromBeingMissing(element, true);
+
+ element.required = false;
+ checkNotSufferingFromBeingMissing(element);
+
+ element.focus();
+ element.required = true;
+ SpecialPowers.wrap(element).value = 'foobar';
+ element.blur();
+ element.form.reset();
+ checkSufferingFromBeingMissing(element, false);
+
+ // TODO: for the moment, a textarea outside of a document is mutable.
+ SpecialPowers.wrap(element).value = ''; // To make -moz-ui-valid apply.
+ element.required = false;
+ document.forms[0].removeChild(element);
+ checkNotSufferingFromBeingMissing(element);
+}
+
+function checkInputRequiredNotApply(type, isBarred)
+{
+ var element = document.createElement('input');
+ element.type = type;
+ document.forms[0].appendChild(element);
+
+ SpecialPowers.wrap(element).value = '';
+ element.required = false;
+ checkNotSufferingFromBeingMissing(element, isBarred);
+
+ element.required = true;
+ checkNotSufferingFromBeingMissing(element, isBarred);
+
+ element.required = false;
+
+ document.forms[0].removeChild(element);
+ checkNotSufferingFromBeingMissing(element, isBarred);
+}
+
+function checkInputRequiredValidity(type)
+{
+ var element = document.createElement('input');
+ element.type = type;
+ document.forms[0].appendChild(element);
+
+ SpecialPowers.wrap(element).value = '';
+ element.required = false;
+ checkNotSufferingFromBeingMissing(element);
+
+ element.required = true;
+ checkSufferingFromBeingMissing(element, true);
+
+ element.readOnly = true;
+ checkNotSufferingFromBeingMissing(element, true);
+
+ element.readOnly = false;
+ checkSufferingFromBeingMissing(element, true);
+
+ if (element.type == 'email') {
+ SpecialPowers.wrap(element).value = 'foo@bar.com';
+ } else if (element.type == 'url') {
+ SpecialPowers.wrap(element).value = 'http://mozilla.org/';
+ } else if (element.type == 'number') {
+ SpecialPowers.wrap(element).value = '42';
+ } else if (element.type == 'date') {
+ SpecialPowers.wrap(element).value = '2010-10-10';
+ } else if (element.type == 'time') {
+ SpecialPowers.wrap(element).value = '21:21';
+ } else if (element.type = 'month') {
+ SpecialPowers.wrap(element).value = '2010-10';
+ } else {
+ SpecialPowers.wrap(element).value = 'foo';
+ }
+ checkNotSufferingFromBeingMissing(element);
+
+ SpecialPowers.wrap(element).value = '';
+ checkSufferingFromBeingMissing(element, true);
+
+ element.focus();
+ element.required = true;
+ SpecialPowers.wrap(element).value = 'foobar';
+ element.blur();
+ element.form.reset();
+ checkSufferingFromBeingMissing(element, false);
+
+ element.required = true;
+ SpecialPowers.wrap(element).value = ''; // To make :-moz-ui-valid apply.
+ checkSufferingFromBeingMissing(element, true);
+ document.forms[0].removeChild(element);
+ // Removing the child changes nothing about whether it's valid
+ checkSufferingFromBeingMissing(element, true);
+}
+
+function checkInputRequiredValidityForCheckbox()
+{
+ var element = document.createElement('input');
+ element.type = 'checkbox';
+ document.forms[0].appendChild(element);
+
+ element.checked = false;
+ element.required = false;
+ checkNotSufferingFromBeingMissing(element);
+
+ element.required = true;
+ checkSufferingFromBeingMissing(element, true);
+
+ element.checked = true;
+ checkNotSufferingFromBeingMissing(element);
+
+ element.checked = false;
+ checkSufferingFromBeingMissing(element, true);
+
+ element.required = false;
+ checkNotSufferingFromBeingMissing(element);
+
+ element.focus();
+ element.required = true;
+ element.checked = true;
+ element.blur();
+ element.form.reset();
+ checkSufferingFromBeingMissing(element, false);
+
+ element.required = true;
+ element.checked = false;
+ document.forms[0].removeChild(element);
+ checkSufferingFromBeingMissing(element, true);
+}
+
+function checkInputRequiredValidityForRadio()
+{
+ var element = document.createElement('input');
+ element.type = 'radio';
+ element.name = 'test'
+ document.forms[0].appendChild(element);
+
+ element.checked = false;
+ element.required = false;
+ checkNotSufferingFromBeingMissing(element);
+
+ element.required = true;
+ checkSufferingFromBeingMissing(element, true);
+
+ element.checked = true;
+ checkNotSufferingFromBeingMissing(element);
+
+ element.checked = false;
+ checkSufferingFromBeingMissing(element, true);
+
+ // A required radio button should not suffer from value missing if another
+ // radio button from the same group is checked.
+ var element2 = document.createElement('input');
+ element2.type = 'radio';
+ element2.name = 'test';
+
+ element2.checked = true;
+ element2.required = false;
+ document.forms[0].appendChild(element2);
+
+ // Adding a checked radio should make required radio in the group not
+ // suffering from being missing.
+ checkNotSufferingFromBeingMissing(element);
+
+ element.checked = false;
+ element2.checked = false;
+ checkSufferingFromBeingMissing(element, true);
+
+ // The other radio button should not be disabled.
+ // A disabled checked radio button in the radio group
+ // is enough to not suffer from value missing.
+ element2.checked = true;
+ element2.disabled = true;
+ checkNotSufferingFromBeingMissing(element);
+
+ // If a radio button is not required but another radio button is required in
+ // the same group, the not required radio button should suffer from value
+ // missing.
+ element2.disabled = false;
+ element2.checked = false;
+ element.required = false;
+ element2.required = true;
+ checkSufferingFromBeingMissing(element, true);
+ checkSufferingFromBeingMissing(element2, true);
+
+ element.checked = true;
+ checkNotSufferingFromBeingMissing(element2);
+
+ // The checked radio is not in the group anymore, element2 should be invalid.
+ element.form.removeChild(element);
+ checkNotSufferingFromBeingMissing(element);
+ checkSufferingFromBeingMissing(element2, true);
+
+ element2.focus();
+ element2.required = true;
+ element2.checked = true;
+ element2.blur();
+ element2.form.reset();
+ checkSufferingFromBeingMissing(element2, false);
+
+ element2.required = true;
+ element2.checked = false;
+ document.forms[0].removeChild(element2);
+ checkSufferingFromBeingMissing(element2, true);
+}
+
+function checkInputRequiredValidityForFile()
+{
+ var element = document.createElement('input');
+ element.type = 'file'
+ document.forms[0].appendChild(element);
+
+ var file = new File([""], "345822_file");
+
+ SpecialPowers.wrap(element).value = "";
+ element.required = false;
+ checkNotSufferingFromBeingMissing(element);
+
+ element.required = true;
+ checkSufferingFromBeingMissing(element, true);
+
+ SpecialPowers.wrap(element).mozSetFileArray([file]);
+ checkNotSufferingFromBeingMissing(element);
+
+ SpecialPowers.wrap(element).value = "";
+ checkSufferingFromBeingMissing(element, true);
+
+ element.required = false;
+ checkNotSufferingFromBeingMissing(element);
+
+ element.focus();
+ SpecialPowers.wrap(element).mozSetFileArray([file]);
+ element.required = true;
+ element.blur();
+ element.form.reset();
+ checkSufferingFromBeingMissing(element, false);
+
+ element.required = true;
+ SpecialPowers.wrap(element).value = '';
+ document.forms[0].removeChild(element);
+ checkSufferingFromBeingMissing(element, true);
+}
+
+checkTextareaRequiredValidity();
+
+// The require attribute behavior depend of the input type.
+// First of all, checks for types that make the element barred from
+// constraint validation.
+var typeBarredFromConstraintValidation = ["hidden", "button", "reset"];
+for (type of typeBarredFromConstraintValidation) {
+ checkInputRequiredNotApply(type, true);
+}
+
+// Then, checks for the types which do not use the required attribute.
+var typeRequireNotApply = ['range', 'color', 'submit', 'image'];
+for (type of typeRequireNotApply) {
+ checkInputRequiredNotApply(type, false);
+}
+
+// Now, checking for all types which accept the required attribute.
+var typeRequireApply = ["text", "password", "search", "tel", "email", "url",
+ "number", "date", "time", "month", "week",
+ "datetime-local"];
+
+for (type of typeRequireApply) {
+ checkInputRequiredValidity(type);
+}
+
+checkInputRequiredValidityForCheckbox();
+checkInputRequiredValidityForRadio();
+checkInputRequiredValidityForFile();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_restore_form_elements.html b/dom/html/test/forms/test_restore_form_elements.html
new file mode 100644
index 000000000..d92c5c7e9
--- /dev/null
+++ b/dom/html/test/forms/test_restore_form_elements.html
@@ -0,0 +1,174 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=737851
+-->
+<head>
+ <meta charset="utf-8">
+
+ <title>Test for Bug 737851</title>
+
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<body>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=737851">Mozilla Bug 737851</a>
+
+<p id="display"></p>
+
+
+<div id="content">
+
+ <iframe id="frame" width="800px" height="600px" src='data:text/html,
+ <html>
+ <body style="display:none;">
+
+ <h3>Checking persistence of inputs through js inserts and moves</h3>
+ <div id="test">
+ <input id="a"/>
+ <input id="b"/>
+ <form id="form1">
+ <input id="c"/>
+ <input id="d"/>
+ </form>
+ <form id="form2">
+ <input id="radio1" type="radio" name="radio"/>
+ <input type="radio" name="radio"/>
+ <input type="radio" name="radio"/>
+ <input type="radio" name="radio"/>
+ </form>
+ <input id="e"/>
+ </div>
+
+ <h3>Bug 728798: checking persistence of inputs when forward-using @form</h3>
+ <div>
+ <input id="728798-a" form="728798-form" name="a"/>
+ <form id="728798-form">
+ <input id="728798-b" form="728798-form" name="b"/>
+ <input id="728798-c" name="c"/>
+ </form>
+ <input id="728798-d" form="728798-form" name="d"/>
+ </div>
+
+ </body>
+ </html>
+ '></iframe>
+
+</div>
+
+
+<pre id="test">
+<script type="text/javascript">
+
+var frameElem = document.getElementById("frame");
+var frame = frameElem.contentWindow;
+
+
+/* -- Main test run -- */
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function() {
+ shuffle();
+ fill();
+ frameElem.addEventListener("load", function() {
+ shuffle();
+ checkAllFields();
+ SimpleTest.finish();
+ });
+ frame.location.reload();
+})
+
+
+/* -- Input fields js changes and moves -- */
+
+function shuffle() {
+ var framedoc = frame.document;
+
+ // Insert a button (toplevel)
+ var btn = framedoc.createElement("button");
+ var testdiv = framedoc.getElementById("test");
+ testdiv.insertBefore(btn, framedoc.getElementById("b"));
+
+ // Insert a dynamically generated input (in a form)
+ var newInput = framedoc.createElement("input");
+ newInput.setAttribute("id","c0");
+ var form1 = framedoc.getElementById("form1");
+ form1.insertBefore(newInput, form1.firstChild);
+
+ // Move an input around
+ var inputD = framedoc.getElementById("d");
+ var form2 = framedoc.getElementById("form2");
+ form2.insertBefore(inputD, form2.firstChild)
+
+ // Clone an existing input
+ var inputE2 = framedoc.getElementById("e").cloneNode(true);
+ inputE2.setAttribute("id","e2");
+ testdiv.appendChild(inputE2);
+}
+
+
+/* -- Input fields fill & check -- */
+
+/* Values entered in the input fields (by id) */
+
+var fieldValues = {
+ 'a':'simple input',
+ 'b':'moved by inserting a button before (no form)',
+ 'c0':'dynamically generated input',
+ 'c':'moved by inserting an input before (in a form)',
+ 'd':'moved from a form to another',
+ 'e':'the original',
+ 'e2':'the clone',
+ '728798-a':'before the form',
+ '728798-b':'from within the form',
+ '728798-c':'no form attribute in the form',
+ '728798-d':'after the form'
+}
+
+/* Fields for which the input is changed, and corresponding value
+ (clone and creation, same behaviour as webkit) */
+
+var changedFields = {
+ // dynamically generated input field not preserved
+ 'c0':'',
+ // cloned input field is restored with the value of the original
+ 'e2':fieldValues.e
+}
+
+/* Simulate user input by entering the values */
+
+function fill() {
+ for (id in fieldValues) {
+ frame.document.getElementById(id).value = fieldValues[id];
+ }
+ // an input is inserted before the radios (that may move the selected one by 1)
+ frame.document.getElementById('radio1').checked = true;
+}
+
+/* Check that all the fields are as they have been entered */
+
+function checkAllFields() {
+
+ for (id in fieldValues) {
+ var fieldValue = frame.document.getElementById(id).value;
+ if (changedFields[id] === undefined) {
+ is(fieldValue, fieldValues[id],
+ "Field "+id+" should be restored after reload");
+ } else {
+ is(fieldValue, changedFields[id],
+ "Field "+id+" normally gets a different value after reload");
+ }
+ }
+
+ ok(frame.document.getElementById('radio1').checked,
+ "Radio button radio1 should be restored after reload")
+
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_save_restore_radio_groups.html b/dom/html/test/forms/test_save_restore_radio_groups.html
new file mode 100644
index 000000000..837d5d681
--- /dev/null
+++ b/dom/html/test/forms/test_save_restore_radio_groups.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=350022
+-->
+<head>
+ <title>Test for Bug 350022</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=350022">Mozilla Bug 350022</a>
+<p id="display"></p>
+<div id="content"><!-- style="display: none">-->
+ <iframe src="save_restore_radio_groups.sjs"></iframe>
+ <iframe src="save_restore_radio_groups.sjs"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 350022 **/
+
+function checkRadioGroup(aFrame, aResults)
+{
+ var radios = frames[aFrame].document.getElementsByTagName('input');
+
+ is(radios.length, aResults.length,
+ "Radio group should have " + aResults.length + "elements");
+
+ for (var i=0; i<aResults.length; ++i) {
+ is(radios[i].checked, aResults[i],
+ "Radio checked state should be " + aResults[i]);
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ /**
+ * We have two iframes each containing one radio button group.
+ * We are going to change the selected radio button in one group.
+ * Then, both iframes will be reloaded and the new groups will have another
+ * radio checked by default.
+ * For the first group (which had a selection change), nothing should change.
+ * For the second, the selected radio button should change.
+ */
+ checkRadioGroup(0, [true, false, false]);
+ checkRadioGroup(1, [true, false, false]);
+
+ frames[0].document.getElementsByTagName('input')[2].checked = true;
+ checkRadioGroup(0, [false, false, true]);
+
+ framesElts = document.getElementsByTagName('iframe');
+ framesElts[0].addEventListener("load", function() {
+ framesElts[0].removeEventListener("load", arguments.callee, false);
+ checkRadioGroup(0, [false, false, true]);
+
+ framesElts[1].addEventListener("load", function() {
+ framesElts[1].removeEventListener("load", arguments.callee, false);
+
+ checkRadioGroup(1, [false, true, false]);
+ SimpleTest.finish();
+ }, false);
+
+ frames[1].location.reload();
+ }, false);
+
+ frames[0].location.reload();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_select_change_event.html b/dom/html/test/forms/test_select_change_event.html
new file mode 100644
index 000000000..80d3cd09d
--- /dev/null
+++ b/dom/html/test/forms/test_select_change_event.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1265968
+-->
+<head>
+ <title>Test for Bug 1265968</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1265968">Mozilla Bug 1265968</a>
+<p id="display"></p>
+<div id="content">
+ <select id="select" onchange="++selectChange;">
+ <option>one</option>
+ <option>two</option>
+ <option>three</option>
+ <option>four</option>
+ <option>five</option>
+ </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+ var select = document.getElementById("select");
+ var selectChange = 0;
+ var expectedChange = 0;
+
+ select.focus();
+ for (var i = 1; i < select.length; i++) {
+ synthesizeKey("VK_DOWN", {});
+ is(select.options[i].selected, true, "Option should be selected");
+ is(selectChange, ++expectedChange, "Down key should fire change event.");
+ }
+
+ // We are at the end of the list, going down should not fire change event.
+ synthesizeKey("VK_DOWN", {});
+ is(selectChange, expectedChange, "Down key should not fire change event when reaching end of the list.");
+
+ for (var i = select.length - 2; i >= 0; i--) {
+ synthesizeKey("VK_UP", {});
+ is(select.options[i].selected, true, "Option should be selected");
+ is(selectChange, ++expectedChange, "Up key should fire change event.");
+ }
+
+ // We are at the top of the list, going up should not fire change event.
+ synthesizeKey("VK_UP", {});
+ is(selectChange, expectedChange, "Up key should not fire change event when reaching top of the list.");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_select_input_change_event.html b/dom/html/test/forms/test_select_input_change_event.html
new file mode 100644
index 000000000..fa1b24b41
--- /dev/null
+++ b/dom/html/test/forms/test_select_input_change_event.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1265968
+-->
+<head>
+ <title>Test for Bug 1024350</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1024350">Mozilla Bug 1024350</a>
+<p id="display"></p>
+<div id="content">
+ <select oninput='++selectInput;' onchange="++selectChange;">
+ <option>one</option>
+ </select>
+ <select oninput='++selectInput;' onchange="++selectChange;">
+ <option>one</option>
+ <option>two</option>
+ </select>
+ <select multiple size='1' oninput='++selectInput;' onchange="++selectChange;">
+ <option>one</option>
+ </select>
+ <select multiple oninput='++selectInput;' onchange="++selectChange;">
+ <option>one</option>
+ <option>two</option>
+ </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+ var selectSingleOneItem = document.getElementsByTagName('select')[0];
+ var selectSingle = document.getElementsByTagName('select')[1];
+ var selectMultipleOneItem = document.getElementsByTagName('select')[2];
+ var selectMultiple = document.getElementsByTagName('select')[3];
+
+ var selectChange = 0;
+ var selectInput = 0;
+ var expectedChange = 0;
+ var expectedInput = 0;
+
+ selectSingleOneItem.focus();
+ synthesizeKey("VK_DOWN", {});
+ is(selectInput, expectedInput, "Down key should not fire input event when reaching end of the list.");
+ is(selectChange, expectedChange, "Down key should not fire change event when reaching end of the list.");
+
+ synthesizeKey("VK_UP", {});
+ is(selectInput, expectedInput, "Up key should not fire input event when reaching top of the list.");
+ is(selectChange, expectedChange, "Up key should not fire change event when reaching top of the list.");
+
+ selectSingle.focus();
+ for (var i = 1; i < selectSingle.length; i++) {
+ synthesizeKey("VK_DOWN", {});
+
+ is(selectSingle.options[i].selected, true, "Option should be selected");
+ is(selectInput, ++expectedInput, "Down key should fire input event.");
+ is(selectChange, ++expectedChange, "Down key should fire change event.");
+ }
+
+ // We are at the end of the list, going down should not fire change event.
+ synthesizeKey("VK_DOWN", {});
+ is(selectInput, expectedInput, "Down key should not fire input event when reaching end of the list.");
+ is(selectChange, expectedChange, "Down key should not fire change event when reaching end of the list.");
+
+ for (var i = selectSingle.length - 2; i >= 0; i--) {
+ synthesizeKey("VK_UP", {});
+
+ is(selectSingle.options[i].selected, true, "Option should be selected");
+ is(selectInput, ++expectedInput, "Up key should fire input event.");
+ is(selectChange, ++expectedChange, "Up key should fire change event.");
+ }
+
+ // We are at the top of the list, going up should not fire change event.
+ synthesizeKey("VK_UP", {});
+ is(selectInput, expectedInput, "Up key should not fire input event when reaching top of the list.");
+ is(selectChange, expectedChange, "Up key should not fire change event when reaching top of the list.");
+
+ selectMultipleOneItem.focus();
+ synthesizeKey("VK_DOWN", {});
+ is(selectInput, ++expectedInput, "Down key should fire input event when reaching end of the list.");
+ is(selectChange, ++expectedChange, "Down key should fire change event when reaching end of the list.");
+
+ synthesizeKey("VK_DOWN", {});
+ is(selectInput, expectedInput, "Down key should not fire input event when reaching end of the list.");
+ is(selectChange, expectedChange, "Down key should not fire change event when reaching end of the list.");
+
+ synthesizeKey("VK_UP", {});
+ is(selectInput, expectedInput, "Up key should not fire input event when reaching top of the list.");
+ is(selectChange, expectedChange, "Up key should not fire change event when reaching top of the list.");
+
+ selectMultiple.focus();
+ for (var i = 0; i < selectMultiple.length; i++) {
+ synthesizeKey("VK_DOWN", {});
+
+ is(selectMultiple.options[i].selected, true, "Option should be selected");
+ is(selectInput, ++expectedInput, "Down key should fire input event.");
+ is(selectChange, ++expectedChange, "Down key should fire change event.");
+ }
+
+ // We are at the end of the list, going down should not fire change event.
+ synthesizeKey("VK_DOWN", {});
+ is(selectInput, expectedInput, "Down key should not fire input event when reaching end of the list.");
+ is(selectChange, expectedChange, "Down key should not fire change event when reaching end of the list.");
+
+ for (var i = selectMultiple.length - 2; i >= 0; i--) {
+ synthesizeKey("VK_UP", {});
+
+ is(selectMultiple.options[i].selected, true, "Option should be selected");
+ is(selectInput, ++expectedInput, "Up key should fire input event.");
+ is(selectChange, ++expectedChange, "Up key should fire change event.");
+ }
+
+ // We are at the top of the list, going up should not fire change event.
+ synthesizeKey("VK_UP", {});
+ is(selectInput, expectedInput, "Up key should not fire input event when reaching top of the list.");
+ is(selectChange, expectedChange, "Up key should not fire change event when reaching top of the list.");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_select_selectedOptions.html b/dom/html/test/forms/test_select_selectedOptions.html
new file mode 100644
index 000000000..e93222459
--- /dev/null
+++ b/dom/html/test/forms/test_select_selectedOptions.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=596681
+-->
+<head>
+ <title>Test for HTMLSelectElement.selectedOptions</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596681">Mozilla Bug 596681</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+
+/** Test for HTMLSelectElement's selectedOptions attribute.
+ *
+ * selectedOptions is a live list of the options that have selectedness of true
+ * (not the selected content attribute).
+ *
+ * See http://www.whatwg.org/html/#dom-select-selectedoptions
+ **/
+
+function checkSelectedOptions(size, elements)
+{
+ is(selectedOptions.length, size,
+ "select should have " + size + " selected options");
+ for (let i = 0; i < size; ++i) {
+ ok(selectedOptions[i], "selected option is valid");
+ if (selectedOptions[i]) {
+ is(selectedOptions[i].value, elements[i].value, "selected options are correct");
+ }
+ }
+}
+
+let select = document.createElement("select");
+document.body.appendChild(select);
+let selectedOptions = select.selectedOptions;
+
+ok("selectedOptions" in select,
+ "select element should have a selectedOptions IDL attribute");
+
+ok(select.selectedOptions instanceof HTMLCollection,
+ "selectedOptions should be an HTMLCollection instance");
+
+let option1 = document.createElement("option");
+let option2 = document.createElement("option");
+let option3 = document.createElement("option");
+option1.id = "option1";
+option1.value = "option1";
+option2.value = "option2";
+option3.value = "option3";
+
+checkSelectedOptions(0, null);
+
+select.add(option1, null);
+is(selectedOptions.namedItem("option1").value, "option1", "named getter works");
+checkSelectedOptions(1, [option1]);
+
+select.add(option2, null);
+checkSelectedOptions(1, [option1]);
+
+select.options[1].selected = true;
+checkSelectedOptions(1, [option2]);
+
+select.multiple = true;
+checkSelectedOptions(1, [option2]);
+
+select.options[0].selected = true;
+checkSelectedOptions(2, [option1, option2]);
+
+option1.selected = false;
+// Usinig selected directly on the option should work.
+checkSelectedOptions(1, [option2]);
+
+select.remove(1);
+select.add(option2, 0);
+select.options[0].selected = true;
+select.options[1].selected = true;
+// Should be in tree order.
+checkSelectedOptions(2, [option2, option1]);
+
+select.add(option3, null);
+checkSelectedOptions(2, [option2, option1]);
+
+select.options[2].selected = true;
+checkSelectedOptions(3, [option2, option1, option3]);
+
+select.length = 0;
+option1.selected = false;
+option2.selected = false;
+option3.selected = false;
+var optgroup1 = document.createElement("optgroup");
+optgroup1.appendChild(option1);
+optgroup1.appendChild(option2);
+select.add(optgroup1)
+var optgroup2 = document.createElement("optgroup");
+optgroup2.appendChild(option3);
+select.add(optgroup2);
+
+checkSelectedOptions(0, null);
+
+option2.selected = true;
+checkSelectedOptions(1, [option2]);
+
+option3.selected = true;
+checkSelectedOptions(2, [option2, option3]);
+
+optgroup1.removeChild(option2);
+checkSelectedOptions(1, [option3]);
+
+document.body.removeChild(select);
+option1.selected = true;
+checkSelectedOptions(2, [option1, option3]);
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_select_validation.html b/dom/html/test/forms/test_select_validation.html
new file mode 100644
index 000000000..1ae134801
--- /dev/null
+++ b/dom/html/test/forms/test_select_validation.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=942321
+-->
+<head>
+ <title>Test for Bug 942321</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=942321">Mozilla Bug 942321</a>
+<p id="display"></p>
+<form id="form" href="">
+ <select required id="testselect">
+ <option id="placeholder" value="" selected>placeholder</option>
+ <option value="test" id="actualvalue">test</option>
+ <select>
+ <input type="submit" />
+</form>
+<script class="testbody" type="text/javascript">
+/** Test for Bug 942321 **/
+var option = document.getElementById("actualvalue");
+option.selected = true;
+is(form.checkValidity(), true, "Select is required and should be valid");
+
+var placeholder = document.getElementById("placeholder");
+placeholder.selected = true;
+is(form.checkValidity(), false, "Select is required and should be invalid");
+
+placeholder.value = "not-invalid-anymore";
+is(form.checkValidity(), true, "Select is required and should be valid when option's value is changed by javascript");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/forms/test_set_range_text.html b/dom/html/test/forms/test_set_range_text.html
new file mode 100644
index 000000000..160c8e58e
--- /dev/null
+++ b/dom/html/test/forms/test_set_range_text.html
@@ -0,0 +1,244 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=850364
+-->
+<head>
+<title>Tests for Bug 850364 && Bug 918940</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=850364">Mozilla Bug 850364</a>
+<p id="display"></p>
+<div id="content">
+
+<!-- "SetRangeText() supported types"-->
+<input type="text" id="input_text"></input>
+<input type="search" id="input_search"></input>
+<input type="url" id="input_url"></input>
+<input type="tel" id="input_tel"></input>
+<input type="password" id="input_password"></input>
+<textarea id="input_textarea"></textarea>
+
+<!-- "SetRangeText() non-supported types" -->
+<input type="button" id="input_button"></input>
+<input type="submit" id="input_submit"></input>
+<input type="image" id="input_image"></input>
+<input type="reset" id="input_reset"></input>
+<input type="radio" id="input_radio"></input>
+<input type="checkbox" id="input_checkbox"></input>
+<input type="range" id="input_range"></input>
+<input type="file" id="input_file"></input>
+<input type="email" id="input_email"></input>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ /** Tests for Bug 850364 && Bug 918940**/
+
+ var SupportedTypes = ["text", "search", "url", "tel", "password", "textarea"];
+ var NonSupportedTypes = ["button", "submit", "image", "reset", "radio",
+ "checkbox", "range", "file", "email"];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function TestInputs() {
+
+ var opThrows, elem, i, msg;
+
+ //Non-supported types should throw
+ for (i = 0; i < NonSupportedTypes.length; ++i) {
+ opThrows = false;
+ msg = "input_" + NonSupportedTypes[i];
+ elem = document.getElementById(msg);
+ elem.focus();
+ try {
+ elem.setRangeText("abc");
+ } catch (ex) {
+ opThrows = true;
+ }
+ ok(opThrows, msg + " should throw InvalidStateError");
+ }
+
+ var numOfSelectCalls = 0, expectedNumOfSelectCalls = 0;
+ //Supported types should not throw
+ for (i = 0; i < SupportedTypes.length; ++i) {
+ opThrows = false;
+ msg = "input_" + SupportedTypes[i];
+ elem = document.getElementById(msg);
+ elem.focus();
+ try {
+ elem.setRangeText("abc");
+ expectedNumOfSelectCalls += 1;
+ } catch (ex) {
+ opThrows = true;
+ }
+ is(opThrows, false, msg + " should not throw InvalidStateError");
+
+ elem.addEventListener("select", function (aEvent) {
+ ok(true, "select event should be fired for " + aEvent.target.id);
+ if (++numOfSelectCalls == expectedNumOfSelectCalls) {
+ SimpleTest.finish();
+ } else if (numOfSelectCalls > expectedNumOfSelectCalls) {
+ ok(false, "Too many select events were fired");
+ }
+ }, false);
+
+ elem.addEventListener("input", function (aEvent) {
+ ok(false, "input event should NOT be fired for " + + aEvent.target.id);
+ }, false);
+
+ var test = " setRange(replacement), shrink";
+ elem.value = "0123456789ABCDEF";
+ elem.setSelectionRange(1, 6);
+ elem.setRangeText("xyz");
+ is(elem.value, "0xyz6789ABCDEF", msg + test);
+ is(elem.selectionStart, 1, msg + test);
+ is(elem.selectionEnd, 4, msg + test);
+ elem.setRangeText("mnk");
+ is(elem.value, "0mnk6789ABCDEF", msg + test);
+ expectedNumOfSelectCalls += 3;
+
+ test = " setRange(replacement), expand";
+ elem.value = "0123456789ABCDEF";
+ elem.setSelectionRange(1, 2);
+ elem.setRangeText("xyz");
+ is(elem.value, "0xyz23456789ABCDEF", msg + test);
+ is(elem.selectionStart, 1, msg + test);
+ is(elem.selectionEnd, 4, msg + test);
+ elem.setRangeText("mnk");
+ is(elem.value, "0mnk23456789ABCDEF", msg + test);
+ expectedNumOfSelectCalls += 3;
+
+ test = " setRange(replacement) pure insertion at start";
+ elem.value = "0123456789ABCDEF";
+ elem.setSelectionRange(0, 0);
+ elem.setRangeText("xyz");
+ is(elem.value, "xyz0123456789ABCDEF", msg + test);
+ is(elem.selectionStart, 0, msg + test);
+ is(elem.selectionEnd, 0, msg + test);
+ elem.setRangeText("mnk");
+ is(elem.value, "mnkxyz0123456789ABCDEF", msg + test);
+ expectedNumOfSelectCalls += 3;
+
+ test = " setRange(replacement) pure insertion in the middle";
+ elem.value = "0123456789ABCDEF";
+ elem.setSelectionRange(4, 4);
+ elem.setRangeText("xyz");
+ is(elem.value, "0123xyz456789ABCDEF", msg + test);
+ is(elem.selectionStart, 4, msg + test);
+ is(elem.selectionEnd, 4, msg + test);
+ elem.setRangeText("mnk");
+ is(elem.value, "0123mnkxyz456789ABCDEF", msg + test);
+ expectedNumOfSelectCalls += 3;
+
+ test = " setRange(replacement) pure insertion at the end";
+ elem.value = "0123456789ABCDEF";
+ elem.setSelectionRange(16, 16);
+ elem.setRangeText("xyz");
+ is(elem.value, "0123456789ABCDEFxyz", msg + test);
+ is(elem.selectionStart, 16, msg + test);
+ is(elem.selectionEnd, 16, msg + test);
+ elem.setRangeText("mnk");
+ is(elem.value, "0123456789ABCDEFmnkxyz", msg + test);
+ expectedNumOfSelectCalls += 3;
+
+ //test SetRange(replacement, start, end, mode) with start > end
+ try {
+ elem.setRangeText("abc", 20, 4);
+ } catch (ex) {
+ opThrows = (ex.name == "IndexSizeError" && ex.code == DOMException.INDEX_SIZE_ERR);
+ }
+ is(opThrows, true, msg + " should throw IndexSizeError");
+
+ //test SelectionMode 'select'
+ elem.value = "0123456789ABCDEF";
+ elem.setRangeText("xyz", 4, 9, "select");
+ is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\"");
+ is(elem.selectionStart, 4, msg + ".selectionStart == 4, with \"select\"");
+ is(elem.selectionEnd, 7, msg + ".selectionEnd == 7, with \"select\"");
+ expectedNumOfSelectCalls += 1;
+
+ elem.setRangeText("pqm", 6, 25, "select");
+ is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\"");
+ is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"select\"");
+ is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"select\"");
+ expectedNumOfSelectCalls += 1;
+
+ //test SelectionMode 'start'
+ elem.value = "0123456789ABCDEF";
+ elem.setRangeText("xyz", 4, 9, "start");
+ is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\"");
+ is(elem.selectionStart, 4, msg + ".selectionStart == 4, with \"start\"");
+ is(elem.selectionEnd, 4, msg + ".selectionEnd == 4, with \"start\"");
+ expectedNumOfSelectCalls += 1;
+
+ elem.setRangeText("pqm", 6, 25, "start");
+ is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\"");
+ is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"start\"");
+ is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"start\"");
+ expectedNumOfSelectCalls += 1;
+
+ //test SelectionMode 'end'
+ elem.value = "0123456789ABCDEF";
+ elem.setRangeText("xyz", 4, 9, "end");
+ is(elem.value, "0123xyz9ABCDEF", msg + ".value == \"0123xyz9ABCDEF\"");
+ is(elem.selectionStart, 7, msg + ".selectionStart == 7, with \"end\"");
+ is(elem.selectionEnd, 7, msg + ".selectionEnd == 7, with \"end\"");
+ expectedNumOfSelectCalls += 1;
+
+ elem.setRangeText("pqm", 6, 25, "end");
+ is(elem.value, "0123xypqm", msg + ".value == \"0123xypqm\"");
+ is(elem.selectionStart, 9, msg + ".selectionStart == 9, with \"end\"");
+ is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"end\"");
+ expectedNumOfSelectCalls += 1;
+
+ //test SelectionMode 'preserve' (default)
+
+ //subcase: selection{Start|End} > end
+ elem.value = "0123456789";
+ elem.setSelectionRange(6, 9);
+ elem.setRangeText("Z", 1, 2, "preserve");
+ is(elem.value, "0Z23456789", msg + ".value == \"0Z23456789\"");
+ is(elem.selectionStart, 6, msg + ".selectionStart == 6, with \"preserve\"");
+ is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"preserve\"");
+ expectedNumOfSelectCalls += 2;
+
+ //subcase: selection{Start|End} < end
+ elem.value = "0123456789";
+ elem.setSelectionRange(4, 5);
+ elem.setRangeText("QRST", 2, 9, "preserve");
+ is(elem.value, "01QRST9", msg + ".value == \"01QRST9\"");
+ is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"preserve\"");
+ is(elem.selectionEnd, 6, msg + ".selectionEnd == 6, with \"preserve\"");
+ expectedNumOfSelectCalls += 2;
+
+ //subcase: selectionStart > end, selectionEnd < end
+ elem.value = "0123456789";
+ elem.setSelectionRange(8, 4);
+ elem.setRangeText("QRST", 1, 5);
+ is(elem.value, "0QRST56789", msg + ".value == \"0QRST56789\"");
+ is(elem.selectionStart, 1, msg + ".selectionStart == 1, with \"default\"");
+ is(elem.selectionEnd, 5, msg + ".selectionEnd == 5, with \"default\"");
+ expectedNumOfSelectCalls += 2;
+
+ //subcase: selectionStart < end, selectionEnd > end
+ elem.value = "0123456789";
+ elem.setSelectionRange(4, 9);
+ elem.setRangeText("QRST", 2, 6);
+ is(elem.value, "01QRST6789", msg + ".value == \"01QRST6789\"");
+ is(elem.selectionStart, 2, msg + ".selectionStart == 2, with \"default\"");
+ is(elem.selectionEnd, 9, msg + ".selectionEnd == 9, with \"default\"");
+ expectedNumOfSelectCalls += 2;
+ }
+ }
+
+ addLoadEvent(TestInputs);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_step_attribute.html b/dom/html/test/forms/test_step_attribute.html
new file mode 100644
index 000000000..31277860c
--- /dev/null
+++ b/dom/html/test/forms/test_step_attribute.html
@@ -0,0 +1,965 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=635553
+-->
+<head>
+ <title>Test for Bug 635553</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 635553 **/
+
+var data = [
+ { type: 'hidden', apply: false },
+ { type: 'text', apply: false },
+ { type: 'search', apply: false },
+ { type: 'tel', apply: false },
+ { type: 'url', apply: false },
+ { type: 'email', apply: false },
+ { type: 'password', apply: false },
+ { type: 'date', apply: true },
+ { type: 'month', apply: true },
+ { type: 'week', apply: true },
+ { type: 'time', apply: true },
+ // TODO: temporary set to false until bug 888331 is fixed.
+ { type: 'datetime-local', apply: false },
+ { type: 'number', apply: true },
+ { type: 'range', apply: true },
+ { type: 'color', apply: false },
+ { type: 'checkbox', apply: false },
+ { type: 'radio', apply: false },
+ { type: 'file', apply: false },
+ { type: 'submit', apply: false },
+ { type: 'image', apply: false },
+ { type: 'reset', apply: false },
+ { type: 'button', apply: false },
+];
+
+function getFreshElement(type) {
+ var elmt = document.createElement('input');
+ elmt.type = type;
+ return elmt;
+}
+
+function checkValidity(aElement, aValidity, aApply, aData)
+{
+ aValidity = aApply ? aValidity : true;
+
+ is(aElement.validity.valid, aValidity,
+ "element validity should be " + aValidity);
+ is(aElement.validity.stepMismatch, !aValidity,
+ "element step mismatch status should be " + !aValidity);
+
+ if (aValidity) {
+ is(aElement.validationMessage, "", "There should be no validation message.");
+ } else {
+ if (aElement.validity.rangeUnderflow) {
+ var underflowMsg =
+ (aElement.type == "date" || aElement.type == "time") ?
+ ("Please select a value that is no earlier than " + aElement.min + ".") :
+ ("Please select a value that is no less than " + aElement.min + ".");
+ is(aElement.validationMessage, underflowMsg,
+ "Checking range underflow validation message.");
+ } else if (aData.low == aData.high) {
+ is(aElement.validationMessage, "Please select a valid value. " +
+ "The nearest valid value is " + aData.low + ".",
+ "There should be a validation message.");
+ } else {
+ is(aElement.validationMessage, "Please select a valid value. " +
+ "The two nearest valid values are " + aData.low + " and " + aData.high + ".",
+ "There should be a validation message.");
+ }
+ }
+
+ is(aElement.matches(":valid"), aElement.willValidate && aValidity,
+ (aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply");
+ is(aElement.matches(":invalid"), aElement.willValidate && !aValidity,
+ (aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply");
+}
+
+for (var test of data) {
+ var input = getFreshElement(test.type);
+ var apply = test.apply;
+
+ if (test.todo) {
+ todo_is(input.type, test.type, test.type + " isn't implemented yet");
+ continue;
+ }
+
+ // The element should be valid, there should be no step mismatch.
+ checkValidity(input, true, apply);
+
+ // Checks to do for all types that support step:
+ // - check for @step=0,
+ // - check for @step behind removed,
+ // - check for @step being 'any' with different case variations.
+ switch (input.type) {
+ case 'text':
+ case 'hidden':
+ case 'search':
+ case 'password':
+ case 'tel':
+ case 'radio':
+ case 'checkbox':
+ case 'reset':
+ case 'button':
+ case 'submit':
+ case 'image':
+ case 'color':
+ input.value = '0';
+ checkValidity(input, true, apply);
+ break;
+ case 'url':
+ input.value = 'http://mozilla.org';
+ checkValidity(input, true, apply);
+ break;
+ case 'email':
+ input.value = 'foo@bar.com';
+ checkValidity(input, true, apply);
+ break;
+ case 'file':
+ var file = new File([''], '635499_file');
+
+ SpecialPowers.wrap(input).mozSetFileArray([file]);
+ checkValidity(input, true, apply);
+
+ break;
+ case 'date':
+ // For date, the step is calulated on the timestamp since 1970-01-01
+ // which mean that for all dates prior to the epoch, this timestamp is < 0
+ // and the behavior might differ, therefore we have to test for these cases.
+
+ // When step is invalid, every date is valid
+ input.step = 0;
+ input.value = '2012-07-05';
+ checkValidity(input, true, apply);
+
+ input.step = 'foo';
+ input.value = '1970-01-01';
+ checkValidity(input, true, apply);
+
+ input.step = '-1';
+ input.value = '1969-12-12';
+ checkValidity(input, true, apply);
+
+ input.removeAttribute('step');
+ input.value = '1500-01-01';
+ checkValidity(input, true, apply);
+
+ input.step = 'any';
+ input.value = '1966-12-12';
+ checkValidity(input, true, apply);
+
+ input.step = 'ANY';
+ input.value = '2013-02-03';
+ checkValidity(input, true, apply);
+
+ // When min is set to a valid date, there is a step base.
+ input.min = '2008-02-28';
+ input.step = '2';
+ input.value = '2008-03-01';
+ checkValidity(input, true, apply);
+
+ input.value = '2008-02-29';
+ checkValidity(input, false, apply, { low: "2008-02-28", high: "2008-03-01" });
+
+ input.min = '2008-02-27';
+ input.value = '2008-02-28';
+ checkValidity(input, false, apply, { low: "2008-02-27", high: "2008-02-29" });
+
+ input.min = '2009-02-27';
+ input.value = '2009-02-28';
+ checkValidity(input, false, apply, { low: "2009-02-27", high: "2009-03-01" });
+
+ input.min = '2009-02-01';
+ input.step = '1.1';
+ input.value = '2009-02-02';
+ checkValidity(input, true, apply);
+
+ // Without any step attribute the date is valid
+ input.removeAttribute('step');
+ checkValidity(input, true, apply);
+
+ input.min = '1950-01-01';
+ input.step = '366';
+ input.value = '1951-01-01';
+ checkValidity(input, false, apply, { low: "1950-01-01", high: "1951-01-02" });
+
+ input.min = '1951-01-01';
+ input.step = '365';
+ input.value = '1952-01-01';
+ checkValidity(input, true, apply);
+
+ input.step = '0.9';
+ input.value = '1951-01-02';
+ is(input.step, '0.9', "check that step value is unchanged");
+ checkValidity(input, true, apply);
+
+ input.step = '0.4';
+ input.value = '1951-01-02';
+ is(input.step, '0.4', "check that step value is unchanged");
+ checkValidity(input, true, apply);
+
+ input.step = '1.5';
+ input.value = '1951-01-02';
+ is(input.step, '1.5', "check that step value is unchanged");
+ checkValidity(input, false, apply, { low: "1951-01-01", high: "1951-01-03" });
+
+ input.value = '1951-01-08';
+ checkValidity(input, false, apply, { low: "1951-01-07", high: "1951-01-09" });
+
+ input.step = '3000';
+ input.min= '1968-01-01';
+ input.value = '1968-05-12';
+ checkValidity(input, false, apply, { low: "1968-01-01", high: "1976-03-19" });
+
+ input.value = '1971-01-01';
+ checkValidity(input, false, apply, { low: "1968-01-01", high: "1976-03-19" });
+
+ input.value = '1991-01-01';
+ checkValidity(input, false, apply, { low: "1984-06-05", high: "1992-08-22" });
+
+ input.value = '1984-06-05';
+ checkValidity(input, true, apply);
+
+ input.value = '1992-08-22';
+ checkValidity(input, true, apply);
+
+ input.step = '2.1';
+ input.min = '1991-01-01';
+ input.value = '1991-01-01';
+ checkValidity(input, true, apply);
+
+ input.value = '1991-01-02';
+ checkValidity(input, false, apply, { low: "1991-01-01", high: "1991-01-03" });
+
+ input.value = '1991-01-03';
+ checkValidity(input, true, apply);
+
+ input.step = '2.1';
+ input.min = '1969-12-20';
+ input.value = '1969-12-20';
+ checkValidity(input, true, apply);
+
+ input.value = '1969-12-21';
+ checkValidity(input, false, apply, { low: "1969-12-20", high: "1969-12-22" });
+
+ input.value = '1969-12-22';
+ checkValidity(input, true, apply);
+
+ break;
+ case 'number':
+ // When step=0, the allowed step is 1.
+ input.step = '0';
+ input.value = '1.2';
+ checkValidity(input, false, apply, { low: 1, high: 2 });
+
+ input.value = '1';
+ checkValidity(input, true, apply);
+
+ input.value = '0';
+ checkValidity(input, true, apply);
+
+ // When step is NaN, the allowed step value is 1.
+ input.step = 'foo';
+ input.value = '1';
+ checkValidity(input, true, apply);
+
+ input.value = '1.5';
+ checkValidity(input, false, apply, { low: 1, high: 2 });
+
+ // When step is negative, the allowed step value is 1.
+ input.step = '-0.1';
+ checkValidity(input, false, apply, { low: 1, high: 2 });
+
+ input.value = '1';
+ checkValidity(input, true, apply);
+
+ // When step is missing, the allowed step value is 1.
+ input.removeAttribute('step');
+ input.value = '1.5';
+ checkValidity(input, false, apply, { low: 1, high: 2 });
+
+ input.value = '1';
+ checkValidity(input, true, apply);
+
+ // When step is 'any', all values are fine wrt to step.
+ input.step = 'any';
+ checkValidity(input, true, apply);
+
+ input.step = 'aNy';
+ input.value = '1337';
+ checkValidity(input, true, apply);
+
+ input.step = 'AnY';
+ input.value = '0.1';
+ checkValidity(input, true, apply);
+
+ input.step = 'ANY';
+ input.value = '-13.37';
+ checkValidity(input, true, apply);
+
+ // When min is set to a valid float, there is a step base.
+ input.min = '1';
+ input.step = '2';
+ input.value = '3';
+ checkValidity(input, true, apply);
+
+ input.value = '2';
+ checkValidity(input, false, apply, { low: 1, high: 3 });
+
+ input.removeAttribute('step'); // step = 1
+ input.min = '0.5';
+ input.value = '5.5';
+ checkValidity(input, true, apply);
+
+ input.value = '1';
+ checkValidity(input, false, apply, { low: 0.5, high: 1.5 });
+
+ input.min = '-0.1';
+ input.step = '1';
+ input.value = '0.9';
+ checkValidity(input, true, apply);
+
+ input.value = '0.1';
+ checkValidity(input, false, apply, { low: -0.1, high: 0.9 });
+
+ // When min is set to NaN, there is no step base (step base=0 actually).
+ input.min = 'foo';
+ input.step = '1';
+ input.value = '1';
+ checkValidity(input, true, apply);
+
+ input.value = '0.5';
+ checkValidity(input, false, apply, { low: 0, high: 1 });
+
+ input.min = '';
+ input.value = '1';
+ checkValidity(input, true, apply);
+
+ input.value = '0.5';
+ checkValidity(input, false, apply, { low: 0, high: 1 });
+
+ input.removeAttribute('min');
+
+ // If value isn't a number, the element isn't invalid.
+ input.value = '';
+ checkValidity(input, true, apply);
+
+ // Regular situations.
+ input.step = '2';
+ input.value = '1.5';
+ checkValidity(input, false, apply, { low: 0, high: 2 });
+
+ input.value = '42.0';
+ checkValidity(input, true, apply);
+
+ input.step = '0.1';
+ input.value = '-0.1';
+ checkValidity(input, true, apply);
+
+ input.step = '2';
+ input.removeAttribute('min');
+ input.max = '10';
+ input.value = '-9';
+ checkValidity(input, false, apply, {low: -10, high: -8});
+
+ // If there is a value defined but no min, the step base is the value.
+ input = getFreshElement(test.type);
+ input.setAttribute('value', '1');
+ input.step = 2;
+ checkValidity(input, true, apply);
+
+ input.value = 3;
+ checkValidity(input, true, apply);
+
+ input.value = 2;
+ checkValidity(input, false, apply, {low: 1, high: 3});
+
+ // Should also work with defaultValue.
+ input = getFreshElement(test.type);
+ input.defaultValue = 1;
+ input.step = 2;
+ checkValidity(input, true, apply);
+
+ input.value = 3;
+ checkValidity(input, true, apply);
+
+ input.value = 2;
+ checkValidity(input, false, apply, {low: 1, high: 3});
+
+ // Rounding issues.
+ input = getFreshElement(test.type);
+ input.min = 0.1;
+ input.step = 0.2;
+ input.value = 0.3;
+ checkValidity(input, true, apply);
+
+ // Check that when the higher value is higher than max, we don't show it.
+ input = getFreshElement(test.type);
+ input.step = '2';
+ input.min = '1';
+ input.max = '10.9';
+ input.value = '10';
+
+ is(input.validationMessage, "Please select a valid value. " +
+ "The nearest valid value is 9.",
+ "The validation message should not include the higher value.");
+ break;
+ case 'range':
+ // Range is special in that it clamps to valid values, so it is much
+ // rarer for it to be invalid.
+
+ // When step=0, the allowed value step is 1.
+ input.step = '0';
+ input.value = '1.2';
+ is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ input.value = '1';
+ is(input.value, '1', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.value = '0';
+ is(input.value, '0', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ // When step is NaN, the allowed step value is 1.
+ input.step = 'foo';
+ input.value = '1';
+ is(input.value, '1', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.value = '1.5';
+ is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ // When step is negative, the allowed step value is 1.
+ input.step = '-0.1';
+ is(input.value, '2', "check that the value still coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.value = '1';
+ is(input.value, '1', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ // When step is missing, the allowed step value is 1.
+ input.removeAttribute('step');
+ input.value = '1.5';
+ is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ input.value = '1';
+ is(input.value, '1', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ // When step is 'any', all values are fine wrt to step.
+ input.step = 'any';
+ checkValidity(input, true, apply);
+
+ input.step = 'aNy';
+ input.value = '97';
+ is(input.value, '97', "check that the value for step=aNy is unchanged");
+ checkValidity(input, true, apply);
+
+ input.step = 'AnY';
+ input.value = '0.1';
+ is(input.value, '0.1', "check that a positive fractional value with step=AnY is unchanged");
+ checkValidity(input, true, apply);
+
+ input.step = 'ANY';
+ input.min = -100;
+ input.value = '-13.37';
+ is(input.value, '-13.37', "check that a negative fractional value with step=ANY is unchanged");
+ checkValidity(input, true, apply);
+
+ // When min is set to a valid float, there is a step base.
+ input.min = '1'; // the step base
+ input.step = '2';
+ input.value = '3';
+ is(input.value, '3', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.value = '2';
+ is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ input.value = '1.99';
+ is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ input.removeAttribute('step'); // step = 1
+ input.min = '0.5'; // step base
+ input.value = '5.5';
+ is(input.value, '5.5', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.value = '1';
+ is(input.value, '1.5', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ input.min = '-0.1'; // step base
+ input.step = '1';
+ input.value = '0.9';
+ is(input.value, '0.9', "the value should be a valid step");
+ checkValidity(input, true, apply);
+
+ input.value = '0.1';
+ is(input.value, '-0.1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ // When min is set to NaN, the step base is the value.
+ input.min = 'foo';
+ input.step = '1';
+ input.value = '1';
+ is(input.value, '1', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.value = '0.5';
+ is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ input.min = '';
+ input.value = '1';
+ is(input.value, '1', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.value = '0.5';
+ is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ input.removeAttribute('min');
+
+ // Test when the value isn't a number
+ input.value = '';
+ is(input.value, '50', "value be should default to the value midway between the minimum (0) and the maximum (100)");
+ checkValidity(input, true, apply);
+
+ // Regular situations.
+ input.step = '2';
+ input.value = '1.5';
+ is(input.value, '2', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ input.value = '42.0';
+ is(input.value, '42.0', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.step = '0.1';
+ input.value = '-0.1';
+ is(input.value, '0', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ input.step = '2';
+ input.removeAttribute('min');
+ input.max = '10';
+ input.value = '-9';
+ is(input.value, '0', "check the value is clamped to the minimum's default of zero");
+ checkValidity(input, true, apply);
+
+ // If @value is defined but not @min, the step base is @value.
+ input = getFreshElement(test.type);
+ input.setAttribute('value', '1');
+ input.step = 2;
+ is(input.value, '1', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ input.value = 3;
+ is(input.value, '3', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.value = 2;
+ is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ // Should also work with defaultValue.
+ input = getFreshElement(test.type);
+ input.defaultValue = 1;
+ input.step = 2;
+ is(input.value, '1', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.value = 3;
+ is(input.value, '3', "check that the value coincides with a step");
+ checkValidity(input, true, apply);
+
+ input.value = 2;
+ is(input.value, '3', "check that the value changes to the nearest valid step, choosing the higher step if both are equally close");
+ checkValidity(input, true, apply);
+
+ // Check contrived error case where there are no valid steps in range:
+ // No @min, so the step base is the default minimum, zero, the valid
+ // range is 0-1, -1 gets clamped to zero.
+ input = getFreshElement(test.type);
+ input.step = '3';
+ input.max = '1';
+ input.defaultValue = '-1';
+ is(input.value, '0', "the value should have been clamped to the default minimum, zero");
+ checkValidity(input, false, apply, {low: -1, high: -1});
+
+ // Check that when the closest of the two steps that the value is between
+ // is greater than the maximum we sanitize to the lower step.
+ input = getFreshElement(test.type);
+ input.step = '2';
+ input.min = '1';
+ input.max = '10.9';
+ input.value = '10.8'; // closest step in 11, but 11 > maximum
+ is(input.value, '9', "check that the value coincides with a step");
+
+ // The way that step base is defined, the converse (the value not being
+ // on a step, and the nearest step being a value that would be underflow)
+ // is not possible, so nothing to test there.
+
+ is(input.validationMessage, "",
+ "The validation message should be empty.");
+ break;
+ case 'time':
+ // Tests invalid step values. That defaults to step = 1 minute (60).
+ var values = [ '0', '-1', 'foo', 'any', 'ANY', 'aNy' ];
+ for (var value of values) {
+ input.step = value;
+ input.value = '19:06:00';
+ checkValidity(input, true, apply);
+ input.value = '19:06:51';
+ if (value.toLowerCase() != 'any') {
+ checkValidity(input, false, apply, {low: '19:06', high: '19:07'});
+ } else {
+ checkValidity(input, true, apply);
+ }
+ }
+
+ // No step means that we use the default step value.
+ input.removeAttribute('step');
+ input.value = '19:06:00';
+ checkValidity(input, true, apply);
+ input.value = '19:06:51';
+ checkValidity(input, false, apply, {low: '19:06', high: '19:07'});
+
+ var tests = [
+ // With step=1, we allow values by the second.
+ { step: '1', value: '19:11:01', min: '00:00', result: true },
+ { step: '1', value: '19:11:01.001', min: '00:00', result: false,
+ low: '19:11:01', high: '19:11:02' },
+ { step: '1', value: '19:11:01.1', min: '00:00', result: false,
+ low: '19:11:01', high: '19:11:02' },
+ // When step >= 86400000, only the minimum value is valid.
+ // This is actually @value if there is no @min.
+ { step: '86400000', value: '00:00', result: true },
+ { step: '86400000', value: '00:01', result: true },
+ { step: '86400000', value: '00:00', min: '00:01', result: false },
+ { step: '86400000', value: '00:01', min: '00:00', result: false,
+ low: '00:00', high: '00:00' },
+ // When step < 1, it should just work.
+ { step: '0.1', value: '15:05:05.1', min: '00:00', result: true },
+ { step: '0.1', value: '15:05:05.101', min: '00:00', result: false,
+ low: '15:05:05.100', high: '15:05:05.200' },
+ { step: '0.2', value: '15:05:05.2', min: '00:00', result: true },
+ { step: '0.2', value: '15:05:05.1', min: '00:00', result: false,
+ low: '15:05:05', high: '15:05:05.200' },
+ { step: '0.01', value: '15:05:05.01', min: '00:00', result: true },
+ { step: '0.01', value: '15:05:05.011', min: '00:00', result: false,
+ low: '15:05:05.010', high: '15:05:05.020' },
+ { step: '0.02', value: '15:05:05.02', min: '00:00', result: true },
+ { step: '0.02', value: '15:05:05.01', min: '00:00', result: false,
+ low: '15:05:05', high: '15:05:05.020' },
+ { step: '0.002', value: '15:05:05.002', min: '00:00', result: true },
+ { step: '0.002', value: '15:05:05.001', min: '00:00', result: false,
+ low: '15:05:05', high: '15:05:05.002' },
+ // When step<=0.001, any value is allowed.
+ { step: '0.001', value: '15:05:05.001', min: '00:00', result: true },
+ { step: '0.001', value: '15:05:05', min: '00:00', result: true },
+ { step: '0.000001', value: '15:05:05', min: '00:00', result: true },
+ // This value has conversion to double issues.
+ { step: '0.0000001', value: '15:05:05', min: '00:00', result: true },
+ // Some random values.
+ { step: '100', value: '15:06:40', min: '00:00', result: true },
+ { step: '100', value: '15:05:05.010', min: '00:00', result: false,
+ low: '15:05', high: '15:06:40' },
+ { step: '3600', value: '15:00', min: '00:00', result: true },
+ { step: '3600', value: '15:14', min: '00:00', result: false,
+ low: '15:00', high: '16:00' },
+ { step: '7200', value: '14:00', min: '00:00', result: true },
+ { step: '7200', value: '15:14', min: '00:00', result: false,
+ low: '14:00', high: '16:00' },
+ { step: '7260', value: '14:07', min: '00:00', result: true },
+ { step: '7260', value: '15:14', min: '00:00', result: false,
+ low: '14:07', high: '16:08' },
+ ];
+
+ var type = test.type;
+ for (var test of tests) {
+ var input = getFreshElement(type);
+ input.step = test.step;
+ input.setAttribute('value', test.value);
+ if (test.min !== undefined) {
+ input.min = test.min;
+ }
+
+ if (test.todo) {
+ todo(input.validity.valid, test.result,
+ "This test should fail for the moment because of precission issues");
+ continue;
+ }
+
+ if (test.result) {
+ checkValidity(input, true, apply);
+ } else {
+ checkValidity(input, false, apply,
+ { low: test.low, high: test.high });
+ }
+ }
+
+ break;
+ case 'month':
+ // When step is invalid, every date is valid
+ input.step = 0;
+ input.value = '2016-07';
+ checkValidity(input, true, apply);
+
+ input.step = 'foo';
+ input.value = '1970-01';
+ checkValidity(input, true, apply);
+
+ input.step = '-1';
+ input.value = '1970-01';
+ checkValidity(input, true, apply);
+
+ input.removeAttribute('step');
+ input.value = '1500-01';
+ checkValidity(input, true, apply);
+
+ input.step = 'any';
+ input.value = '1966-12';
+ checkValidity(input, true, apply);
+
+ input.step = 'ANY';
+ input.value = '2013-02';
+ checkValidity(input, true, apply);
+
+ // When min is set to a valid month, there is a step base.
+ input.min = '2000-01';
+ input.step = '2';
+ input.value = '2000-03';
+ checkValidity(input, true, apply);
+
+ input.value = '2000-02';
+ checkValidity(input, false, apply, { low: "2000-01", high: "2000-03" });
+
+ input.min = '2012-12';
+ input.value = '2013-01';
+ checkValidity(input, false, apply, { low: "2012-12", high: "2013-02" });
+
+ input.min = '2010-10';
+ input.value = '2010-11';
+ checkValidity(input, false, apply, { low: "2010-10", high: "2010-12" });
+
+ input.min = '2010-01';
+ input.step = '1.1';
+ input.value = '2010-02';
+ checkValidity(input, true, apply);
+
+ input.min = '2010-05';
+ input.step = '1.9';
+ input.value = '2010-06';
+ checkValidity(input, false, apply, { low: "2010-05", high: "2010-07" });
+
+ // Without any step attribute the date is valid
+ input.removeAttribute('step');
+ checkValidity(input, true, apply);
+
+ input.min = '1950-01';
+ input.step = '13';
+ input.value = '1951-01';
+ checkValidity(input, false, apply, { low: "1950-01", high: "1951-02" });
+
+ input.min = '1951-01';
+ input.step = '12';
+ input.value = '1952-01';
+ checkValidity(input, true, apply);
+
+ input.step = '0.9';
+ input.value = '1951-02';
+ checkValidity(input, true, apply);
+
+ input.step = '1.5';
+ input.value = '1951-04';
+ checkValidity(input, false, apply, { low: "1951-03", high: "1951-05" });
+
+ input.value = '1951-08';
+ checkValidity(input, false, apply, { low: "1951-07", high: "1951-09" });
+
+ input.step = '300';
+ input.min= '1968-01';
+ input.value = '1968-05';
+ checkValidity(input, false, apply, { low: "1968-01", high: "1993-01" });
+
+ input.value = '1971-01';
+ checkValidity(input, false, apply, { low: "1968-01", high: "1993-01" });
+
+ input.value = '1994-01';
+ checkValidity(input, false, apply, { low: "1993-01", high: "2018-01" });
+
+ input.value = '2018-01';
+ checkValidity(input, true, apply);
+
+ input.value = '2043-01';
+ checkValidity(input, true, apply);
+
+ input.step = '2.1';
+ input.min = '1991-01';
+ input.value = '1991-01';
+ checkValidity(input, true, apply);
+
+ input.value = '1991-02';
+ checkValidity(input, false, apply, { low: "1991-01", high: "1991-03" });
+
+ input.value = '1991-03';
+ checkValidity(input, true, apply);
+
+ input.step = '2.1';
+ input.min = '1969-12';
+ input.value = '1969-12';
+ checkValidity(input, true, apply);
+
+ input.value = '1970-01';
+ checkValidity(input, false, apply, { low: "1969-12", high: "1970-02" });
+
+ input.value = '1970-02';
+ checkValidity(input, true, apply);
+
+ break;
+ case 'week':
+ // When step is invalid, every week is valid
+ input.step = 0;
+ input.value = '2016-W30';
+ checkValidity(input, true, apply);
+
+ input.step = 'foo';
+ input.value = '1970-W01';
+ checkValidity(input, true, apply);
+
+ input.step = '-1';
+ input.value = '1970-W01';
+ checkValidity(input, true, apply);
+
+ input.removeAttribute('step');
+ input.value = '1500-W01';
+ checkValidity(input, true, apply);
+
+ input.step = 'any';
+ input.value = '1966-W52';
+ checkValidity(input, true, apply);
+
+ input.step = 'ANY';
+ input.value = '2013-W10';
+ checkValidity(input, true, apply);
+
+ // When min is set to a valid week, there is a step base.
+ input.min = '2000-W01';
+ input.step = '2';
+ input.value = '2000-W03';
+ checkValidity(input, true, apply);
+
+ input.value = '2000-W02';
+ checkValidity(input, false, apply, { low: "2000-W01", high: "2000-W03" });
+
+ input.min = '2012-W52';
+ input.value = '2013-W01';
+ checkValidity(input, false, apply, { low: "2012-W52", high: "2013-W02" });
+
+ input.min = '2010-W01';
+ input.step = '1.1';
+ input.value = '2010-W02';
+ checkValidity(input, true, apply);
+
+ input.min = '2010-W05';
+ input.step = '1.9';
+ input.value = '2010-W06';
+ checkValidity(input, false, apply, { low: "2010-W05", high: "2010-W07" });
+
+ // Without any step attribute the week is valid
+ input.removeAttribute('step');
+ checkValidity(input, true, apply);
+
+ input.min = '1950-W01';
+ input.step = '53';
+ input.value = '1951-W01';
+ checkValidity(input, false, apply, { low: "1950-W01", high: "1951-W02" });
+
+ input.min = '1951-W01';
+ input.step = '52';
+ input.value = '1952-W01';
+ checkValidity(input, true, apply);
+
+ input.step = '0.9';
+ input.value = '1951-W02';
+ checkValidity(input, true, apply);
+
+ input.step = '1.5';
+ input.value = '1951-W04';
+ checkValidity(input, false, apply, { low: "1951-W03", high: "1951-W05" });
+
+ input.value = '1951-W20';
+ checkValidity(input, false, apply, { low: "1951-W19", high: "1951-W21" });
+
+ input.step = '300';
+ input.min= '1968-W01';
+ input.value = '1968-W05';
+ checkValidity(input, false, apply, { low: "1968-W01", high: "1973-W40" });
+
+ input.value = '1971-W01';
+ checkValidity(input, false, apply, { low: "1968-W01", high: "1973-W40" });
+
+ input.value = '1975-W01';
+ checkValidity(input, false, apply, { low: "1973-W40", high: "1979-W27" });
+
+ input.value = '1985-W14';
+ checkValidity(input, true, apply);
+
+ input.step = '2.1';
+ input.min = '1991-W01';
+ input.value = '1991-W01';
+ checkValidity(input, true, apply);
+
+ input.value = '1991-W02';
+ checkValidity(input, false, apply, { low: "1991-W01", high: "1991-W03" });
+
+ input.value = '1991-W03';
+ checkValidity(input, true, apply);
+
+ input.step = '2.1';
+ input.min = '1969-W52';
+ input.value = '1969-W52';
+ checkValidity(input, true, apply);
+
+ input.value = '1970-W01';
+ checkValidity(input, false, apply, { low: "1969-W52", high: "1970-W02" });
+
+ input.value = '1970-W02';
+ checkValidity(input, true, apply);
+
+ break;
+ case 'datetime-local':
+ // TODO: this is temporary until bug 888331 is fixed.
+
+ break;
+ default:
+ ok(false, "Implement the tests for <input type='" + test.type + " >");
+ break;
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_stepup_stepdown.html b/dom/html/test/forms/test_stepup_stepdown.html
new file mode 100644
index 000000000..d96895180
--- /dev/null
+++ b/dom/html/test/forms/test_stepup_stepdown.html
@@ -0,0 +1,1018 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=636627
+-->
+<head>
+ <title>Test for Bug 636627</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=636627">Mozilla Bug 636627</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 636627 **/
+
+/**
+ * This test is testing stepDown() and stepUp().
+ */
+
+function checkPresence()
+{
+ var input = document.createElement('input');
+ is('stepDown' in input, true, 'stepDown() should be an input function');
+ is('stepUp' in input, true, 'stepUp() should be an input function');
+}
+
+function checkAvailability()
+{
+ var testData =
+ [
+ ["text", false],
+ ["password", false],
+ ["search", false],
+ ["telephone", false],
+ ["email", false],
+ ["url", false],
+ ["hidden", false],
+ ["checkbox", false],
+ ["radio", false],
+ ["file", false],
+ ["submit", false],
+ ["image", false],
+ ["reset", false],
+ ["button", false],
+ ["number", true],
+ ["range", true],
+ ["date", true],
+ ["time", true],
+ ["month", true],
+ ["week", true],
+ ["color", false],
+ ];
+
+ var todoList =
+ [
+ ["datetime", true],
+ ["datetime-local", true],
+ ];
+
+ var element = document.createElement("input");
+ element.setAttribute('value', '0');
+
+ for (data of testData) {
+ var exceptionCaught = false;
+ element.type = data[0];
+ try {
+ element.stepDown();
+ } catch (e) {
+ exceptionCaught = true;
+ }
+ is(exceptionCaught, !data[1], "stepDown() availability is not correct");
+
+ exceptionCaught = false;
+ try {
+ element.stepUp();
+ } catch (e) {
+ exceptionCaught = true;
+ }
+ is(exceptionCaught, !data[1], "stepUp() availability is not correct");
+ }
+
+ for (data of todoList) {
+ var exceptionCaught = false;
+ element.type = data[0];
+ try {
+ element.stepDown();
+ } catch (e) {
+ exceptionCaught = true;
+ }
+ todo_is(exceptionCaught, !data[1],
+ "stepDown() availability is not correct");
+
+ exceptionCaught = false;
+ try {
+ element.stepUp();
+ } catch (e) {
+ exceptionCaught = true;
+ }
+ todo_is(exceptionCaught, !data[1],
+ "stepUp() availability is not correct");
+ }
+}
+
+function checkStepDown()
+{
+ // This testData is very similar to the one in checkStepUp with some changes
+ // relative to stepDown.
+ var testData = [
+ /* Initial value | step | min | max | stepDown arg | final value | exception */
+ { type: 'number', data: [
+ // Regular case.
+ [ '1', null, null, null, null, '0', false ],
+ // Argument testing.
+ [ '1', null, null, null, 1, '0', false ],
+ [ '9', null, null, null, 9, '0', false ],
+ [ '1', null, null, null, -1, '2', false ],
+ [ '1', null, null, null, 0, '1', false ],
+ // Float values are rounded to integer (1.1 -> 1).
+ [ '1', null, null, null, 1.1, '0', false ],
+ // With step values.
+ [ '1', '0.5', null, null, null, '0.5', false ],
+ [ '1', '0.25', null, null, 4, '0', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '1', '0', null, null, null, '0', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '1', '-1', null, null, null, '0', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '1', 'foo', null, null, null, '0', false ],
+ // Min values testing.
+ [ '1', '1', 'foo', null, null, '0', false ],
+ [ '1', null, '-10', null, null, '0', false ],
+ [ '1', null, '0', null, null, '0', false ],
+ [ '1', null, '10', null, null, '1', false ],
+ [ '1', null, '2', null, null, '1', false ],
+ [ '1', null, '1', null, null, '1', false ],
+ // Max values testing.
+ [ '1', '1', null, 'foo', null, '0', false ],
+ [ '1', null, null, '10', null, '0', false ],
+ [ '1', null, null, '0', null, '0', false ],
+ [ '1', null, null, '-10', null, '-10', false ],
+ [ '1', null, null, '1', null, '0', false ],
+ [ '5', null, null, '3', '3', '2', false ],
+ [ '5', '2', '-6', '3', '2', '2', false ],
+ [ '-3', '5', '-10', '-3', null, '-5', false ],
+ // Step mismatch.
+ [ '1', '2', '-2', null, null, '0', false ],
+ [ '3', '2', '-2', null, null, '2', false ],
+ [ '3', '2', '-2', null, '2', '0', false ],
+ [ '3', '2', '-2', null, '-2', '6', false ],
+ [ '1', '2', '-6', null, null, '0', false ],
+ [ '1', '2', '-2', null, null, '0', false ],
+ [ '1', '3', '-6', null, null, '0', false ],
+ [ '2', '3', '-6', null, null, '0', false ],
+ [ '2', '3', '1', null, null, '1', false ],
+ [ '5', '3', '1', null, null, '4', false ],
+ [ '3', '2', '-6', null, null, '2', false ],
+ [ '5', '2', '-6', null, null, '4', false ],
+ [ '6', '2', '1', null, null, '5', false ],
+ [ '8', '3', '1', null, null, '7', false ],
+ [ '9', '2', '-10', null, null, '8', false ],
+ [ '7', '3', '-10', null, null, '5', false ],
+ [ '-2', '3', '-10', null, null, '-4', false ],
+ // Clamping.
+ [ '0', '2', '-1', null, null, '-1', false ],
+ [ '10', '2', '0', '4', '10', '0', false ],
+ [ '10', '2', '0', '4', '5', '0', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '-1', false ],
+ [ '', '2', null, null, null, '-2', false ],
+ [ '', '2', '3', null, null, '3', false ],
+ [ '', null, '3', null, null, '3', false ],
+ [ '', '2', '3', '8', null, '3', false ],
+ [ '', null, '-10', '10', null, '-1', false ],
+ [ '', '3', '-10', '10', null, '-1', false ],
+ // With step = 'any'.
+ [ '0', 'any', null, null, 1, null, true ],
+ [ '0', 'ANY', null, null, 1, null, true ],
+ [ '0', 'AnY', null, null, 1, null, true ],
+ [ '0', 'aNy', null, null, 1, null, true ],
+ // With @value = step base.
+ [ '1', '2', null, null, null, '-1', false ],
+ ]},
+ { type: 'range', data: [
+ // Regular case.
+ [ '1', null, null, null, null, '0', false ],
+ // Argument testing.
+ [ '1', null, null, null, 1, '0', false ],
+ [ '9', null, null, null, 9, '0', false ],
+ [ '1', null, null, null, -1, '2', false ],
+ [ '1', null, null, null, 0, '1', false ],
+ // Float values are rounded to integer (1.1 -> 1).
+ [ '1', null, null, null, 1.1, '0', false ],
+ // With step values.
+ [ '1', '0.5', null, null, null, '0.5', false ],
+ [ '1', '0.25', null, null, 4, '0', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '1', '0', null, null, null, '0', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '1', '-1', null, null, null, '0', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '1', 'foo', null, null, null, '0', false ],
+ // Min values testing.
+ [ '1', '1', 'foo', null, null, '0', false ],
+ [ '1', null, '-10', null, null, '0', false ],
+ [ '1', null, '0', null, null, '0', false ],
+ [ '1', null, '10', null, null, '10', false ],
+ [ '1', null, '2', null, null, '2', false ],
+ [ '1', null, '1', null, null, '1', false ],
+ // Max values testing.
+ [ '1', '1', null, 'foo', null, '0', false ],
+ [ '1', null, null, '10', null, '0', false ],
+ [ '1', null, null, '0', null, '0', false ],
+ [ '1', null, null, '-10', null, '0', false ],
+ [ '1', null, null, '1', null, '0', false ],
+ [ '5', null, null, '3', '3', '0', false ],
+ [ '5', '2', '-6', '3', '2', '-2', false ],
+ [ '-3', '5', '-10', '-3', null, '-10', false ],
+ // Step mismatch.
+ [ '1', '2', '-2', null, null, '0', false ],
+ [ '3', '2', '-2', null, null, '2', false ],
+ [ '3', '2', '-2', null, '2', '0', false ],
+ [ '3', '2', '-2', null, '-2', '8', false ],
+ [ '1', '2', '-6', null, null, '0', false ],
+ [ '1', '2', '-2', null, null, '0', false ],
+ [ '1', '3', '-6', null, null, '-3', false ],
+ [ '2', '3', '-6', null, null, '0', false ],
+ [ '2', '3', '1', null, null, '1', false ],
+ [ '5', '3', '1', null, null, '1', false ],
+ [ '3', '2', '-6', null, null, '2', false ],
+ [ '5', '2', '-6', null, null, '4', false ],
+ [ '6', '2', '1', null, null, '5', false ],
+ [ '8', '3', '1', null, null, '4', false ],
+ [ '9', '2', '-10', null, null, '8', false ],
+ [ '7', '3', '-10', null, null, '5', false ],
+ [ '-2', '3', '-10', null, null, '-4', false ],
+ // Clamping.
+ [ '0', '2', '-1', null, null, '-1', false ],
+ [ '10', '2', '0', '4', '10', '0', false ],
+ [ '10', '2', '0', '4', '5', '0', false ],
+ // value = "" (default will be 50).
+ [ '', null, null, null, null, '49', false ],
+ // With step = 'any'.
+ [ '0', 'any', null, null, 1, null, true ],
+ [ '0', 'ANY', null, null, 1, null, true ],
+ [ '0', 'AnY', null, null, 1, null, true ],
+ [ '0', 'aNy', null, null, 1, null, true ],
+ // With @value = step base.
+ [ '1', '2', null, null, null, '1', false ],
+ ]},
+ { type: 'date', data: [
+ // Regular case.
+ [ '2012-07-09', null, null, null, null, '2012-07-08', false ],
+ // Argument testing.
+ [ '2012-07-09', null, null, null, 1, '2012-07-08', false ],
+ [ '2012-07-09', null, null, null, 5, '2012-07-04', false ],
+ [ '2012-07-09', null, null, null, -1, '2012-07-10', false ],
+ [ '2012-07-09', null, null, null, 0, '2012-07-09', false ],
+ // Month/Year wrapping.
+ [ '2012-08-01', null, null, null, 1, '2012-07-31', false ],
+ [ '1969-01-02', null, null, null, 4, '1968-12-29', false ],
+ [ '1969-01-01', null, null, null, -365, '1970-01-01', false ],
+ [ '2012-02-29', null, null, null, -1, '2012-03-01', false ],
+ // Float values are rounded to integer (1.1 -> 1).
+ [ '2012-01-02', null, null, null, 1.1, '2012-01-01', false ],
+ [ '2012-01-02', null, null, null, 1.9, '2012-01-01', false ],
+ // With step values.
+ [ '2012-01-03', '0.5', null, null, null, '2012-01-02', false ],
+ [ '2012-01-02', '0.5', null, null, null, '2012-01-01', false ],
+ [ '2012-01-01', '2', null, null, null, '2011-12-30', false ],
+ [ '2012-01-02', '0.25',null, null, 4, '2011-12-29', false ],
+ [ '2012-01-15', '1.1', '2012-01-01', null, 1, '2012-01-14', false ],
+ [ '2012-01-12', '1.1', '2012-01-01', null, 2, '2012-01-10', false ],
+ [ '2012-01-23', '1.1', '2012-01-01', null, 10, '2012-01-13', false ],
+ [ '2012-01-23', '1.1', '2012-01-01', null, 11, '2012-01-12', false ],
+ [ '1968-01-12', '1.1', '1968-01-01', null, 8, '1968-01-04', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '2012-01-02', '0', null, null, null, '2012-01-01', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '2012-01-02', '-1', null, null, null, '2012-01-01', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '2012-01-02', 'foo', null, null, null, '2012-01-01', false ],
+ // Min values testing.
+ [ '2012-01-03', '1', 'foo', null, 2, '2012-01-01', false ],
+ [ '2012-01-02', '1', '2012-01-01', null, null, '2012-01-01', false ],
+ [ '2012-01-01', '1', '2012-01-01', null, null, '2012-01-01', false ],
+ [ '2012-01-01', '1', '2012-01-10', null, 1, '2012-01-01', false ],
+ [ '2012-01-05', '3', '2012-01-01', null, null, '2012-01-04', false ],
+ [ '1969-01-01', '5', '1969-01-01', '1969-01-02', null, '1969-01-01', false ],
+ // Max values testing.
+ [ '2012-01-02', '1', null, 'foo', null, '2012-01-01', false ],
+ [ '2012-01-02', null, null, '2012-01-05', null, '2012-01-01', false ],
+ [ '2012-01-03', null, null, '2012-01-03', null, '2012-01-02', false ],
+ [ '2012-01-07', null, null, '2012-01-04', 4, '2012-01-03', false ],
+ [ '2012-01-07', '2', null, '2012-01-04', 3, '2012-01-01', false ],
+ // Step mismatch.
+ [ '2012-01-04', '2', '2012-01-01', null, null, '2012-01-03', false ],
+ [ '2012-01-06', '2', '2012-01-01', null, 2, '2012-01-03', false ],
+ [ '2012-01-05', '2', '2012-01-04', '2012-01-08', null, '2012-01-04', false ],
+ [ '1970-01-04', '2', null, null, null, '1970-01-02', false ],
+ [ '1970-01-09', '3', null, null, null, '1970-01-06', false ],
+ // Clamping.
+ [ '2012-05-01', null, null, '2012-01-05', null, '2012-01-05', false ],
+ [ '1970-01-05', '2', '1970-01-02', '1970-01-05', null, '1970-01-04', false ],
+ [ '1970-01-01', '5', '1970-01-02', '1970-01-09', 10, '1970-01-01', false ],
+ [ '1970-01-07', '5', '1969-12-27', '1970-01-06', 2, '1970-01-01', false ],
+ [ '1970-03-08', '3', '1970-02-01', '1970-02-07', 15, '1970-02-01', false ],
+ [ '1970-01-10', '3', '1970-01-01', '1970-01-06', 2, '1970-01-04', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '1969-12-31', false ],
+ // With step = 'any'.
+ [ '2012-01-01', 'any', null, null, 1, null, true ],
+ [ '2012-01-01', 'ANY', null, null, 1, null, true ],
+ [ '2012-01-01', 'AnY', null, null, 1, null, true ],
+ [ '2012-01-01', 'aNy', null, null, 1, null, true ],
+ ]},
+ { type: 'time', data: [
+ // Regular case.
+ [ '16:39', null, null, null, null, '16:38', false ],
+ // Argument testing.
+ [ '16:40', null, null, null, 1, '16:39', false ],
+ [ '16:40', null, null, null, 5, '16:35', false ],
+ [ '16:40', null, null, null, -1, '16:41', false ],
+ [ '16:40', null, null, null, 0, '16:40', false ],
+ // hour/minutes/seconds wrapping.
+ [ '05:00', null, null, null, null, '04:59', false ],
+ [ '05:00:00', 1, null, null, null, '04:59:59', false ],
+ [ '05:00:00', 0.1, null, null, null, '04:59:59.900', false ],
+ [ '05:00:00', 0.01, null, null, null, '04:59:59.990', false ],
+ [ '05:00:00', 0.001, null, null, null, '04:59:59.999', false ],
+ // stepDown() on '00:00' gives '23:59'.
+ [ '00:00', null, null, null, 1, '23:59', false ],
+ [ '00:00', null, null, null, 3, '23:57', false ],
+ // Some random step values..
+ [ '16:56', '0.5', null, null, null, '16:55:59.500', false ],
+ [ '16:56', '2', null, null, null, '16:55:58', false ],
+ [ '16:56', '0.25',null, null, 4, '16:55:59', false ],
+ [ '16:57', '1.1', '16:00', null, 1, '16:56:59.900', false ],
+ [ '16:57', '1.1', '16:00', null, 2, '16:56:58.800', false ],
+ [ '16:57', '1.1', '16:00', null, 10, '16:56:50', false ],
+ [ '16:57', '1.1', '16:00', null, 11, '16:56:48.900', false ],
+ [ '16:57', '1.1', '16:00', null, 8, '16:56:52.200', false ],
+ // Invalid @step, means that we use the default value.
+ [ '17:01', '0', null, null, null, '17:00', false ],
+ [ '17:01', '-1', null, null, null, '17:00', false ],
+ [ '17:01', 'foo', null, null, null, '17:00', false ],
+ // Min values testing.
+ [ '17:02', '60', 'foo', null, 2, '17:00', false ],
+ [ '17:10', '60', '17:09', null, null, '17:09', false ],
+ [ '17:10', '60', '17:10', null, null, '17:10', false ],
+ [ '17:10', '60', '17:30', null, 1, '17:10', false ],
+ [ '17:10', '180', '17:05', null, null, '17:08', false ],
+ [ '17:10', '300', '17:10', '17:11', null, '17:10', false ],
+ // Max values testing.
+ [ '17:15', '60', null, 'foo', null, '17:14', false ],
+ [ '17:15', null, null, '17:20', null, '17:14', false ],
+ [ '17:15', null, null, '17:15', null, '17:14', false ],
+ [ '17:15', null, null, '17:13', 4, '17:11', false ],
+ [ '17:15', '120', null, '17:13', 3, '17:09', false ],
+ // Step mismatch.
+ [ '17:19', '120', '17:10', null, null, '17:18', false ],
+ [ '17:19', '120', '17:10', null, 2, '17:16', false ],
+ [ '17:19', '120', '17:18', '17:25', null, '17:18', false ],
+ [ '17:19', '120', null, null, null, '17:17', false ],
+ [ '17:19', '180', null, null, null, '17:16', false ],
+ // Clamping.
+ [ '17:22', null, null, '17:11', null, '17:11', false ],
+ [ '17:22', '120', '17:20', '17:22', null, '17:20', false ],
+ [ '17:22', '300', '17:12', '17:20', 10, '17:12', false ],
+ [ '17:22', '300', '17:18', '17:20', 2, '17:18', false ],
+ [ '17:22', '180', '17:00', '17:20', 15, '17:00', false ],
+ [ '17:22', '180', '17:10', '17:20', 2, '17:16', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '23:59', false ],
+ // With step = 'any'.
+ [ '17:26', 'any', null, null, 1, null, true ],
+ [ '17:26', 'ANY', null, null, 1, null, true ],
+ [ '17:26', 'AnY', null, null, 1, null, true ],
+ [ '17:26', 'aNy', null, null, 1, null, true ],
+ ]},
+ { type: 'month', data: [
+ // Regular case.
+ [ '2016-08', null, null, null, null, '2016-07', false ],
+ // Argument testing.
+ [ '2016-08', null, null, null, 1, '2016-07', false ],
+ [ '2016-08', null, null, null, 5, '2016-03', false ],
+ [ '2016-08', null, null, null, -1, '2016-09', false ],
+ [ '2016-08', null, null, null, 0, '2016-08', false ],
+ // Month/Year wrapping.
+ [ '2016-01', null, null, null, 1, '2015-12', false ],
+ [ '1969-02', null, null, null, 4, '1968-10', false ],
+ [ '1969-01', null, null, null, -12, '1970-01', false ],
+ // Float values are rounded to integer (1.1 -> 1).
+ [ '2016-08', null, null, null, 1.1, '2016-07', false ],
+ [ '2016-01', null, null, null, 1.9, '2015-12', false ],
+ // With step values.
+ [ '2016-03', '0.5', null, null, null, '2016-02', false ],
+ [ '2016-03', '2', null, null, null, '2016-01', false ],
+ [ '2016-03', '0.25',null, null, 4, '2015-11', false ],
+ [ '2016-12', '1.1', '2016-01', null, 1, '2016-11', false ],
+ [ '2016-12', '1.1', '2016-01', null, 2, '2016-10', false ],
+ [ '2016-12', '1.1', '2016-01', null, 10, '2016-02', false ],
+ [ '2016-12', '1.1', '2016-01', null, 12, '2016-01', false ],
+ [ '1968-12', '1.1', '1968-01', null, 8, '1968-04', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '2016-02', '0', null, null, null, '2016-01', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '2016-02', '-1', null, null, null, '2016-01', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '2016-02', 'foo', null, null, null, '2016-01', false ],
+ // Min values testing.
+ [ '2016-03', '1', 'foo', null, 2, '2016-01', false ],
+ [ '2016-02', '1', '2016-01', null, null, '2016-01', false ],
+ [ '2016-01', '1', '2016-01', null, null, '2016-01', false ],
+ [ '2016-01', '1', '2016-01', null, 1, '2016-01', false ],
+ [ '2016-05', '3', '2016-01', null, null, '2016-04', false ],
+ [ '1969-01', '5', '1969-01', '1969-02', null, '1969-01', false ],
+ // Max values testing.
+ [ '2016-02', '1', null, 'foo', null, '2016-01', false ],
+ [ '2016-02', null, null, '2016-05', null, '2016-01', false ],
+ [ '2016-03', null, null, '2016-03', null, '2016-02', false ],
+ [ '2016-07', null, null, '2016-04', 4, '2016-03', false ],
+ [ '2016-07', '2', null, '2016-04', 3, '2016-01', false ],
+ // Step mismatch.
+ [ '2016-04', '2', '2016-01', null, null, '2016-03', false ],
+ [ '2016-06', '2', '2016-01', null, 2, '2016-03', false ],
+ [ '2016-05', '2', '2016-04', '2016-08', null, '2016-04', false ],
+ [ '1970-04', '2', null, null, null, '1970-02', false ],
+ [ '1970-09', '3', null, null, null, '1970-06', false ],
+ // Clamping.
+ [ '2016-05', null, null, '2016-01', null, '2016-01', false ],
+ [ '1970-05', '2', '1970-02', '1970-05', null, '1970-04', false ],
+ [ '1970-01', '5', '1970-02', '1970-09', 10, '1970-01', false ],
+ [ '1970-07', '5', '1969-12', '1970-10', 2, '1969-12', false ],
+ [ '1970-08', '3', '1970-01', '1970-07', 15, '1970-01', false ],
+ [ '1970-10', '3', '1970-01', '1970-06', 2, '1970-04', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '1969-12', false ],
+ // With step = 'any'.
+ [ '2016-01', 'any', null, null, 1, null, true ],
+ [ '2016-01', 'ANY', null, null, 1, null, true ],
+ [ '2016-01', 'AnY', null, null, 1, null, true ],
+ [ '2016-01', 'aNy', null, null, 1, null, true ],
+ ]},
+ { type: 'week', data: [
+ // Regular case.
+ [ '2016-W40', null, null, null, null, '2016-W39', false ],
+ // Argument testing.
+ [ '2016-W40', null, null, null, 1, '2016-W39', false ],
+ [ '2016-W40', null, null, null, 5, '2016-W35', false ],
+ [ '2016-W40', null, null, null, -1, '2016-W41', false ],
+ [ '2016-W40', null, null, null, 0, '2016-W40', false ],
+ // Week/Year wrapping.
+ [ '2016-W01', null, null, null, 1, '2015-W53', false ],
+ [ '1969-W02', null, null, null, 4, '1968-W50', false ],
+ [ '1969-W01', null, null, null, -52, '1970-W01', false ],
+ // Float values are rounded to integer (1.1 -> 1).
+ [ '2016-W40', null, null, null, 1.1, '2016-W39', false ],
+ [ '2016-W01', null, null, null, 1.9, '2015-W53', false ],
+ // With step values.
+ [ '2016-W03', '0.5', null, null, null, '2016-W02', false ],
+ [ '2016-W03', '2', null, null, null, '2016-W01', false ],
+ [ '2016-W03', '0.25', null, null, 4, '2015-W52', false ],
+ [ '2016-W52', '1.1', '2016-W01', null, 1, '2016-W51', false ],
+ [ '2016-W52', '1.1', '2016-W01', null, 2, '2016-W50', false ],
+ [ '2016-W52', '1.1', '2016-W01', null, 10, '2016-W42', false ],
+ [ '2016-W52', '1.1', '2016-W01', null, 52, '2016-W01', false ],
+ [ '1968-W52', '1.1', '1968-W01', null, 8, '1968-W44', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '2016-W02', '0', null, null, null, '2016-W01', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '2016-W02', '-1', null, null, null, '2016-W01', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '2016-W02', 'foo', null, null, null, '2016-W01', false ],
+ // Min values testing.
+ [ '2016-W03', '1', 'foo', null, 2, '2016-W01', false ],
+ [ '2016-W02', '1', '2016-01', null, null, '2016-W01', false ],
+ [ '2016-W01', '1', '2016-W01', null, null, '2016-W01', false ],
+ [ '2016-W01', '1', '2016-W01', null, 1, '2016-W01', false ],
+ [ '2016-W05', '3', '2016-W01', null, null, '2016-W04', false ],
+ [ '1969-W01', '5', '1969-W01', '1969-W02', null, '1969-W01', false ],
+ // Max values testing.
+ [ '2016-W02', '1', null, 'foo', null, '2016-W01', false ],
+ [ '2016-W02', null, null, '2016-W05', null, '2016-W01', false ],
+ [ '2016-W03', null, null, '2016-W03', null, '2016-W02', false ],
+ [ '2016-W07', null, null, '2016-W04', 4, '2016-W03', false ],
+ [ '2016-W07', '2', null, '2016-W04', 3, '2016-W01', false ],
+ // Step mismatch.
+ [ '2016-W04', '2', '2016-W01', null, null, '2016-W03', false ],
+ [ '2016-W06', '2', '2016-W01', null, 2, '2016-W03', false ],
+ [ '2016-W05', '2', '2016-W04', '2016-W08', null, '2016-W04', false ],
+ [ '1970-W04', '2', null, null, null, '1970-W02', false ],
+ [ '1970-W09', '3', null, null, null, '1970-W06', false ],
+ // Clamping.
+ [ '2016-W05', null, null, '2016-W01', null, '2016-W01', false ],
+ [ '1970-W05', '2', '1970-W02', '1970-W05', null, '1970-W04', false ],
+ [ '1970-W01', '5', '1970-W02', '1970-W09', 10, '1970-W01', false ],
+ [ '1970-W07', '5', '1969-W52', '1970-W10', 2, '1969-W52', false ],
+ [ '1970-W08', '3', '1970-W01', '1970-W07', 15, '1970-W01', false ],
+ [ '1970-W10', '3', '1970-W01', '1970-W06', 2, '1970-W04', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '1970-W01', false ],
+ // With step = 'any'.
+ [ '2016-W01', 'any', null, null, 1, null, true ],
+ [ '2016-W01', 'ANY', null, null, 1, null, true ],
+ [ '2016-W01', 'AnY', null, null, 1, null, true ],
+ [ '2016-W01', 'aNy', null, null, 1, null, true ],
+ ]},
+ ];
+
+ for (var test of testData) {
+ for (var data of test.data) {
+ var element = document.createElement("input");
+ element.type = test.type;
+
+ if (data[1] != null) {
+ element.step = data[1];
+ }
+
+ if (data[2] != null) {
+ element.min = data[2];
+ }
+
+ if (data[3] != null) {
+ element.max = data[3];
+ }
+
+ // Set 'value' last for type=range, because the final sanitized value
+ // after setting 'step', 'min' and 'max' can be affected by the order in
+ // which those attributes are set. Setting 'value' last makes it simpler
+ // to reason about what the final value should be.
+ if (data[0] != null) {
+ element.setAttribute('value', data[0]);
+ }
+
+ var exceptionCaught = false;
+ try {
+ if (data[4] != null) {
+ element.stepDown(data[4]);
+ } else {
+ element.stepDown();
+ }
+
+ is(element.value, data[5], "The value for type=" + test.type + " should be " + data[5]);
+ } catch (e) {
+ exceptionCaught = true;
+ is(element.value, data[0], e.name + "The value should not have changed");
+ is(e.name, 'InvalidStateError',
+ "It should be a InvalidStateError exception.");
+ } finally {
+ is(exceptionCaught, data[6], "exception status should be " + data[6]);
+ }
+ }
+ }
+}
+
+function checkStepUp()
+{
+ // This testData is very similar to the one in checkStepDown with some changes
+ // relative to stepUp.
+ var testData = [
+ /* Initial value | step | min | max | stepUp arg | final value | exception */
+ { type: 'number', data: [
+ // Regular case.
+ [ '1', null, null, null, null, '2', false ],
+ // Argument testing.
+ [ '1', null, null, null, 1, '2', false ],
+ [ '9', null, null, null, 9, '18', false ],
+ [ '1', null, null, null, -1, '0', false ],
+ [ '1', null, null, null, 0, '1', false ],
+ // Float values are rounded to integer (1.1 -> 1).
+ [ '1', null, null, null, 1.1, '2', false ],
+ // With step values.
+ [ '1', '0.5', null, null, null, '1.5', false ],
+ [ '1', '0.25', null, null, 4, '2', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '1', '0', null, null, null, '2', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '1', '-1', null, null, null, '2', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '1', 'foo', null, null, null, '2', false ],
+ // Min values testing.
+ [ '1', '1', 'foo', null, null, '2', false ],
+ [ '1', null, '-10', null, null, '2', false ],
+ [ '1', null, '0', null, null, '2', false ],
+ [ '1', null, '10', null, null, '10', false ],
+ [ '1', null, '2', null, null, '2', false ],
+ [ '1', null, '1', null, null, '2', false ],
+ [ '0', null, '4', null, '5', '5', false ],
+ [ '0', '2', '5', null, '3', '5', false ],
+ // Max values testing.
+ [ '1', '1', null, 'foo', null, '2', false ],
+ [ '1', null, null, '10', null, '2', false ],
+ [ '1', null, null, '0', null, '1', false ],
+ [ '1', null, null, '-10', null, '1', false ],
+ [ '1', null, null, '1', null, '1', false ],
+ [ '-3', '5', '-10', '-3', null, '-3', false ],
+ // Step mismatch.
+ [ '1', '2', '0', null, null, '2', false ],
+ [ '1', '2', '0', null, '2', '4', false ],
+ [ '8', '2', null, '9', null, '8', false ],
+ [ '-3', '2', '-6', null, null, '-2', false ],
+ [ '9', '3', '-10', null, null, '11', false ],
+ [ '7', '3', '-10', null, null, '8', false ],
+ [ '7', '3', '5', null, null, '8', false ],
+ [ '9', '4', '3', null, null, '11', false ],
+ [ '-2', '3', '-6', null, null, '0', false ],
+ [ '7', '3', '6', null, null, '9', false ],
+ // Clamping.
+ [ '1', '2', '0', '3', null, '2', false ],
+ [ '0', '5', '1', '8', '10', '6', false ],
+ [ '-9', '3', '-8', '-1', '5', '-2', false ],
+ [ '-9', '3', '8', '15', '15', '14', false ],
+ [ '-1', '3', '-1', '4', '3', '2', false ],
+ [ '-3', '2', '-6', '-2', null, '-2', false ],
+ [ '-3', '2', '-6', '-1', null, '-2', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '1', false ],
+ [ '', null, null, null, null, '1', false ],
+ [ '', '2', null, null, null, '2', false ],
+ [ '', '2', '3', null, null, '3', false ],
+ [ '', null, '3', null, null, '3', false ],
+ [ '', '2', '3', '8', null, '3', false ],
+ [ '', null, '-10', '10', null, '1', false ],
+ [ '', '3', '-10', '10', null, '2', false ],
+ // With step = 'any'.
+ [ '0', 'any', null, null, 1, null, true ],
+ [ '0', 'ANY', null, null, 1, null, true ],
+ [ '0', 'AnY', null, null, 1, null, true ],
+ [ '0', 'aNy', null, null, 1, null, true ],
+ // With @value = step base.
+ [ '1', '2', null, null, null, '3', false ],
+ ]},
+ { type: 'range', data: [
+ // Regular case.
+ [ '1', null, null, null, null, '2', false ],
+ // Argument testing.
+ [ '1', null, null, null, 1, '2', false ],
+ [ '9', null, null, null, 9, '18', false ],
+ [ '1', null, null, null, -1, '0', false ],
+ [ '1', null, null, null, 0, '1', false ],
+ // Float values are rounded to integer (1.1 -> 1).
+ [ '1', null, null, null, 1.1, '2', false ],
+ // With step values.
+ [ '1', '0.5', null, null, null, '1.5', false ],
+ [ '1', '0.25', null, null, 4, '2', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '1', '0', null, null, null, '2', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '1', '-1', null, null, null, '2', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '1', 'foo', null, null, null, '2', false ],
+ // Min values testing.
+ [ '1', '1', 'foo', null, null, '2', false ],
+ [ '1', null, '-10', null, null, '2', false ],
+ [ '1', null, '0', null, null, '2', false ],
+ [ '1', null, '10', null, null, '11', false ],
+ [ '1', null, '2', null, null, '3', false ],
+ [ '1', null, '1', null, null, '2', false ],
+ [ '0', null, '4', null, '5', '9', false ],
+ [ '0', '2', '5', null, '3', '11', false ],
+ // Max values testing.
+ [ '1', '1', null, 'foo', null, '2', false ],
+ [ '1', null, null, '10', null, '2', false ],
+ [ '1', null, null, '0', null, '0', false ],
+ [ '1', null, null, '-10', null, '0', false ],
+ [ '1', null, null, '1', null, '1', false ],
+ [ '-3', '5', '-10', '-3', null, '-5', false ],
+ // Step mismatch.
+ [ '1', '2', '0', null, null, '4', false ],
+ [ '1', '2', '0', null, '2', '6', false ],
+ [ '8', '2', null, '9', null, '8', false ],
+ [ '-3', '2', '-6', null, null, '0', false ],
+ [ '9', '3', '-10', null, null, '11', false ],
+ [ '7', '3', '-10', null, null, '11', false ],
+ [ '7', '3', '5', null, null, '11', false ],
+ [ '9', '4', '3', null, null, '15', false ],
+ [ '-2', '3', '-6', null, null, '0', false ],
+ [ '7', '3', '6', null, null, '9', false ],
+ // Clamping.
+ [ '1', '2', '0', '3', null, '2', false ],
+ [ '0', '5', '1', '8', '10', '6', false ],
+ [ '-9', '3', '-8', '-1', '5', '-2', false ],
+ [ '-9', '3', '8', '15', '15', '14', false ],
+ [ '-1', '3', '-1', '4', '3', '2', false ],
+ [ '-3', '2', '-6', '-2', null, '-2', false ],
+ [ '-3', '2', '-6', '-1', null, '-2', false ],
+ // value = "" (default will be 50).
+ [ '', null, null, null, null, '51', false ],
+ // With step = 'any'.
+ [ '0', 'any', null, null, 1, null, true ],
+ [ '0', 'ANY', null, null, 1, null, true ],
+ [ '0', 'AnY', null, null, 1, null, true ],
+ [ '0', 'aNy', null, null, 1, null, true ],
+ // With @value = step base.
+ [ '1', '2', null, null, null, '3', false ],
+ ]},
+ { type: 'date', data: [
+ // Regular case.
+ [ '2012-07-09', null, null, null, null, '2012-07-10', false ],
+ // Argument testing.
+ [ '2012-07-09', null, null, null, 1, '2012-07-10', false ],
+ [ '2012-07-09', null, null, null, 9, '2012-07-18', false ],
+ [ '2012-07-09', null, null, null, -1, '2012-07-08', false ],
+ [ '2012-07-09', null, null, null, 0, '2012-07-09', false ],
+ // Month/Year wrapping.
+ [ '2012-07-31', null, null, null, 1, '2012-08-01', false ],
+ [ '1968-12-29', null, null, null, 4, '1969-01-02', false ],
+ [ '1970-01-01', null, null, null, -365, '1969-01-01', false ],
+ [ '2012-03-01', null, null, null, -1, '2012-02-29', false ],
+ // Float values are rounded to integer (1.1 -> 1).
+ [ '2012-01-01', null, null, null, 1.1, '2012-01-02', false ],
+ [ '2012-01-01', null, null, null, 1.9, '2012-01-02', false ],
+ // With step values.
+ [ '2012-01-01', '0.5', null, null, null, '2012-01-02', false ],
+ [ '2012-01-01', '2', null, null, null, '2012-01-03', false ],
+ [ '2012-01-01', '0.25', null, null, 4, '2012-01-05', false ],
+ [ '2012-01-01', '1.1', '2012-01-01', null, 1, '2012-01-02', false ],
+ [ '2012-01-01', '1.1', '2012-01-01', null, 2, '2012-01-03', false ],
+ [ '2012-01-01', '1.1', '2012-01-01', null, 10, '2012-01-11', false ],
+ [ '2012-01-01', '1.1', '2012-01-01', null, 11, '2012-01-12', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '2012-01-01', '0', null, null, null, '2012-01-02', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '2012-01-01', '-1', null, null, null, '2012-01-02', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '2012-01-01', 'foo', null, null, null, '2012-01-02', false ],
+ // Min values testing.
+ [ '2012-01-01', '1', 'foo', null, null, '2012-01-02', false ],
+ [ '2012-01-01', null, '2011-12-01', null, null, '2012-01-02', false ],
+ [ '2012-01-01', null, '2012-01-02', null, null, '2012-01-02', false ],
+ [ '2012-01-01', null, '2012-01-01', null, null, '2012-01-02', false ],
+ [ '2012-01-01', null, '2012-01-04', null, 4, '2012-01-05', false ],
+ [ '2012-01-01', '2', '2012-01-04', null, 3, '2012-01-06', false ],
+ // Max values testing.
+ [ '2012-01-01', '1', null, 'foo', 2, '2012-01-03', false ],
+ [ '2012-01-01', '1', null, '2012-01-10', 1, '2012-01-02', false ],
+ [ '2012-01-02', null, null, '2012-01-01', null, '2012-01-02', false ],
+ [ '2012-01-02', null, null, '2012-01-02', null, '2012-01-02', false ],
+ [ '1969-01-02', '5', '1969-01-01', '1969-01-02', null, '1969-01-02', false ],
+ // Step mismatch.
+ [ '2012-01-02', '2', '2012-01-01', null, null, '2012-01-03', false ],
+ [ '2012-01-02', '2', '2012-01-01', null, 2, '2012-01-05', false ],
+ [ '2012-01-05', '2', '2012-01-01', '2012-01-06', null, '2012-01-05', false ],
+ [ '1970-01-02', '2', null, null, null, '1970-01-04', false ],
+ [ '1970-01-05', '3', null, null, null, '1970-01-08', false ],
+ [ '1970-01-03', '3', null, null, null, '1970-01-06', false ],
+ [ '1970-01-03', '3', '1970-01-02', null, null, '1970-01-05', false ],
+ // Clamping.
+ [ '2012-01-01', null, '2012-01-31', null, null, '2012-01-31', false ],
+ [ '1970-01-02', '2', '1970-01-01', '1970-01-04', null, '1970-01-03', false ],
+ [ '1970-01-01', '5', '1970-01-02', '1970-01-09', 10, '1970-01-07', false ],
+ [ '1969-12-28', '5', '1969-12-29', '1970-01-06', 3, '1970-01-03', false ],
+ [ '1970-01-01', '3', '1970-02-01', '1970-02-07', 15, '1970-02-07', false ],
+ [ '1970-01-01', '3', '1970-01-01', '1970-01-06', 2, '1970-01-04', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '1970-01-02', false ],
+ // With step = 'any'.
+ [ '2012-01-01', 'any', null, null, 1, null, true ],
+ [ '2012-01-01', 'ANY', null, null, 1, null, true ],
+ [ '2012-01-01', 'AnY', null, null, 1, null, true ],
+ [ '2012-01-01', 'aNy', null, null, 1, null, true ],
+ ]},
+ { type: 'time', data: [
+ // Regular case.
+ [ '16:39', null, null, null, null, '16:40', false ],
+ // Argument testing.
+ [ '16:40', null, null, null, 1, '16:41', false ],
+ [ '16:40', null, null, null, 5, '16:45', false ],
+ [ '16:40', null, null, null, -1, '16:39', false ],
+ [ '16:40', null, null, null, 0, '16:40', false ],
+ // hour/minutes/seconds wrapping.
+ [ '04:59', null, null, null, null, '05:00', false ],
+ [ '04:59:59', 1, null, null, null, '05:00', false ],
+ [ '04:59:59.900', 0.1, null, null, null, '05:00', false ],
+ [ '04:59:59.990', 0.01, null, null, null, '05:00', false ],
+ [ '04:59:59.999', 0.001, null, null, null, '05:00', false ],
+ // stepUp() on '23:59' gives '00:00'.
+ [ '23:59', null, null, null, 1, '00:00', false ],
+ [ '23:59', null, null, null, 3, '00:02', false ],
+ // Some random step values..
+ [ '16:56', '0.5', null, null, null, '16:56:00.500', false ],
+ [ '16:56', '2', null, null, null, '16:56:02', false ],
+ [ '16:56', '0.25',null, null, 4, '16:56:01', false ],
+ [ '16:57', '1.1', '16:00', null, 1, '16:57:01', false ],
+ [ '16:57', '1.1', '16:00', null, 2, '16:57:02.100', false ],
+ [ '16:57', '1.1', '16:00', null, 10, '16:57:10.900', false ],
+ [ '16:57', '1.1', '16:00', null, 11, '16:57:12', false ],
+ [ '16:57', '1.1', '16:00', null, 8, '16:57:08.700', false ],
+ // Invalid @step, means that we use the default value.
+ [ '17:01', '0', null, null, null, '17:02', false ],
+ [ '17:01', '-1', null, null, null, '17:02', false ],
+ [ '17:01', 'foo', null, null, null, '17:02', false ],
+ // Min values testing.
+ [ '17:02', '60', 'foo', null, 2, '17:04', false ],
+ [ '17:10', '60', '17:09', null, null, '17:11', false ],
+ [ '17:10', '60', '17:10', null, null, '17:11', false ],
+ [ '17:10', '60', '17:30', null, 1, '17:30', false ],
+ [ '17:10', '180', '17:05', null, null, '17:11', false ],
+ [ '17:10', '300', '17:10', '17:11', null,'17:10', false ],
+ // Max values testing.
+ [ '17:15', '60', null, 'foo', null, '17:16', false ],
+ [ '17:15', null, null, '17:20', null, '17:16', false ],
+ [ '17:15', null, null, '17:15', null, '17:15', false ],
+ [ '17:15', null, null, '17:13', 4, '17:15', false ],
+ [ '17:15', '120', null, '17:13', 3, '17:15', false ],
+ // Step mismatch.
+ [ '17:19', '120', '17:10', null, null, '17:20', false ],
+ [ '17:19', '120', '17:10', null, 2, '17:22', false ],
+ [ '17:19', '120', '17:18', '17:25', null, '17:20', false ],
+ [ '17:19', '120', null, null, null, '17:21', false ],
+ [ '17:19', '180', null, null, null, '17:22', false ],
+ // Clamping.
+ [ '17:22', null, null, '17:11', null, '17:22', false ],
+ [ '17:22', '120', '17:20', '17:22', null, '17:22', false ],
+ [ '17:22', '300', '17:12', '17:20', 10, '17:22', false ],
+ [ '17:22', '300', '17:18', '17:20', 2, '17:22', false ],
+ [ '17:22', '180', '17:00', '17:20', 15, '17:22', false ],
+ [ '17:22', '180', '17:10', '17:20', 2, '17:22', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '00:01', false ],
+ // With step = 'any'.
+ [ '17:26', 'any', null, null, 1, null, true ],
+ [ '17:26', 'ANY', null, null, 1, null, true ],
+ [ '17:26', 'AnY', null, null, 1, null, true ],
+ [ '17:26', 'aNy', null, null, 1, null, true ],
+ ]},
+ { type: 'month', data: [
+ // Regular case.
+ [ '2016-08', null, null, null, null, '2016-09', false ],
+ // Argument testing.
+ [ '2016-08', null, null, null, 1, '2016-09', false ],
+ [ '2016-08', null, null, null, 9, '2017-05', false ],
+ [ '2016-08', null, null, null, -1, '2016-07', false ],
+ [ '2016-08', null, null, null, 0, '2016-08', false ],
+ // Month/Year wrapping.
+ [ '2015-12', null, null, null, 1, '2016-01', false ],
+ [ '1968-12', null, null, null, 4, '1969-04', false ],
+ [ '1970-01', null, null, null, -12, '1969-01', false ],
+ // Float values are rounded to integer (1.1 -> 1).
+ [ '2016-01', null, null, null, 1.1, '2016-02', false ],
+ [ '2016-01', null, null, null, 1.9, '2016-02', false ],
+ // With step values.
+ [ '2016-01', '0.5', null, null, null, '2016-02', false ],
+ [ '2016-01', '2', null, null, null, '2016-03', false ],
+ [ '2016-01', '0.25', null, null, 4, '2016-05', false ],
+ [ '2016-01', '1.1', '2016-01', null, 1, '2016-02', false ],
+ [ '2016-01', '1.1', '2016-01', null, 2, '2016-03', false ],
+ [ '2016-01', '1.1', '2016-01', null, 10, '2016-11', false ],
+ [ '2016-01', '1.1', '2016-01', null, 11, '2016-12', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '2016-01', '0', null, null, null, '2016-02', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '2016-01', '-1', null, null, null, '2016-02', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '2016-01', 'foo', null, null, null, '2016-02', false ],
+ // Min values testing.
+ [ '2016-01', '1', 'foo', null, null, '2016-02', false ],
+ [ '2016-01', null, '2015-12', null, null, '2016-02', false ],
+ [ '2016-01', null, '2016-02', null, null, '2016-02', false ],
+ [ '2016-01', null, '2016-01', null, null, '2016-02', false ],
+ [ '2016-01', null, '2016-04', null, 4, '2016-05', false ],
+ [ '2016-01', '2', '2016-04', null, 3, '2016-06', false ],
+ // Max values testing.
+ [ '2016-01', '1', null, 'foo', 2, '2016-03', false ],
+ [ '2016-01', '1', null, '2016-02', 1, '2016-02', false ],
+ [ '2016-02', null, null, '2016-01', null, '2016-02', false ],
+ [ '2016-02', null, null, '2016-02', null, '2016-02', false ],
+ [ '1969-02', '5', '1969-01', '1969-02', null, '1969-02', false ],
+ // Step mismatch.
+ [ '2016-02', '2', '2016-01', null, null, '2016-03', false ],
+ [ '2016-02', '2', '2016-01', null, 2, '2016-05', false ],
+ [ '2016-05', '2', '2016-01', '2016-06', null, '2016-05', false ],
+ [ '1970-02', '2', null, null, null, '1970-04', false ],
+ [ '1970-05', '3', null, null, null, '1970-08', false ],
+ [ '1970-03', '3', null, null, null, '1970-06', false ],
+ [ '1970-03', '3', '1970-02', null, null, '1970-05', false ],
+ // Clamping.
+ [ '2016-01', null, '2016-12', null, null, '2016-12', false ],
+ [ '1970-02', '2', '1970-01', '1970-04', null, '1970-03', false ],
+ [ '1970-01', '5', '1970-02', '1970-09', 10, '1970-07', false ],
+ [ '1969-11', '5', '1969-12', '1970-06', 3, '1970-05', false ],
+ [ '1970-01', '3', '1970-02', '1971-07', 15, '1971-05', false ],
+ [ '1970-01', '3', '1970-01', '1970-06', 2, '1970-04', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '1970-02', false ],
+ // With step = 'any'.
+ [ '2016-01', 'any', null, null, 1, null, true ],
+ [ '2016-01', 'ANY', null, null, 1, null, true ],
+ [ '2016-01', 'AnY', null, null, 1, null, true ],
+ [ '2016-01', 'aNy', null, null, 1, null, true ],
+ ]},
+ { type: 'week', data: [
+ // Regular case.
+ [ '2016-W40', null, null, null, null, '2016-W41', false ],
+ // Argument testing.
+ [ '2016-W40', null, null, null, 1, '2016-W41', false ],
+ [ '2016-W40', null, null, null, 20, '2017-W08', false ],
+ [ '2016-W40', null, null, null, -1, '2016-W39', false ],
+ [ '2016-W40', null, null, null, 0, '2016-W40', false ],
+ // Week/Year wrapping.
+ [ '2015-W53', null, null, null, 1, '2016-W01', false ],
+ [ '1968-W52', null, null, null, 4, '1969-W04', false ],
+ [ '1970-W01', null, null, null, -52, '1969-W01', false ],
+ // Float values are rounded to integer (1.1 -> 1).
+ [ '2016-W01', null, null, null, 1.1, '2016-W02', false ],
+ [ '2016-W01', null, null, null, 1.9, '2016-W02', false ],
+ // With step values.
+ [ '2016-W01', '0.5', null, null, null, '2016-W02', false ],
+ [ '2016-W01', '2', null, null, null, '2016-W03', false ],
+ [ '2016-W01', '0.25', null, null, 4, '2016-W05', false ],
+ [ '2016-W01', '1.1', '2016-01', null, 1, '2016-W02', false ],
+ [ '2016-W01', '1.1', '2016-01', null, 2, '2016-W03', false ],
+ [ '2016-W01', '1.1', '2016-01', null, 10, '2016-W11', false ],
+ [ '2016-W01', '1.1', '2016-01', null, 20, '2016-W21', false ],
+ // step = 0 isn't allowed (-> step = 1).
+ [ '2016-W01', '0', null, null, null, '2016-W02', false ],
+ // step < 0 isn't allowed (-> step = 1).
+ [ '2016-W01', '-1', null, null, null, '2016-W02', false ],
+ // step = NaN isn't allowed (-> step = 1).
+ [ '2016-W01', 'foo', null, null, null, '2016-W02', false ],
+ // Min values testing.
+ [ '2016-W01', '1', 'foo', null, null, '2016-W02', false ],
+ [ '2016-W01', null, '2015-W53', null, null, '2016-W02', false ],
+ [ '2016-W01', null, '2016-W02', null, null, '2016-W02', false ],
+ [ '2016-W01', null, '2016-W01', null, null, '2016-W02', false ],
+ [ '2016-W01', null, '2016-W04', null, 4, '2016-W05', false ],
+ [ '2016-W01', '2', '2016-W04', null, 3, '2016-W06', false ],
+ // Max values testing.
+ [ '2016-W01', '1', null, 'foo', 2, '2016-W03', false ],
+ [ '2016-W01', '1', null, '2016-W02', 1, '2016-W02', false ],
+ [ '2016-W02', null, null, '2016-W01', null, '2016-W02', false ],
+ [ '2016-W02', null, null, '2016-W02', null, '2016-W02', false ],
+ [ '1969-W02', '5', '1969-W01', '1969-W02', null, '1969-W02', false ],
+ // Step mismatch.
+ [ '2016-W02', '2', '2016-W01', null, null, '2016-W03', false ],
+ [ '2016-W02', '2', '2016-W01', null, 2, '2016-W05', false ],
+ [ '2016-W05', '2', '2016-W01', '2016-W06', null, '2016-W05', false ],
+ [ '1970-W02', '2', null, null, null, '1970-W04', false ],
+ [ '1970-W05', '3', null, null, null, '1970-W08', false ],
+ [ '1970-W03', '3', null, null, null, '1970-W06', false ],
+ [ '1970-W03', '3', '1970-W02', null, null, '1970-W05', false ],
+ // Clamping.
+ [ '2016-W01', null, '2016-W52', null, null, '2016-W52', false ],
+ [ '1970-W02', '2', '1970-W01', '1970-W04', null, '1970-W03', false ],
+ [ '1970-W01', '5', '1970-W02', '1970-W09', 10, '1970-W07', false ],
+ [ '1969-W50', '5', '1969-W52', '1970-W06', 3, '1970-W05', false ],
+ [ '1970-W01', '3', '1970-W02', '1971-W07', 15, '1970-W44', false ],
+ [ '1970-W01', '3', '1970-W01', '1970-W06', 2, '1970-W04', false ],
+ // value = "" (NaN).
+ [ '', null, null, null, null, '1970-W02', false ],
+ // With step = 'any'.
+ [ '2016-W01', 'any', null, null, 1, null, true ],
+ [ '2016-W01', 'ANY', null, null, 1, null, true ],
+ [ '2016-W01', 'AnY', null, null, 1, null, true ],
+ [ '2016-W01', 'aNy', null, null, 1, null, true ],
+ ]},
+ ];
+
+ for (var test of testData) {
+ for (var data of test.data) {
+ var element = document.createElement("input");
+ element.type = test.type;
+
+ if (data[1] != null) {
+ element.step = data[1];
+ }
+
+ if (data[2] != null) {
+ element.min = data[2];
+ }
+
+ if (data[3] != null) {
+ element.max = data[3];
+ }
+
+ // Set 'value' last for type=range, because the final sanitized value
+ // after setting 'step', 'min' and 'max' can be affected by the order in
+ // which those attributes are set. Setting 'value' last makes it simpler
+ // to reason about what the final value should be.
+ if (data[0] != null) {
+ element.setAttribute('value', data[0]);
+ }
+
+ var exceptionCaught = false;
+ try {
+ if (data[4] != null) {
+ element.stepUp(data[4]);
+ } else {
+ element.stepUp();
+ }
+
+ is(element.value, data[5], "The value for type=" + test.type + " should be " + data[5]);
+ } catch (e) {
+ exceptionCaught = true;
+ is(element.value, data[0], e.name + "The value should not have changed");
+ is(e.name, 'InvalidStateError',
+ "It should be a InvalidStateError exception.");
+ } finally {
+ is(exceptionCaught, data[6], "exception status should be " + data[6]);
+ }
+ }
+ }
+}
+
+checkPresence();
+checkAvailability();
+
+checkStepDown();
+checkStepUp();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_submit_invalid_file.html b/dom/html/test/forms/test_submit_invalid_file.html
new file mode 100644
index 000000000..3941bf2b6
--- /dev/null
+++ b/dom/html/test/forms/test_submit_invalid_file.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=702949
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test invalid file submission</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=702949">Mozilla Bug 702949</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <form action='http://mochi.test:8888/chrome/dom/html/test/forms/submit_invalid_file.sjs' method='post' target='result'
+ enctype='multipart/form-data'>
+ <input type='file' name='file'>
+ </form>
+ <iframe name='result'></iframe>
+</div>
+<pre id="test">
+</pre>
+<script type="application/javascript">
+ /*
+ * Test invalid file submission by submitting a file that has been deleted
+ * from the file system before the form has been submitted.
+ * The form submission triggers a sjs file that shows its output in a frame.
+ * That means the test might time out if it fails.
+ */
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(function() {
+ var FileUtils = SpecialPowers.Cu.import("resource://gre/modules/FileUtils.jsm").FileUtils;
+
+ var i = document.getElementsByTagName('input')[0];
+
+ var file = FileUtils.getDir("TmpD", [], false);
+ file.append("testfile");
+ file.createUnique(SpecialPowers.Ci.nsIFile.NORMAL_FILE_TYPE, 0644);
+
+ SpecialPowers.wrap(i).value = file.path;
+ file.remove(/* recursive = */ false);
+
+ document.getElementsByName('result')[0].addEventListener('load', function() {
+ is(window.frames[0].document.body.textContent, "SUCCESS");
+ SimpleTest.finish();
+ });
+ document.forms[0].submit();
+ });
+</script>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_textarea_attributes_reflection.html b/dom/html/test/forms/test_textarea_attributes_reflection.html
new file mode 100644
index 000000000..a285b9955
--- /dev/null
+++ b/dom/html/test/forms/test_textarea_attributes_reflection.html
@@ -0,0 +1,104 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLTextAreaElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="../reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLTextAreaElement attributes reflection **/
+
+// .autofocus
+reflectBoolean({
+ element: document.createElement("textarea"),
+ attribute: "autofocus",
+});
+
+//.cols
+reflectUnsignedInt({
+ element: document.createElement("textarea"),
+ attribute: "cols",
+ nonZero: true,
+ defaultValue: 20,
+ fallback: true,
+});
+
+todo("dirName" in document.createElement("textarea"),
+ "dirName isn't implemented yet");
+
+// .disabled
+reflectBoolean({
+ element: document.createElement("textarea"),
+ attribute: "disabled",
+});
+
+// TODO: form (HTMLFormElement)
+
+// .maxLength
+reflectInt({
+ element: document.createElement("textarea"),
+ attribute: "maxLength",
+ nonNegative: true,
+});
+
+// .name
+reflectString({
+ element: document.createElement("textarea"),
+ attribute: "name",
+ otherValues: [ "isindex", "_charset_" ],
+});
+
+// .placeholder
+reflectString({
+ element: document.createElement("textarea"),
+ attribute: "placeholder",
+ otherValues: [ "foo\nbar", "foo\rbar", "foo\r\nbar" ],
+});
+
+// .readOnly
+reflectBoolean({
+ element: document.createElement("textarea"),
+ attribute: "readOnly",
+});
+
+// .required
+reflectBoolean({
+ element: document.createElement("textarea"),
+ attribute: "required",
+});
+
+// .rows
+reflectUnsignedInt({
+ element: document.createElement("textarea"),
+ attribute: "rows",
+ nonZero: true,
+ defaultValue: 2,
+ fallback: true,
+});
+
+// .wrap
+// TODO: make it an enumerated attributes limited to only known values, bug 670869.
+reflectString({
+ element: document.createElement("textarea"),
+ attribute: "wrap",
+ otherValues: [ "soft", "hard" ],
+});
+
+// .type doesn't reflect a content attribute.
+// .defaultValue doesn't reflect a content attribute.
+// .value doesn't reflect a content attribute.
+// .textLength doesn't reflect a content attribute.
+// .willValidate doesn't reflect a content attribute.
+// .validity doesn't reflect a content attribute.
+// .validationMessage doesn't reflect a content attribute.
+// .labels doesn't reflect a content attribute.
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_validation.html b/dom/html/test/forms/test_validation.html
new file mode 100644
index 000000000..ee0a93a99
--- /dev/null
+++ b/dom/html/test/forms/test_validation.html
@@ -0,0 +1,358 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=345624
+-->
+<head>
+ <title>Test for Bug 345624</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ input, textarea, fieldset, button, select, keygen, output, object { background-color: rgb(0,0,0) !important; }
+ :valid { background-color: rgb(0,255,0) !important; }
+ :invalid { background-color: rgb(255,0,0) !important; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">Mozilla Bug 345624</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <fieldset id='f'></fieldset>
+ <input id='i' oninvalid="invalidEventHandler(event);">
+ <button id='b' oninvalid="invalidEventHandler(event);"></button>
+ <select id='s' oninvalid="invalidEventHandler(event);"></select>
+ <textarea id='t' oninvalid="invalidEventHandler(event);"></textarea>
+ <output id='o' oninvalid="invalidEventHandler(event);"></output>
+ <keygen id='k'></keygen>
+ <object id='obj'></object>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 345624 **/
+
+var gInvalid = false;
+
+function invalidEventHandler(aEvent)
+{
+ function checkInvalidEvent(aEvent)
+ {
+ is(aEvent.type, "invalid", "Invalid event type should be invalid");
+ ok(!aEvent.bubbles, "Invalid event should not bubble");
+ ok(aEvent.cancelable, "Invalid event should be cancelable");
+ }
+
+ checkInvalidEvent(aEvent);
+
+ gInvalid = true;
+}
+
+function checkConstraintValidationAPIExist(element)
+{
+ ok('willValidate' in element, "willValidate is not available in the DOM");
+ ok('validationMessage' in element, "validationMessage is not available in the DOM");
+ ok('validity' in element, "validity is not available in the DOM");
+
+ if ('validity' in element) {
+ validity = element.validity;
+ ok('valueMissing' in validity, "validity.valueMissing is not available in the DOM");
+ ok('typeMismatch' in validity, "validity.typeMismatch is not available in the DOM");
+ ok('badInput' in validity, "validity.badInput is not available in the DOM");
+ ok('patternMismatch' in validity, "validity.patternMismatch is not available in the DOM");
+ ok('tooLong' in validity, "validity.tooLong is not available in the DOM");
+ ok('rangeUnderflow' in validity, "validity.rangeUnderflow is not available in the DOM");
+ ok('rangeOverflow' in validity, "validity.rangeOverflow is not available in the DOM");
+ ok('stepMismatch' in validity, "validity.stepMismatch is not available in the DOM");
+ ok('customError' in validity, "validity.customError is not available in the DOM");
+ ok('valid' in validity, "validity.valid is not available in the DOM");
+ }
+}
+
+function checkConstraintValidationAPIDefaultValues(element)
+{
+ // Not checking willValidate because the default value depends of the element
+
+ is(element.validationMessage, "", "validationMessage default value should be empty string");
+
+ ok(!element.validity.valueMissing, "The element should not suffer from a constraint validation");
+ ok(!element.validity.typeMismatch, "The element should not suffer from a constraint validation");
+ ok(!element.validity.badInput, "The element should not suffer from a constraint validation");
+ ok(!element.validity.patternMismatch, "The element should not suffer from a constraint validation");
+ ok(!element.validity.tooLong, "The element should not suffer from a constraint validation");
+ ok(!element.validity.rangeUnderflow, "The element should not suffer from a constraint validation");
+ ok(!element.validity.rangeOverflow, "The element should not suffer from a constraint validation");
+ ok(!element.validity.stepMismatch, "The element should not suffer from a constraint validation");
+ ok(!element.validity.customError, "The element should not suffer from a constraint validation");
+ ok(element.validity.valid, "The element should be valid by default");
+
+ ok(element.checkValidity(), "The element should be valid by default");
+}
+
+function checkDefaultPseudoClass()
+{
+ is(window.getComputedStyle(document.getElementById('f'), null)
+ .getPropertyValue('background-color'), "rgb(0, 255, 0)",
+ ":valid should apply");
+
+ is(window.getComputedStyle(document.getElementById('o'), null)
+ .getPropertyValue('background-color'), "rgb(0, 255, 0)",
+ ":valid should apply");
+
+ is(window.getComputedStyle(document.getElementById('obj'), null)
+ .getPropertyValue('background-color'), "rgb(0, 0, 0)",
+ "Nor :valid and :invalid should apply");
+
+ todo_is(window.getComputedStyle(document.getElementById('k'), null)
+ .getPropertyValue('background-color'), "rgb(0, 0, 0)",
+ "Nor :valid and :invalid should apply");
+
+ is(window.getComputedStyle(document.getElementById('s'), null)
+ .getPropertyValue('background-color'), "rgb(0, 255, 0)",
+ ":valid pseudo-class should apply");
+
+ is(window.getComputedStyle(document.getElementById('i'), null)
+ .getPropertyValue('background-color'), "rgb(0, 255, 0)",
+ ":valid pseudo-class should apply");
+
+ is(window.getComputedStyle(document.getElementById('t'), null)
+ .getPropertyValue('background-color'), "rgb(0, 255, 0)",
+ ":valid pseudo-class should apply");
+
+ is(window.getComputedStyle(document.getElementById('b'), null)
+ .getPropertyValue('background-color'), "rgb(0, 255, 0)",
+ ":valid pseudo-class should apply");
+}
+
+function checkSpecificWillValidate()
+{
+ // fieldset, output, object, keygen (TODO) and select elements
+ ok(!document.getElementById('f').willValidate, "Fielset element should be barred from constraint validation");
+ ok(!document.getElementById('obj').willValidate, "Object element should be barred from constraint validation");
+ todo(!document.getElementById('k').willValidate, "Keygen element should be barred from constraint validation");
+ ok(document.getElementById('o').willValidate, "Output element should not be barred from constraint validation");
+ ok(document.getElementById('s').willValidate, "Select element should not be barred from constraint validation");
+
+ // input element
+ i = document.getElementById('i');
+ i.type = "hidden";
+ ok(!i.willValidate, "Hidden state input should be barred from constraint validation");
+ is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
+ "rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
+ i.type = "reset";
+ ok(!i.willValidate, "Reset button state input should be barred from constraint validation");
+ is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
+ "rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
+ i.type = "button";
+ ok(!i.willValidate, "Button state input should be barred from constraint validation");
+ is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
+ "rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
+ i.type = "image";
+ ok(i.willValidate, "Image state input should not be barred from constraint validation");
+ is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid and :invalid should apply");
+ i.type = "submit";
+ ok(i.willValidate, "Submit state input should not be barred from constraint validation");
+ is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid and :invalid should apply");
+ i.type = "number";
+ ok(i.willValidate, "Number state input should not be barred from constraint validation");
+ is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+ i.type = "";
+ i.readOnly = 'true';
+ ok(!i.willValidate, "Readonly input should be barred from constraint validation");
+ is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
+ "rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
+ i.removeAttribute('readOnly');
+ ok(i.willValidate, "Default input element should not be barred from constraint validation");
+ is(window.getComputedStyle(i, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+
+ // button element
+ b = document.getElementById('b');
+ b.type = "reset";
+ ok(!b.willValidate, "Reset state button should be barred from constraint validation");
+ is(window.getComputedStyle(b, null).getPropertyValue('background-color'),
+ "rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
+ b.type = "button";
+ ok(!b.willValidate, "Button state button should be barred from constraint validation");
+ is(window.getComputedStyle(b, null).getPropertyValue('background-color'),
+ "rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
+ b.type = "submit";
+ ok(b.willValidate, "Submit state button should not be barred from constraint validation");
+ is(window.getComputedStyle(b, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid and :invalid should apply");
+ b.type = "";
+ ok(b.willValidate, "Default button element should not be barred from constraint validation");
+ is(window.getComputedStyle(b, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+
+ // textarea element
+ t = document.getElementById('t');
+ t.readOnly = true;
+ ok(!t.willValidate, "Readonly textarea should be barred from constraint validation");
+ is(window.getComputedStyle(t, null).getPropertyValue('background-color'),
+ "rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
+ t.removeAttribute('readOnly');
+ ok(t.willValidate, "Default textarea element should not be barred from constraint validation");
+ is(window.getComputedStyle(t, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+
+ // TODO: PROGRESS
+ // TODO: METER
+}
+
+function checkCommonWillValidate(element)
+{
+ // Not checking the default value because it has been checked previously.
+
+ // Not checking output elements because they can't be disabled.
+ if (element.tagName != 'OUTPUT') {
+ element.disabled = true;
+ ok(!element.willValidate, "Disabled element should be barred from constraint validation");
+
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 0, 0)", "Nor :valid and :invalid should apply");
+
+ element.removeAttribute('disabled');
+ }
+
+ // TODO: If an element has a datalist element ancestor, it is barred from constraint validation.
+}
+
+function checkCustomError(element, isBarred)
+{
+ element.setCustomValidity("message");
+ if (!isBarred) {
+ is(element.validationMessage, "message",
+ "When the element has a custom validity message, validation message should return it");
+ } else {
+ is(element.validationMessage, "",
+ "An element barred from constraint validation can't have a validation message");
+ }
+ ok(element.validity.customError, "The element should suffer from a custom error");
+ ok(!element.validity.valid, "The element should not be valid with a custom error");
+
+ if (element.tagName == "FIELDSET") {
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ isBarred ? "rgb(0, 255, 0)" : "rgb(255, 0, 0)",
+ ":invalid pseudo-classs should apply" + element.tagName);
+ }
+ else {
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ isBarred ? "rgb(0, 0, 0)" : "rgb(255, 0, 0)",
+ ":invalid pseudo-classs should apply" + element.tagName);
+ }
+
+ element.setCustomValidity("");
+ is(element.validationMessage, "", "The element should not have a validation message when reseted");
+ ok(!element.validity.customError, "The element should not suffer anymore from a custom error");
+ ok(element.validity.valid, "The element should now be valid");
+
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ isBarred && element.tagName != "FIELDSET" ? "rgb(0, 0, 0)" : "rgb(0, 255, 0)",
+ ":valid pseudo-classs should apply");
+}
+
+function checkCheckValidity(element)
+{
+ element.setCustomValidity("message");
+ ok(!element.checkValidity(), "checkValidity() should return false when the element is not valid");
+
+ ok(gInvalid, "Invalid event should have been handled");
+
+ gInvalid = false;
+ element.setCustomValidity("");
+
+ ok(element.checkValidity(), "Element should be valid");
+ ok(!gInvalid, "Invalid event should not have been handled");
+}
+
+function checkValidityStateObjectAliveWithoutElement(element)
+{
+ // We are creating a temporary element and getting it's ValidityState object.
+ // Then, we make sure it is removed by the garbage collector and we check the
+ // ValidityState default values (it should not crash).
+
+ var v = document.createElement(element).validity;
+ SpecialPowers.gc();
+
+ ok(!v.valueMissing,
+ "When the element is not alive, it shouldn't suffer from constraint validation");
+ ok(!v.typeMismatch,
+ "When the element is not alive, it shouldn't suffer from constraint validation");
+ ok(!v.badInput,
+ "When the element is not alive, it shouldn't suffer from constraint validation");
+ ok(!v.patternMismatch,
+ "When the element is not alive, it shouldn't suffer from constraint validation");
+ ok(!v.tooLong,
+ "When the element is not alive, it shouldn't suffer from constraint validation");
+ ok(!v.rangeUnderflow,
+ "When the element is not alive, it shouldn't suffer from constraint validation");
+ ok(!v.rangeOverflow,
+ "When the element is not alive, it shouldn't suffer from constraint validation");
+ ok(!v.stepMismatch,
+ "When the element is not alive, it shouldn't suffer from constraint validation");
+ ok(!v.customError,
+ "When the element is not alive, it shouldn't suffer from constraint validation");
+ ok(v.valid, "When the element is not alive, it should be valid");
+}
+
+checkConstraintValidationAPIExist(document.getElementById('f'));
+checkConstraintValidationAPIExist(document.getElementById('i'));
+checkConstraintValidationAPIExist(document.getElementById('b'));
+checkConstraintValidationAPIExist(document.getElementById('s'));
+checkConstraintValidationAPIExist(document.getElementById('t'));
+checkConstraintValidationAPIExist(document.getElementById('k'));
+checkConstraintValidationAPIExist(document.getElementById('o'));
+checkConstraintValidationAPIExist(document.getElementById('obj'));
+
+checkConstraintValidationAPIDefaultValues(document.getElementById('f'));
+checkConstraintValidationAPIDefaultValues(document.getElementById('i'));
+checkConstraintValidationAPIDefaultValues(document.getElementById('b'));
+checkConstraintValidationAPIDefaultValues(document.getElementById('s'));
+checkConstraintValidationAPIDefaultValues(document.getElementById('t'));
+checkConstraintValidationAPIDefaultValues(document.getElementById('k'));
+checkConstraintValidationAPIDefaultValues(document.getElementById('o'));
+checkConstraintValidationAPIDefaultValues(document.getElementById('obj'));
+
+checkDefaultPseudoClass();
+
+checkSpecificWillValidate();
+
+// Not checking button, fieldset, object and keygen
+// because they are always barred from constraint validation.
+checkCommonWillValidate(document.getElementById('i'));
+checkCommonWillValidate(document.getElementById('s'));
+checkCommonWillValidate(document.getElementById('t'));
+checkCommonWillValidate(document.getElementById('o'));
+
+/* TODO: add "keygen" element */
+checkCustomError(document.getElementById('i'), false);
+checkCustomError(document.getElementById('s'), false);
+checkCustomError(document.getElementById('t'), false);
+checkCustomError(document.getElementById('o'), false);
+checkCustomError(document.getElementById('b'), false);
+checkCustomError(document.getElementById('f'), true);
+checkCustomError(document.getElementById('obj'), true);
+
+// Not checking button, fieldset, object and keygen
+// because they are always barred from constraint validation.
+checkCheckValidity(document.getElementById('i'));
+checkCheckValidity(document.getElementById('s'));
+checkCheckValidity(document.getElementById('t'));
+checkCheckValidity(document.getElementById('o'));
+
+/* TODO: add "keygen" element */
+checkValidityStateObjectAliveWithoutElement("fieldset");
+checkValidityStateObjectAliveWithoutElement("input");
+checkValidityStateObjectAliveWithoutElement("button");
+checkValidityStateObjectAliveWithoutElement("select");
+checkValidityStateObjectAliveWithoutElement("textarea");
+checkValidityStateObjectAliveWithoutElement("output");
+checkValidityStateObjectAliveWithoutElement("object");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_validation_not_in_doc.html b/dom/html/test/forms/test_validation_not_in_doc.html
new file mode 100644
index 000000000..1500c6086
--- /dev/null
+++ b/dom/html/test/forms/test_validation_not_in_doc.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for constraint validation of form controls not in documents</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var input = document.createElement('input');
+ input.required = true;
+ assert_false(input.checkValidity());
+}, "Should validate input not in document");
+
+test(function() {
+ var textarea = document.createElement('textarea');
+ textarea.required = true;
+ assert_false(textarea.checkValidity());
+}, "Should validate textarea not in document");
+</script>
diff --git a/dom/html/test/forms/test_valueAsDate_pref.html b/dom/html/test/forms/test_valueAsDate_pref.html
new file mode 100644
index 000000000..8518c291b
--- /dev/null
+++ b/dom/html/test/forms/test_valueAsDate_pref.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=874640
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 874640</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 874640 **/
+ var states = [
+ // dom.experimental_forms, dom.forms.datepicker, dom.forms.datetime, expectedValueAsDate
+ [ 'true', 'true', 'true', 'true' ],
+ [ 'true', 'false', 'false', 'true' ],
+ [ 'false', 'true', 'false', 'true' ],
+ [ 'false', 'false', 'true', 'true' ],
+ [ 'false', 'false', 'false', 'false' ],
+ 'end'
+ ];
+
+ SimpleTest.waitForExplicitFinish();
+
+ function runTest(iframe) {
+ var state = states.shift();
+
+ if (state == 'end') {
+ SimpleTest.finish();
+ return;
+ }
+
+ SpecialPowers.pushPrefEnv({"set":[
+ ["dom.experimental_forms", state[0] === 'true'],
+ ["dom.forms.datepicker", state[1] === 'true'],
+ ["dom.forms.datetime", state[2] === 'true']]},
+ function() {
+ iframe.src = 'data:text/html,<script>' +
+ 'parent.is("valueAsDate" in document.createElement("input"), ' +
+ state[3] + ', "valueAsDate presence state should be ' + state[3] + '");' +
+ '<\/script>'
+ });
+ }
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=874640">Mozilla Bug 874640</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe onload='runTest(this);'></iframe>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/forms/test_valueasdate_attribute.html b/dom/html/test/forms/test_valueasdate_attribute.html
new file mode 100644
index 000000000..8c19fefd9
--- /dev/null
+++ b/dom/html/test/forms/test_valueasdate_attribute.html
@@ -0,0 +1,649 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=769370
+-->
+<head>
+ <title>Test for input.valueAsDate</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=769370">Mozilla Bug 769370</a>
+<iframe name="testFrame" style="display: none"></iframe>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 769370**/
+
+/**
+ * This test is checking .valueAsDate.
+ */
+
+var element = document.createElement("input");
+
+var validTypes =
+[
+ ["text", false],
+ ["password", false],
+ ["search", false],
+ ["tel", false],
+ ["email", false],
+ ["url", false],
+ ["hidden", false],
+ ["checkbox", false],
+ ["radio", false],
+ ["file", false],
+ ["submit", false],
+ ["image", false],
+ ["reset", false],
+ ["button", false],
+ ["number", false],
+ ["range", false],
+ ["date", true],
+ ["time", true],
+ ["color", false],
+ ["month", true],
+ ["week", true],
+ // TODO: temporary set to false until bug 888331 is fixed.
+ ["datetime-local", false],
+];
+
+function checkAvailability()
+{
+ for (let data of validTypes) {
+ var exceptionCatched = false;
+ element.type = data[0];
+ try {
+ element.valueAsDate;
+ } catch (e) {
+ exceptionCatched = true;
+ }
+ is(exceptionCatched, false,
+ "valueAsDate shouldn't throw exception on getting");
+
+ exceptionCatched = false;
+ try {
+ element.valueAsDate = new Date();
+ } catch (e) {
+ exceptionCatched = true;
+ }
+ is(exceptionCatched, !data[1], "valueAsDate for " + data[0] +
+ " availability is not correct");
+ }
+}
+
+function checkGarbageValues()
+{
+ for (let type of validTypes) {
+ if (!type[1]) {
+ continue;
+ }
+ type = type[0];
+
+ var element = document.createElement('input');
+ element.type = type;
+
+ element.value = "test";
+ element.valueAsDate = null;
+ is(element.value, "", "valueAsDate should set the value to the empty string");
+
+ element.value = "test";
+ element.valueAsDate = undefined;
+ is(element.value, "", "valueAsDate should set the value to the empty string");
+
+ element.value = "test";
+ element.valueAsDate = new Date(NaN);
+ is(element.value, "", "valueAsDate should set the value to the empty string");
+
+ var illegalValues = [
+ "foobar", 42, {}, function() { return 42; }, function() { return Date(); }
+ ];
+
+ for (let value of illegalValues) {
+ try {
+ var caught = false;
+ element.valueAsDate = value;
+ } catch(e) {
+ is(e.name, "TypeError", "Exception should be 'TypeError'.");
+ caught = true;
+ }
+ ok(caught, "Assigning " + value + " to .valueAsDate should throw");
+ }
+ }
+}
+
+function checkDateGet()
+{
+ var validData =
+ [
+ [ "2012-07-12", 1342051200000 ],
+ [ "1970-01-01", 0 ],
+ [ "1970-01-02", 86400000 ],
+ [ "1969-12-31", -86400000 ],
+ [ "0311-01-31", -52350451200000 ],
+ [ "275760-09-13", 8640000000000000 ],
+ [ "0001-01-01", -62135596800000 ],
+ [ "2012-02-29", 1330473600000 ],
+ [ "2011-02-28", 1298851200000 ],
+ ];
+
+ var invalidData =
+ [
+ [ "invaliddate" ],
+ [ "-001-12-31" ],
+ [ "901-12-31" ],
+ [ "1901-13-31" ],
+ [ "1901-12-32" ],
+ [ "1901-00-12" ],
+ [ "1901-01-00" ],
+ [ "1900-02-29" ],
+ [ "0000-01-01" ],
+ [ "" ],
+ // This date is valid for the input element, but is out of
+ // the date object range. In this case, on getting valueAsDate,
+ // a Date object will be created, but it will have a NaN internal value,
+ // and will return the string "Invalid Date".
+ [ "275760-09-14", true ],
+ ];
+
+ element.type = "date";
+ for (let data of validData) {
+ element.value = data[0];
+ is(element.valueAsDate.valueOf(), data[1],
+ "valueAsDate should return the " +
+ "valid date object representing this date");
+ }
+
+ for (let data of invalidData) {
+ element.value = data[0];
+ if (data[1]) {
+ is(String(element.valueAsDate), "Invalid Date",
+ "valueAsDate should return an invalid Date object " +
+ "when the element value is not a valid date");
+ } else {
+ is(element.valueAsDate, null,
+ "valueAsDate should return null " +
+ "when the element value is not a valid date");
+ }
+ }
+}
+
+function checkDateSet()
+{
+ var testData =
+ [
+ [ 1342051200000, "2012-07-12" ],
+ [ 0, "1970-01-01" ],
+ // Maximum valid date (limited by the ecma date object range).
+ [ 8640000000000000, "275760-09-13" ],
+ // Minimum valid date (limited by the input element minimum valid value).
+ [ -62135596800000 , "0001-01-01" ],
+ [ 1330473600000, "2012-02-29" ],
+ [ 1298851200000, "2011-02-28" ],
+ // "Values must be truncated to valid dates"
+ [ 42.1234, "1970-01-01" ],
+ [ 123.123456789123, "1970-01-01" ],
+ [ 1e-1, "1970-01-01" ],
+ [ 1298851200010, "2011-02-28" ],
+ [ -1, "1969-12-31" ],
+ [ -86400000, "1969-12-31" ],
+ [ 86400000, "1970-01-02" ],
+ // Negative years, this is out of range for the input element,
+ // the corresponding date string is the empty string
+ [ -62135596800001, "" ],
+ // Invalid dates.
+ ];
+
+ element.type = "date";
+ for (let data of testData) {
+ element.valueAsDate = new Date(data[0]);
+ is(element.value, data[1], "valueAsDate should set the value to "
+ + data[1]);
+ element.valueAsDate = new testFrame.Date(data[0]);
+ is(element.value, data[1], "valueAsDate with other-global date should " +
+ "set the value to " + data[1]);
+ }
+}
+
+function checkTimeGet()
+{
+ var tests = [
+ // Some invalid values to begin.
+ { value: "", result: null },
+ { value: "foobar", result: null },
+ { value: "00:", result: null },
+ { value: "24:00", result: null },
+ { value: "00:99", result: null },
+ { value: "00:00:", result: null },
+ { value: "00:00:99", result: null },
+ { value: "00:00:00:", result: null },
+ { value: "00:00:00.", result: null },
+ { value: "00:00:00.0000", result: null },
+ // Some simple valid values.
+ { value: "00:00", result: { time: 0, hours: 0, minutes: 0, seconds: 0, ms: 0 } },
+ { value: "00:01", result: { time: 60000, hours: 0, minutes: 1, seconds: 0, ms: 0 } },
+ { value: "01:00", result: { time: 3600000, hours: 1, minutes: 0, seconds: 0, ms: 0 } },
+ { value: "01:01", result: { time: 3660000, hours: 1, minutes: 1, seconds: 0, ms: 0 } },
+ { value: "13:37", result: { time: 49020000, hours: 13, minutes: 37, seconds: 0, ms: 0 } },
+ // Valid values including seconds.
+ { value: "00:00:01", result: { time: 1000, hours: 0, minutes: 0, seconds: 1, ms: 0 } },
+ { value: "13:37:42", result: { time: 49062000, hours: 13, minutes: 37, seconds: 42, ms: 0 } },
+ // Valid values including seconds fractions.
+ { value: "00:00:00.001", result: { time: 1, hours: 0, minutes: 0, seconds: 0, ms: 1 } },
+ { value: "00:00:00.123", result: { time: 123, hours: 0, minutes: 0, seconds: 0, ms: 123 } },
+ { value: "00:00:00.100", result: { time: 100, hours: 0, minutes: 0, seconds: 0, ms: 100 } },
+ { value: "00:00:00.000", result: { time: 0, hours: 0, minutes: 0, seconds: 0, ms: 0 } },
+ { value: "20:17:31.142", result: { time: 73051142, hours: 20, minutes: 17, seconds: 31, ms: 142 } },
+ // Highest possible value.
+ { value: "23:59:59.999", result: { time: 86399999, hours: 23, minutes: 59, seconds: 59, ms: 999 } },
+ // Some values with one or two digits for the fraction of seconds.
+ { value: "00:00:00.1", result: { time: 100, hours: 0, minutes: 0, seconds: 0, ms: 100 } },
+ { value: "00:00:00.14", result: { time: 140, hours: 0, minutes: 0, seconds: 0, ms: 140 } },
+ { value: "13:37:42.7", result: { time: 49062700, hours: 13, minutes: 37, seconds: 42, ms: 700 } },
+ { value: "23:31:12.23", result: { time: 84672230, hours: 23, minutes: 31, seconds: 12, ms: 230 } },
+ ];
+
+ var element = document.createElement('input');
+ element.type = 'time';
+
+ for (let test of tests) {
+ element.value = test.value;
+ if (test.result === null) {
+ is(element.valueAsDate, null, "element.valueAsDate should return null");
+ } else {
+ var date = element.valueAsDate;
+ isnot(date, null, "element.valueAsDate should not be null");
+
+ is(date.getTime(), test.result.time);
+ is(date.getUTCHours(), test.result.hours);
+ is(date.getUTCMinutes(), test.result.minutes);
+ is(date.getUTCSeconds(), test.result.seconds);
+ is(date.getUTCMilliseconds(), test.result.ms);
+ }
+ }
+}
+
+function checkTimeSet()
+{
+ var tests = [
+ // Simple tests.
+ { value: 0, result: "00:00" },
+ { value: 1, result: "00:00:00.001" },
+ { value: 100, result: "00:00:00.100" },
+ { value: 1000, result: "00:00:01" },
+ { value: 60000, result: "00:01" },
+ { value: 3600000, result: "01:00" },
+ { value: 83622234, result: "23:13:42.234" },
+ // Some edge cases.
+ { value: 86400000, result: "00:00" },
+ { value: 86400001, result: "00:00:00.001" },
+ { value: 170022234, result: "23:13:42.234" },
+ { value: 432000000, result: "00:00" },
+ { value: -1, result: "23:59:59.999" },
+ { value: -86400000, result: "00:00" },
+ { value: -86400001, result: "23:59:59.999" },
+ { value: -56789, result: "23:59:03.211" },
+ { value: 0.9, result: "00:00" },
+ ];
+
+ var element = document.createElement('input');
+ element.type = 'time';
+
+ for (let test of tests) {
+ element.valueAsDate = new Date(test.value);
+ is(element.value, test.result,
+ "element.value should have been changed by setting valueAsDate");
+ }
+}
+
+function checkWithBustedPrototype()
+{
+ for (let type of validTypes) {
+ if (!type[1]) {
+ continue;
+ }
+
+ type = type[0];
+
+ var element = document.createElement('input');
+ element.type = type;
+
+ var backupPrototype = {};
+ backupPrototype.getUTCFullYear = Date.prototype.getUTCFullYear;
+ backupPrototype.getUTCMonth = Date.prototype.getUTCMonth;
+ backupPrototype.getUTCDate = Date.prototype.getUTCDate;
+ backupPrototype.getTime = Date.prototype.getTime;
+ backupPrototype.setUTCFullYear = Date.prototype.setUTCFullYear;
+
+ Date.prototype.getUTCFullYear = function() { return {}; };
+ Date.prototype.getUTCMonth = function() { return {}; };
+ Date.prototype.getUTCDate = function() { return {}; };
+ Date.prototype.getTime = function() { return {}; };
+ Date.prototype.setUTCFullYear = function(y,m,d) { };
+
+ element.valueAsDate = new Date();
+
+ isnot(element.valueAsDate, null, ".valueAsDate should not return null");
+ // The object returned by element.valueAsDate should return a Date object
+ // with the same prototype:
+ is(element.valueAsDate.getUTCFullYear, Date.prototype.getUTCFullYear,
+ "prototype is the same");
+ is(element.valueAsDate.getUTCMonth, Date.prototype.getUTCMonth,
+ "prototype is the same");
+ is(element.valueAsDate.getUTCDate, Date.prototype.getUTCDate,
+ "prototype is the same");
+ is(element.valueAsDate.getTime, Date.prototype.getTime,
+ "prototype is the same");
+ is(element.valueAsDate.setUTCFullYear, Date.prototype.setUTCFullYear,
+ "prototype is the same");
+
+ // However the Date should have the correct information.
+ // Skip type=month for now, since .valueAsNumber returns number of months
+ // and not milliseconds.
+ if (type != "month") {
+ var witnessDate = new Date(element.valueAsNumber);
+ is(element.valueAsDate.valueOf(), witnessDate.valueOf(), "correct Date");
+ }
+
+ // Same test as above but using NaN instead of {}.
+
+ Date.prototype.getUTCFullYear = function() { return NaN; };
+ Date.prototype.getUTCMonth = function() { return NaN; };
+ Date.prototype.getUTCDate = function() { return NaN; };
+ Date.prototype.getTime = function() { return NaN; };
+ Date.prototype.setUTCFullYear = function(y,m,d) { };
+
+ element.valueAsDate = new Date();
+
+ isnot(element.valueAsDate, null, ".valueAsDate should not return null");
+ // The object returned by element.valueAsDate should return a Date object
+ // with the same prototype:
+ is(element.valueAsDate.getUTCFullYear, Date.prototype.getUTCFullYear,
+ "prototype is the same");
+ is(element.valueAsDate.getUTCMonth, Date.prototype.getUTCMonth,
+ "prototype is the same");
+ is(element.valueAsDate.getUTCDate, Date.prototype.getUTCDate,
+ "prototype is the same");
+ is(element.valueAsDate.getTime, Date.prototype.getTime,
+ "prototype is the same");
+ is(element.valueAsDate.setUTCFullYear, Date.prototype.setUTCFullYear,
+ "prototype is the same");
+
+ // However the Date should have the correct information.
+ // Skip type=month for now, since .valueAsNumber returns number of months
+ // and not milliseconds.
+ if (type != "month") {
+ var witnessDate = new Date(element.valueAsNumber);
+ is(element.valueAsDate.valueOf(), witnessDate.valueOf(), "correct Date");
+ }
+
+ Date.prototype.getUTCFullYear = backupPrototype.getUTCFullYear;
+ Date.prototype.getUTCMonth = backupPrototype.getUTCMonth;
+ Date.prototype.getUTCDate = backupPrototype.getUTCDate;
+ Date.prototype.getTime = backupPrototype.getTime;
+ Date.prototype.setUTCFullYear = backupPrototype.setUTCFullYear;
+ }
+}
+
+function checkMonthGet()
+{
+ var validData =
+ [
+ [ "2016-07", 1467331200000 ],
+ [ "1970-01", 0 ],
+ [ "1970-02", 2678400000 ],
+ [ "1969-12", -2678400000 ],
+ [ "0001-01", -62135596800000 ],
+ [ "275760-09", 8639998963200000 ],
+ ];
+
+ var invalidData =
+ [
+ [ "invalidmonth" ],
+ [ "0000-01" ],
+ [ "2016-00" ],
+ [ "123-01" ],
+ [ "2017-13" ],
+ [ "" ],
+ // This month is valid for the input element, but is out of
+ // the date object range. In this case, on getting valueAsDate,
+ // a Date object will be created, but it will have a NaN internal value,
+ // and will return the string "Invalid Date".
+ [ "275760-10", true ],
+ ];
+
+ element.type = "month";
+ for (let data of validData) {
+ element.value = data[0];
+ is(element.valueAsDate.valueOf(), data[1],
+ "valueAsDate should return the " +
+ "valid date object representing this month");
+ }
+
+ for (let data of invalidData) {
+ element.value = data[0];
+ if (data[1]) {
+ is(String(element.valueAsDate), "Invalid Date",
+ "valueAsDate should return an invalid Date object " +
+ "when the element value is not a valid month");
+ } else {
+ is(element.valueAsDate, null,
+ "valueAsDate should return null " +
+ "when the element value is not a valid month");
+ }
+ }
+}
+
+function checkMonthSet()
+{
+ var testData =
+ [
+ [ 1342051200000, "2012-07" ],
+ [ 0, "1970-01" ],
+ // Maximum valid month (limited by the ecma date object range).
+ [ 8640000000000000, "275760-09" ],
+ // Minimum valid month (limited by the input element minimum valid value).
+ [ -62135596800000 , "0001-01" ],
+ [ 1330473600000, "2012-02" ],
+ [ 1298851200000, "2011-02" ],
+ // "Values must be truncated to valid months"
+ [ 42.1234, "1970-01" ],
+ [ 123.123456789123, "1970-01" ],
+ [ 1e-1, "1970-01" ],
+ [ 1298851200010, "2011-02" ],
+ [ -1, "1969-12" ],
+ [ -86400000, "1969-12" ],
+ [ 86400000, "1970-01" ],
+ // Negative years, this is out of range for the input element,
+ // the corresponding month string is the empty string
+ [ -62135596800001, "" ],
+ ];
+
+ element.type = "month";
+ for (let data of testData) {
+ element.valueAsDate = new Date(data[0]);
+ is(element.value, data[1], "valueAsDate should set the value to "
+ + data[1]);
+ element.valueAsDate = new testFrame.Date(data[0]);
+ is(element.value, data[1], "valueAsDate with other-global date should " +
+ "set the value to " + data[1]);
+ }
+}
+
+function checkWeekGet()
+{
+ var validData =
+ [
+ // Common years starting on different days of week.
+ [ "2007-W01", Date.UTC(2007, 0, 1) ], // Mon
+ [ "2013-W01", Date.UTC(2012, 11, 31) ], // Tue
+ [ "2014-W01", Date.UTC(2013, 11, 30) ], // Wed
+ [ "2015-W01", Date.UTC(2014, 11, 29) ], // Thu
+ [ "2010-W01", Date.UTC(2010, 0, 4) ], // Fri
+ [ "2011-W01", Date.UTC(2011, 0, 3) ], // Sat
+ [ "2017-W01", Date.UTC(2017, 0, 2) ], // Sun
+ // Common years ending on different days of week.
+ [ "2007-W52", Date.UTC(2007, 11, 24) ], // Mon
+ [ "2013-W52", Date.UTC(2013, 11, 23) ], // Tue
+ [ "2014-W52", Date.UTC(2014, 11, 22) ], // Wed
+ [ "2015-W53", Date.UTC(2015, 11, 28) ], // Thu
+ [ "2010-W52", Date.UTC(2010, 11, 27) ], // Fri
+ [ "2011-W52", Date.UTC(2011, 11, 26) ], // Sat
+ [ "2017-W52", Date.UTC(2017, 11, 25) ], // Sun
+ // Leap years starting on different days of week.
+ [ "1996-W01", Date.UTC(1996, 0, 1) ], // Mon
+ [ "2008-W01", Date.UTC(2007, 11, 31) ], // Tue
+ [ "2020-W01", Date.UTC(2019, 11, 30) ], // Wed
+ [ "2004-W01", Date.UTC(2003, 11, 29) ], // Thu
+ [ "2016-W01", Date.UTC(2016, 0, 4) ], // Fri
+ [ "2000-W01", Date.UTC(2000, 0, 3) ], // Sat
+ [ "2012-W01", Date.UTC(2012, 0, 2) ], // Sun
+ // Leap years ending on different days of week.
+ [ "2012-W52", Date.UTC(2012, 11, 24) ], // Mon
+ [ "2024-W52", Date.UTC(2024, 11, 23) ], // Tue
+ [ "1980-W52", Date.UTC(1980, 11, 22) ], // Wed
+ [ "1992-W53", Date.UTC(1992, 11, 28) ], // Thu
+ [ "2004-W53", Date.UTC(2004, 11, 27) ], // Fri
+ [ "1988-W52", Date.UTC(1988, 11, 26) ], // Sat
+ [ "2000-W52", Date.UTC(2000, 11, 25) ], // Sun
+ // Other normal cases.
+ [ "2016-W36", 1473033600000 ],
+ [ "1969-W52", -864000000 ],
+ [ "1970-W01", -259200000 ],
+ [ "275760-W37", 8639999568000000 ],
+ ];
+
+ var invalidData =
+ [
+ [ "invalidweek" ],
+ [ "0000-W01" ],
+ [ "2016-W00" ],
+ [ "123-W01" ],
+ [ "2016-W53" ],
+ [ "" ],
+ // This week is valid for the input element, but is out of
+ // the date object range. In this case, on getting valueAsDate,
+ // a Date object will be created, but it will have a NaN internal value,
+ // and will return the string "Invalid Date".
+ [ "275760-W38", true ],
+ ];
+
+ element.type = "week";
+ for (let data of validData) {
+ element.value = data[0];
+ is(element.valueAsDate.valueOf(), data[1],
+ "valueAsDate should return the " +
+ "valid date object representing this week");
+ }
+
+ for (let data of invalidData) {
+ element.value = data[0];
+ if (data[1]) {
+ is(String(element.valueAsDate), "Invalid Date",
+ "valueAsDate should return an invalid Date object " +
+ "when the element value is not a valid week");
+ } else {
+ is(element.valueAsDate, null,
+ "valueAsDate should return null " +
+ "when the element value is not a valid week");
+ }
+ }
+}
+
+function checkWeekSet()
+{
+ var testData =
+ [
+ // Common years starting on different days of week.
+ [ Date.UTC(2007, 0, 1), "2007-W01" ], // Mon
+ [ Date.UTC(2013, 0, 1), "2013-W01" ], // Tue
+ [ Date.UTC(2014, 0, 1), "2014-W01" ], // Wed
+ [ Date.UTC(2015, 0, 1), "2015-W01" ], // Thu
+ [ Date.UTC(2010, 0, 1), "2009-W53" ], // Fri
+ [ Date.UTC(2011, 0, 1), "2010-W52" ], // Sat
+ [ Date.UTC(2017, 0, 1), "2016-W52" ], // Sun
+ // Common years ending on different days of week.
+ [ Date.UTC(2007, 11, 31), "2008-W01" ], // Mon
+ [ Date.UTC(2013, 11, 31), "2014-W01" ], // Tue
+ [ Date.UTC(2014, 11, 31), "2015-W01" ], // Wed
+ [ Date.UTC(2015, 11, 31), "2015-W53" ], // Thu
+ [ Date.UTC(2010, 11, 31), "2010-W52" ], // Fri
+ [ Date.UTC(2011, 11, 31), "2011-W52" ], // Sat
+ [ Date.UTC(2017, 11, 31), "2017-W52" ], // Sun
+ // Leap years starting on different days of week.
+ [ Date.UTC(1996, 0, 1), "1996-W01" ], // Mon
+ [ Date.UTC(2008, 0, 1), "2008-W01" ], // Tue
+ [ Date.UTC(2020, 0, 1), "2020-W01" ], // Wed
+ [ Date.UTC(2004, 0, 1), "2004-W01" ], // Thu
+ [ Date.UTC(2016, 0, 1), "2015-W53" ], // Fri
+ [ Date.UTC(2000, 0, 1), "1999-W52" ], // Sat
+ [ Date.UTC(2012, 0, 1), "2011-W52" ], // Sun
+ // Leap years ending on different days of week.
+ [ Date.UTC(2012, 11, 31), "2013-W01" ], // Mon
+ [ Date.UTC(2024, 11, 31), "2025-W01" ], // Tue
+ [ Date.UTC(1980, 11, 31), "1981-W01" ], // Wed
+ [ Date.UTC(1992, 11, 31), "1992-W53" ], // Thu
+ [ Date.UTC(2004, 11, 31), "2004-W53" ], // Fri
+ [ Date.UTC(1988, 11, 31), "1988-W52" ], // Sat
+ [ Date.UTC(2000, 11, 31), "2000-W52" ], // Sun
+ // Other normal cases.
+ [ Date.UTC(2016, 8, 9), "2016-W36" ],
+ [ Date.UTC(2010, 0, 3), "2009-W53" ],
+ [ Date.UTC(2010, 0, 4), "2010-W01" ],
+ [ Date.UTC(2010, 0, 10), "2010-W01" ],
+ [ Date.UTC(2010, 0, 11), "2010-W02" ],
+ [ 0, "1970-W01" ],
+ // Maximum valid month (limited by the ecma date object range).
+ [ 8640000000000000, "275760-W37" ],
+ // Minimum valid month (limited by the input element minimum valid value).
+ [ -62135596800000 , "0001-W01" ],
+ // "Values must be truncated to valid week"
+ [ 42.1234, "1970-W01" ],
+ [ 123.123456789123, "1970-W01" ],
+ [ 1e-1, "1970-W01" ],
+ [ -1.1, "1970-W01" ],
+ [ -345600000, "1969-W52" ],
+ // Negative years, this is out of range for the input element,
+ // the corresponding week string is the empty string
+ [ -62135596800001, "" ],
+ ];
+
+ element.type = "week";
+ for (let data of testData) {
+ element.valueAsDate = new Date(data[0]);
+ is(element.value, data[1], "valueAsDate should set the value to "
+ + data[1]);
+ element.valueAsDate = new testFrame.Date(data[0]);
+ is(element.value, data[1], "valueAsDate with other-global date should " +
+ "set the value to " + data[1]);
+ }
+}
+
+checkAvailability();
+checkGarbageValues();
+checkWithBustedPrototype();
+
+// Test <input type='date'>.
+checkDateGet();
+checkDateSet();
+
+// Test <input type='time'>.
+checkTimeGet();
+checkTimeSet();
+
+// Test <input type='month'>.
+checkMonthGet();
+checkMonthSet();
+
+// Test <input type='week'>.
+checkWeekGet();
+checkWeekSet();
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/forms/test_valueasnumber_attribute.html b/dom/html/test/forms/test_valueasnumber_attribute.html
new file mode 100644
index 000000000..d7471502b
--- /dev/null
+++ b/dom/html/test/forms/test_valueasnumber_attribute.html
@@ -0,0 +1,744 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=636737
+-->
+<head>
+ <title>Test for Bug input.valueAsNumber</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=636737">Mozilla Bug 636737</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 636737 **/
+
+/**
+ * This test is checking .valueAsNumber.
+ */
+
+function checkAvailability()
+{
+ var testData =
+ [
+ ["text", false],
+ ["password", false],
+ ["search", false],
+ ["tel", false],
+ ["email", false],
+ ["url", false],
+ ["hidden", false],
+ ["checkbox", false],
+ ["radio", false],
+ ["file", false],
+ ["submit", false],
+ ["image", false],
+ ["reset", false],
+ ["button", false],
+ ["number", true],
+ ["range", true],
+ ["date", true],
+ ["time", true],
+ ["color", false],
+ ["month", true],
+ ["week", true],
+ // TODO: temporary set to false until bug 888331 is fixed.
+ ["datetime-local", false],
+ ];
+
+ var element = document.createElement('input');
+
+ for (let data of testData) {
+ var exceptionCatched = false;
+ element.type = data[0];
+ try {
+ element.valueAsNumber;
+ } catch (e) {
+ exceptionCatched = true;
+ }
+ is(exceptionCatched, false,
+ "valueAsNumber shouldn't throw exception on getting");
+
+ exceptionCatched = false;
+ try {
+ element.valueAsNumber = 42;
+ } catch (e) {
+ exceptionCatched = true;
+ }
+ is(exceptionCatched, !data[1], "valueAsNumber for " + data[0] +
+ " availability is not correct");
+ }
+}
+
+function checkNumberGet()
+{
+ var testData =
+ [
+ ["42", 42],
+ ["-42", -42], // should work for negative values
+ ["42.1234", 42.1234],
+ ["123.123456789123", 123.123456789123], // double precision
+ ["1e2", 100], // e should be usable
+ ["2e1", 20],
+ ["1e-1", 0.1], // value after e can be negative
+ ["1E2", 100], // E can be used instead of e
+ ["e", null],
+ ["e2", null],
+ ["1e0.1", null],
+ ["", null], // the empty string is not a number
+ ["foo", null],
+ ["42,13", null], // comma can't be used as a decimal separator
+ ];
+
+ var element = document.createElement('input');
+ element.type = "number";
+ for (let data of testData) {
+ element.value = data[0];
+
+ // Given that NaN != NaN, we have to use null when the expected value is NaN.
+ if (data[1] != null) {
+ is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
+ "floating point representation of the value");
+ } else {
+ ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
+ "when the element value is not a number");
+ }
+ }
+}
+
+function checkNumberSet()
+{
+ var testData =
+ [
+ [42, "42"],
+ [-42, "-42"], // should work for negative values
+ [42.1234, "42.1234"],
+ [123.123456789123, "123.123456789123"], // double precision
+ [1e2, "100"], // e should be usable
+ [2e1, "20"],
+ [1e-1, "0.1"], // value after e can be negative
+ [1E2, "100"], // E can be used instead of e
+ // Setting a string will set NaN.
+ ["foo", ""],
+ // "" is converted to 0.
+ ["", "0"],
+ [42, "42"], // Keep this here, it is used by the next test.
+ // Setting Infinity should throw and not change the current value.
+ [Infinity, "42", true],
+ [-Infinity, "42", true],
+ // Setting NaN should change the value to the empty string.
+ [NaN, ""],
+ ];
+
+ var element = document.createElement('input');
+ element.type = "number";
+ for (let data of testData) {
+ var caught = false;
+ try {
+ element.valueAsNumber = data[0];
+ is(element.value, data[1],
+ "valueAsNumber should be able to set the value");
+ } catch (e) {
+ caught = true;
+ }
+
+ if (data[2]) {
+ ok(caught, "valueAsNumber should have thrown");
+ is(element.value, data[1], "value should not have changed");
+ } else {
+ ok(!caught, "valueAsNumber should not have thrown");
+ }
+ }
+}
+
+function checkRangeGet()
+{
+ // For type=range we should never get NaN since the user agent is required
+ // to fix up the input's value to be something sensible.
+
+ var min = -200;
+ var max = 200;
+ var defaultValue = min + (max - min)/2;
+
+ var testData =
+ [
+ ["42", 42],
+ ["-42", -42], // should work for negative values
+ ["42.1234", 42.1234],
+ ["123.123456789123", 123.123456789123], // double precision
+ ["1e2", 100], // e should be usable
+ ["2e1", 20],
+ ["1e-1", 0.1], // value after e can be negative
+ ["1E2", 100], // E can be used instead of e
+ ["e", defaultValue],
+ ["e2", defaultValue],
+ ["1e0.1", defaultValue],
+ ["", defaultValue],
+ ["foo", defaultValue],
+ ["42,13", defaultValue],
+ ];
+
+ var element = document.createElement('input');
+ element.type = "range";
+ element.setAttribute("min", min); // avoids out of range sanitization
+ element.setAttribute("max", max);
+ element.setAttribute("step", "any"); // avoids step mismatch sanitization
+ for (let data of testData) {
+ element.value = data[0];
+
+ // Given that NaN != NaN, we have to use null when the expected value is NaN.
+ is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
+ "floating point representation of the value");
+ }
+}
+
+function checkRangeSet()
+{
+ var min = -200;
+ var max = 200;
+ var defaultValue = String(min + (max - min)/2);
+
+ var testData =
+ [
+ [42, "42"],
+ [-42, "-42"], // should work for negative values
+ [42.1234, "42.1234"],
+ [123.123456789123, "123.123456789123"], // double precision
+ [1e2, "100"], // e should be usable
+ [2e1, "20"],
+ [1e-1, "0.1"], // value after e can be negative
+ [1E2, "100"], // E can be used instead of e
+ ["foo", defaultValue],
+ ["", defaultValue],
+ [42, "42"], // Keep this here, it is used by the next test.
+ // Setting Infinity should throw and not change the current value.
+ [Infinity, "42", true],
+ [-Infinity, "42", true],
+ // Setting NaN should change the value to the empty string.
+ [NaN, defaultValue],
+ ];
+
+ var element = document.createElement('input');
+ element.type = "range";
+ element.setAttribute("min", min); // avoids out of range sanitization
+ element.setAttribute("max", max);
+ element.setAttribute("step", "any"); // avoids step mismatch sanitization
+ for (let data of testData) {
+ var caught = false;
+ try {
+ element.valueAsNumber = data[0];
+ is(element.value, data[1],
+ "valueAsNumber should be able to set the value");
+ } catch (e) {
+ caught = true;
+ }
+
+ if (data[2]) {
+ ok(caught, "valueAsNumber should have thrown");
+ is(element.value, data[1], "value should not have changed");
+ } else {
+ ok(!caught, "valueAsNumber should not have thrown");
+ }
+ }
+}
+
+function checkDateGet()
+{
+ var validData =
+ [
+ [ "2012-07-12", 1342051200000 ],
+ [ "1970-01-01", 0 ],
+ // We are supposed to support at least until this date.
+ // (corresponding to the date object maximal value)
+ [ "275760-09-13", 8640000000000000 ],
+ // Minimum valid date (limited by the input element minimum valid value)
+ [ "0001-01-01", -62135596800000 ],
+ [ "2012-02-29", 1330473600000 ],
+ [ "2011-02-28", 1298851200000 ],
+ ];
+
+ var invalidData =
+ [
+ "invaliddate",
+ "",
+ "275760-09-14",
+ "999-12-31",
+ "-001-12-31",
+ "0000-01-01",
+ "2011-02-29",
+ "1901-13-31",
+ "1901-12-32",
+ "1901-00-12",
+ "1901-01-00",
+ "1900-02-29",
+ ];
+
+ var element = document.createElement('input');
+ element.type = "date";
+ for (let data of validData) {
+ element.value = data[0];
+ is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
+ "timestamp representing this date");
+ }
+
+ for (let data of invalidData) {
+ element.value = data;
+ ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
+ "when the element value is not a valid date");
+ }
+}
+
+function checkDateSet()
+{
+ var testData =
+ [
+ [ 1342051200000, "2012-07-12" ],
+ [ 0, "1970-01-01" ],
+ // Maximum valid date (limited by the ecma date object range).
+ [ 8640000000000000, "275760-09-13" ],
+ // Minimum valid date (limited by the input element minimum valid value)
+ [ -62135596800000, "0001-01-01" ],
+ [ 1330473600000, "2012-02-29" ],
+ [ 1298851200000, "2011-02-28" ],
+ // "Values must be truncated to valid dates"
+ [ 42.1234, "1970-01-01" ],
+ [ 123.123456789123, "1970-01-01" ],
+ [ 1e2, "1970-01-01" ],
+ [ 1E9, "1970-01-12" ],
+ [ 1e-1, "1970-01-01" ],
+ [ 2e10, "1970-08-20" ],
+ [ 1298851200010, "2011-02-28" ],
+ [ -1, "1969-12-31" ],
+ [ -86400000, "1969-12-31" ],
+ [ 86400000, "1970-01-02" ],
+ // Invalid numbers.
+ // Those are implicitly converted to numbers
+ [ "", "1970-01-01" ],
+ [ true, "1970-01-01" ],
+ [ false, "1970-01-01" ],
+ [ null, "1970-01-01" ],
+ // Those are converted to NaN, the corresponding date string is the empty string
+ [ "invaliddatenumber", "" ],
+ [ NaN, "" ],
+ [ undefined, "" ],
+ // Out of range, the corresponding date string is the empty string
+ [ -62135596800001, "" ],
+ // Infinity will keep the current value and throw (so we need to set a current value).
+ [ 1298851200010, "2011-02-28" ],
+ [ Infinity, "2011-02-28", true ],
+ [ -Infinity, "2011-02-28", true ],
+ ];
+
+ var element = document.createElement('input');
+ element.type = "date";
+ for (let data of testData) {
+ var caught = false;
+
+ try {
+ element.valueAsNumber = data[0];
+ is(element.value, data[1], "valueAsNumber should set the value to " + data[1]);
+ } catch(e) {
+ caught = true;
+ }
+
+ if (data[2]) {
+ ok(caught, "valueAsNumber should have thrown");
+ is(element.value, data[1], "the value should not have changed");
+ } else {
+ ok(!caught, "valueAsNumber should not have thrown");
+ }
+ }
+
+}
+
+function checkTimeGet()
+{
+ var tests = [
+ // Some invalid values to begin.
+ { value: "", result: NaN },
+ { value: "foobar", result: NaN },
+ { value: "00:", result: NaN },
+ { value: "24:00", result: NaN },
+ { value: "00:99", result: NaN },
+ { value: "00:00:", result: NaN },
+ { value: "00:00:99", result: NaN },
+ { value: "00:00:00:", result: NaN },
+ { value: "00:00:00.", result: NaN },
+ { value: "00:00:00.0000", result: NaN },
+ // Some simple valid values.
+ { value: "00:00", result: 0 },
+ { value: "00:01", result: 60000 },
+ { value: "01:00", result: 3600000 },
+ { value: "01:01", result: 3660000 },
+ { value: "13:37", result: 49020000 },
+ // Valid values including seconds.
+ { value: "00:00:01", result: 1000 },
+ { value: "13:37:42", result: 49062000 },
+ // Valid values including seconds fractions.
+ { value: "00:00:00.001", result: 1 },
+ { value: "00:00:00.123", result: 123 },
+ { value: "00:00:00.100", result: 100 },
+ { value: "00:00:00.000", result: 0 },
+ { value: "20:17:31.142", result: 73051142 },
+ // Highest possible value.
+ { value: "23:59:59.999", result: 86399999 },
+ // Some values with one or two digits for the fraction of seconds.
+ { value: "00:00:00.1", result: 100 },
+ { value: "00:00:00.14", result: 140 },
+ { value: "13:37:42.7", result: 49062700 },
+ { value: "23:31:12.23", result: 84672230 },
+ ];
+
+ var element = document.createElement('input');
+ element.type = 'time';
+
+ for (let test of tests) {
+ element.value = test.value;
+ if (isNaN(test.result)) {
+ ok(isNaN(element.valueAsNumber),
+ "invalid value should have .valueAsNumber return NaN");
+ } else {
+ is(element.valueAsNumber, test.result,
+ ".valueAsNumber should return " + test.result);
+ }
+ }
+}
+
+function checkTimeSet()
+{
+ var tests = [
+ // Some NaN values (should set to empty string).
+ { value: NaN, result: "" },
+ { value: "foobar", result: "" },
+ { value: function() {}, result: "" },
+ // Inifinity (should throw).
+ { value: Infinity, throw: true },
+ { value: -Infinity, throw: true },
+ // "" converts to 0... JS is fun :)
+ { value: "", result: "00:00" },
+ // Simple tests.
+ { value: 0, result: "00:00" },
+ { value: 1, result: "00:00:00.001" },
+ { value: 100, result: "00:00:00.100" },
+ { value: 1000, result: "00:00:01" },
+ { value: 60000, result: "00:01" },
+ { value: 3600000, result: "01:00" },
+ { value: 83622234, result: "23:13:42.234" },
+ // Some edge cases.
+ { value: 86400000, result: "00:00" },
+ { value: 86400001, result: "00:00:00.001" },
+ { value: 170022234, result: "23:13:42.234" },
+ { value: 432000000, result: "00:00" },
+ { value: -1, result: "23:59:59.999" },
+ { value: -86400000, result: "00:00" },
+ { value: -86400001, result: "23:59:59.999" },
+ { value: -56789, result: "23:59:03.211" },
+ { value: 0.9, result: "00:00" },
+ ];
+
+ var element = document.createElement('input');
+ element.type = 'time';
+
+ for (let test of tests) {
+ try {
+ var caught = false;
+ element.valueAsNumber = test.value;
+ is(element.value, test.result, "value should return " + test.result);
+ } catch(e) {
+ caught = true;
+ }
+
+ if (!test.throw) {
+ test.throw = false;
+ }
+
+ is(caught, test.throw, "the test throwing status should be " + test.throw);
+ }
+}
+
+function checkMonthGet()
+{
+ var validData =
+ [
+ [ "2016-07", 558 ],
+ [ "1970-01", 0 ],
+ [ "1969-12", -1 ],
+ [ "0001-01", -23628 ],
+ [ "10000-12", 96371 ],
+ [ "275760-09", 3285488 ],
+ ];
+
+ var invalidData =
+ [
+ "invalidmonth",
+ "0000-01",
+ "2000-00",
+ "2012-13",
+ // Out of range.
+ "275760-10",
+ ];
+
+ var element = document.createElement('input');
+ element.type = "month";
+ for (let data of validData) {
+ element.value = data[0];
+ is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
+ "integer value representing this month");
+ }
+
+ for (let data of invalidData) {
+ element.value = data;
+ ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
+ "when the element value is not a valid month");
+ }
+}
+
+function checkMonthSet()
+{
+ var testData =
+ [
+ [ 558, "2016-07" ],
+ [ 0, "1970-01" ],
+ [ -1, "1969-12" ],
+ [ 96371, "10000-12" ],
+ [ 12, "1971-01" ],
+ [ -12, "1969-01" ],
+ // Maximum valid month (limited by the ecma date object range)
+ [ 3285488, "275760-09" ],
+ // Minimum valid month (limited by the input element minimum valid value)
+ [ -23628, "0001-01" ],
+ // "Values must be truncated to valid months"
+ [ 0.3, "1970-01" ],
+ [ -1.1, "1969-11" ],
+ [ 1e2, "1978-05" ],
+ [ 1e-1, "1970-01" ],
+ // Invalid numbers.
+ // Those are implicitly converted to numbers
+ [ "", "1970-01" ],
+ [ true, "1970-02" ],
+ [ false, "1970-01" ],
+ [ null, "1970-01" ],
+ // Those are converted to NaN, the corresponding month string is the empty string
+ [ "invalidmonth", "" ],
+ [ NaN, "" ],
+ [ undefined, "" ],
+ // Out of range, the corresponding month string is the empty string
+ [ -23629, "" ],
+ [ 3285489, "" ],
+ // Infinity will keep the current value and throw (so we need to set a current value)
+ [ 558, "2016-07" ],
+ [ Infinity, "2016-07", true ],
+ [ -Infinity, "2016-07", true ],
+ ];
+
+ var element = document.createElement('input');
+ element.type = "month";
+ for (let data of testData) {
+ var caught = false;
+
+ try {
+ element.valueAsNumber = data[0];
+ is(element.value, data[1], "valueAsNumber should set the value to " + data[1]);
+ } catch(e) {
+ caught = true;
+ }
+
+ if (data[2]) {
+ ok(caught, "valueAsNumber should have thrown");
+ is(element.value, data[1], "the value should not have changed");
+ } else {
+ ok(!caught, "valueAsNumber should not have thrown");
+ }
+ }
+}
+
+function checkWeekGet()
+{
+ var validData =
+ [
+ // Common years starting on different days of week.
+ [ "2007-W01", Date.UTC(2007, 0, 1) ], // Mon
+ [ "2013-W01", Date.UTC(2012, 11, 31) ], // Tue
+ [ "2014-W01", Date.UTC(2013, 11, 30) ], // Wed
+ [ "2015-W01", Date.UTC(2014, 11, 29) ], // Thu
+ [ "2010-W01", Date.UTC(2010, 0, 4) ], // Fri
+ [ "2011-W01", Date.UTC(2011, 0, 3) ], // Sat
+ [ "2017-W01", Date.UTC(2017, 0, 2) ], // Sun
+ // Common years ending on different days of week.
+ [ "2007-W52", Date.UTC(2007, 11, 24) ], // Mon
+ [ "2013-W52", Date.UTC(2013, 11, 23) ], // Tue
+ [ "2014-W52", Date.UTC(2014, 11, 22) ], // Wed
+ [ "2015-W53", Date.UTC(2015, 11, 28) ], // Thu
+ [ "2010-W52", Date.UTC(2010, 11, 27) ], // Fri
+ [ "2011-W52", Date.UTC(2011, 11, 26) ], // Sat
+ [ "2017-W52", Date.UTC(2017, 11, 25) ], // Sun
+ // Leap years starting on different days of week.
+ [ "1996-W01", Date.UTC(1996, 0, 1) ], // Mon
+ [ "2008-W01", Date.UTC(2007, 11, 31) ], // Tue
+ [ "2020-W01", Date.UTC(2019, 11, 30) ], // Wed
+ [ "2004-W01", Date.UTC(2003, 11, 29) ], // Thu
+ [ "2016-W01", Date.UTC(2016, 0, 4) ], // Fri
+ [ "2000-W01", Date.UTC(2000, 0, 3) ], // Sat
+ [ "2012-W01", Date.UTC(2012, 0, 2) ], // Sun
+ // Leap years ending on different days of week.
+ [ "2012-W52", Date.UTC(2012, 11, 24) ], // Mon
+ [ "2024-W52", Date.UTC(2024, 11, 23) ], // Tue
+ [ "1980-W52", Date.UTC(1980, 11, 22) ], // Wed
+ [ "1992-W53", Date.UTC(1992, 11, 28) ], // Thu
+ [ "2004-W53", Date.UTC(2004, 11, 27) ], // Fri
+ [ "1988-W52", Date.UTC(1988, 11, 26) ], // Sat
+ [ "2000-W52", Date.UTC(2000, 11, 25) ], // Sun
+ // Other normal cases.
+ [ "2015-W53", Date.UTC(2015, 11, 28) ],
+ [ "2016-W36", Date.UTC(2016, 8, 5) ],
+ [ "1970-W01", Date.UTC(1969, 11, 29) ],
+ [ "275760-W37", Date.UTC(275760, 8, 8) ],
+ ];
+
+ var invalidData =
+ [
+ "invalidweek",
+ "0000-W01",
+ "2016-W00",
+ "2016-W53",
+ // Out of range.
+ "275760-W38",
+ ];
+
+ var element = document.createElement('input');
+ element.type = "week";
+ for (let data of validData) {
+ dump("Test: " + data[0]);
+ element.value = data[0];
+ is(element.valueAsNumber, data[1], "valueAsNumber should return the " +
+ "integer value representing this week");
+ }
+
+ for (let data of invalidData) {
+ element.value = data;
+ ok(isNaN(element.valueAsNumber), "valueAsNumber should return NaN " +
+ "when the element value is not a valid week");
+ }
+}
+
+function checkWeekSet()
+{
+ var testData =
+ [
+ // Common years starting on different days of week.
+ [ Date.UTC(2007, 0, 1), "2007-W01" ], // Mon
+ [ Date.UTC(2013, 0, 1), "2013-W01" ], // Tue
+ [ Date.UTC(2014, 0, 1), "2014-W01" ], // Wed
+ [ Date.UTC(2015, 0, 1), "2015-W01" ], // Thu
+ [ Date.UTC(2010, 0, 1), "2009-W53" ], // Fri
+ [ Date.UTC(2011, 0, 1), "2010-W52" ], // Sat
+ [ Date.UTC(2017, 0, 1), "2016-W52" ], // Sun
+ // Common years ending on different days of week.
+ [ Date.UTC(2007, 11, 31), "2008-W01" ], // Mon
+ [ Date.UTC(2013, 11, 31), "2014-W01" ], // Tue
+ [ Date.UTC(2014, 11, 31), "2015-W01" ], // Wed
+ [ Date.UTC(2015, 11, 31), "2015-W53" ], // Thu
+ [ Date.UTC(2010, 11, 31), "2010-W52" ], // Fri
+ [ Date.UTC(2011, 11, 31), "2011-W52" ], // Sat
+ [ Date.UTC(2017, 11, 31), "2017-W52" ], // Sun
+ // Leap years starting on different days of week.
+ [ Date.UTC(1996, 0, 1), "1996-W01" ], // Mon
+ [ Date.UTC(2008, 0, 1), "2008-W01" ], // Tue
+ [ Date.UTC(2020, 0, 1), "2020-W01" ], // Wed
+ [ Date.UTC(2004, 0, 1), "2004-W01" ], // Thu
+ [ Date.UTC(2016, 0, 1), "2015-W53" ], // Fri
+ [ Date.UTC(2000, 0, 1), "1999-W52" ], // Sat
+ [ Date.UTC(2012, 0, 1), "2011-W52" ], // Sun
+ // Leap years ending on different days of week.
+ [ Date.UTC(2012, 11, 31), "2013-W01" ], // Mon
+ [ Date.UTC(2024, 11, 31), "2025-W01" ], // Tue
+ [ Date.UTC(1980, 11, 31), "1981-W01" ], // Wed
+ [ Date.UTC(1992, 11, 31), "1992-W53" ], // Thu
+ [ Date.UTC(2004, 11, 31), "2004-W53" ], // Fri
+ [ Date.UTC(1988, 11, 31), "1988-W52" ], // Sat
+ [ Date.UTC(2000, 11, 31), "2000-W52" ], // Sun
+ // Other normal cases.
+ [ Date.UTC(2008, 8, 26), "2008-W39" ],
+ [ Date.UTC(2016, 0, 4), "2016-W01" ],
+ [ Date.UTC(2016, 0, 10), "2016-W01" ],
+ [ Date.UTC(2016, 0, 11), "2016-W02" ],
+ // Maximum valid week (limited by the ecma date object range).
+ [ 8640000000000000, "275760-W37" ],
+ // Minimum valid week (limited by the input element minimum valid value)
+ [ -62135596800000, "0001-W01" ],
+ // "Values must be truncated to valid weeks"
+ [ 0.3, "1970-W01" ],
+ [ 1e-1, "1970-W01" ],
+ [ -1.1, "1970-W01" ],
+ [ -345600000, "1969-W52" ],
+ // Invalid numbers.
+ // Those are implicitly converted to numbers
+ [ "", "1970-W01" ],
+ [ true, "1970-W01" ],
+ [ false, "1970-W01" ],
+ [ null, "1970-W01" ],
+ // Those are converted to NaN, the corresponding week string is the empty string
+ [ "invalidweek", "" ],
+ [ NaN, "" ],
+ [ undefined, "" ],
+ // Infinity will keep the current value and throw (so we need to set a current value).
+ [ Date.UTC(2016, 8, 8), "2016-W36" ],
+ [ Infinity, "2016-W36", true ],
+ [ -Infinity, "2016-W36", true ],
+ ];
+
+ var element = document.createElement('input');
+ element.type = "week";
+ for (let data of testData) {
+ var caught = false;
+
+ try {
+ element.valueAsNumber = data[0];
+ is(element.value, data[1], "valueAsNumber should set the value to " + data[1]);
+ } catch(e) {
+ caught = true;
+ }
+
+ if (data[2]) {
+ ok(caught, "valueAsNumber should have thrown");
+ is(element.value, data[1], "the value should not have changed");
+ } else {
+ ok(!caught, "valueAsNumber should not have thrown");
+ }
+ }
+}
+
+checkAvailability();
+
+// <input type='number'> test
+checkNumberGet();
+checkNumberSet();
+
+// <input type='range'> test
+checkRangeGet();
+checkRangeSet();
+
+// <input type='date'> test
+checkDateGet();
+checkDateSet();
+
+// <input type='time'> test
+checkTimeGet();
+checkTimeSet();
+
+// <input type='month'> test
+checkMonthGet();
+checkMonthSet();
+
+// <input type='week'> test
+checkWeekGet();
+checkWeekSet();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/head.js b/dom/html/test/head.js
new file mode 100644
index 000000000..7f5db315e
--- /dev/null
+++ b/dom/html/test/head.js
@@ -0,0 +1,54 @@
+function pushPrefs(...aPrefs) {
+ return new Promise(resolve => {
+ SpecialPowers.pushPrefEnv({"set": aPrefs}, resolve);
+ });
+}
+
+function promiseWaitForEvent(object, eventName, capturing = false, chrome = false) {
+ return new Promise((resolve) => {
+ function listener(event) {
+ info("Saw " + eventName);
+ object.removeEventListener(eventName, listener, capturing, chrome);
+ resolve(event);
+ }
+
+ info("Waiting for " + eventName);
+ object.addEventListener(eventName, listener, capturing, chrome);
+ });
+}
+
+/**
+ * Waits for the next load to complete in any browser or the given browser.
+ * If a <tabbrowser> is given it waits for a load in any of its browsers.
+ *
+ * @return promise
+ */
+function waitForDocLoadComplete(aBrowser=gBrowser) {
+ return new Promise(resolve => {
+ let listener = {
+ onStateChange: function (webProgress, req, flags, status) {
+ let docStop = Ci.nsIWebProgressListener.STATE_IS_NETWORK |
+ Ci.nsIWebProgressListener.STATE_STOP;
+ info("Saw state " + flags.toString(16) + " and status " + status.toString(16));
+ // When a load needs to be retargetted to a new process it is cancelled
+ // with NS_BINDING_ABORTED so ignore that case
+ if ((flags & docStop) == docStop && status != Cr.NS_BINDING_ABORTED) {
+ aBrowser.removeProgressListener(this);
+ waitForDocLoadComplete.listeners.delete(this);
+ let chan = req.QueryInterface(Ci.nsIChannel);
+ info("Browser loaded " + chan.originalURI.spec);
+ resolve();
+ }
+ },
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
+ Ci.nsISupportsWeakReference])
+ };
+ aBrowser.addProgressListener(listener);
+ waitForDocLoadComplete.listeners.add(listener);
+ info("Waiting for browser load");
+ });
+}
+// Keep a set of progress listeners for waitForDocLoadComplete() to make sure
+// they're not GC'ed before we saw the page load.
+waitForDocLoadComplete.listeners = new Set();
+registerCleanupFunction(() => waitForDocLoadComplete.listeners.clear());
diff --git a/dom/html/test/image-allow-credentials.png b/dom/html/test/image-allow-credentials.png
new file mode 100644
index 000000000..df24ac6d3
--- /dev/null
+++ b/dom/html/test/image-allow-credentials.png
Binary files differ
diff --git a/dom/html/test/image-allow-credentials.png^headers^ b/dom/html/test/image-allow-credentials.png^headers^
new file mode 100644
index 000000000..a03f99a9c
--- /dev/null
+++ b/dom/html/test/image-allow-credentials.png^headers^
@@ -0,0 +1,2 @@
+Access-Control-Allow-Origin: http://mochi.test:8888
+Access-Control-Allow-Credentials: true
diff --git a/dom/html/test/image.png b/dom/html/test/image.png
new file mode 100644
index 000000000..d26878c9f
--- /dev/null
+++ b/dom/html/test/image.png
Binary files differ
diff --git a/dom/html/test/imports/file_CSP_sandbox.html b/dom/html/test/imports/file_CSP_sandbox.html
new file mode 100644
index 000000000..72d3bbeb3
--- /dev/null
+++ b/dom/html/test/imports/file_CSP_sandbox.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<head>
+</head>
+<body>
+ <link rel="import" href="file_CSP_sandbox_import.html" id="import"></link>
+</body>
+
diff --git a/dom/html/test/imports/file_CSP_sandbox_import.html b/dom/html/test/imports/file_CSP_sandbox_import.html
new file mode 100644
index 000000000..33f88aecc
--- /dev/null
+++ b/dom/html/test/imports/file_CSP_sandbox_import.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<head>
+</head>
+<body>
+<script>
+ var scriptExecuted = true;
+</script>
+</body>
+
diff --git a/dom/html/test/imports/file_blocking_DOMContentLoaded_A.html b/dom/html/test/imports/file_blocking_DOMContentLoaded_A.html
new file mode 100644
index 000000000..2a18604ed
--- /dev/null
+++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_A.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <script>
+ order.push("AS0");
+ </script>
+ <link rel="import" href="file_blocking_DOMContentLoaded_B.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_blocking_DOMContentLoaded_B.html b/dom/html/test/imports/file_blocking_DOMContentLoaded_B.html
new file mode 100644
index 000000000..a69a38d16
--- /dev/null
+++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_B.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <script>
+ order.push("BS0");
+ </script>
+ <link rel="import" href="file_blocking_DOMContentLoaded_C.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_blocking_DOMContentLoaded_C.html b/dom/html/test/imports/file_blocking_DOMContentLoaded_C.html
new file mode 100644
index 000000000..76719b1b2
--- /dev/null
+++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_C.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <script>
+ order.push("CS0");
+ </script>
+ <link rel="import" href="file_blocking_DOMContentLoaded_D.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_blocking_DOMContentLoaded_D.html b/dom/html/test/imports/file_blocking_DOMContentLoaded_D.html
new file mode 100644
index 000000000..0ae10e702
--- /dev/null
+++ b/dom/html/test/imports/file_blocking_DOMContentLoaded_D.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <script>
+ order.push("DS0");
+ </script>
+</head>
+<body>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_1_A.html b/dom/html/test/imports/file_cycle_1_A.html
new file mode 100644
index 000000000..17f2499d9
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_1_A.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_1_B.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("A");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_1_B.html b/dom/html/test/imports/file_cycle_1_B.html
new file mode 100644
index 000000000..a7d77c823
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_1_B.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_1_C.html" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="file_cycle_1_A.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("B");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_1_C.html b/dom/html/test/imports/file_cycle_1_C.html
new file mode 100644
index 000000000..0c563c6ce
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_1_C.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_1_B.html" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="file_cycle_1_A.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("C");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_2_A.html b/dom/html/test/imports/file_cycle_2_A.html
new file mode 100644
index 000000000..5e4b6bfd3
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_2_A.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_2_B.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("A");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_2_B.html b/dom/html/test/imports/file_cycle_2_B.html
new file mode 100644
index 000000000..ed5c4acf6
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_2_B.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_2_A.html" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="file_cycle_2_C.html" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="file_cycle_2_D.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("B");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_2_C.html b/dom/html/test/imports/file_cycle_2_C.html
new file mode 100644
index 000000000..4492c068a
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_2_C.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+</head>
+<body>
+ <script>
+ order.push("C");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_2_D.html b/dom/html/test/imports/file_cycle_2_D.html
new file mode 100644
index 000000000..eae5280e0
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_2_D.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+</head>
+<body>
+ <script>
+ order.push("D");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_3_A.html b/dom/html/test/imports/file_cycle_3_A.html
new file mode 100644
index 000000000..bc2a31d1c
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_3_A.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_3_C.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("A");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_3_B.html b/dom/html/test/imports/file_cycle_3_B.html
new file mode 100644
index 000000000..19d51a6ed
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_3_B.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_3_C.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("B");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_3_C.html b/dom/html/test/imports/file_cycle_3_C.html
new file mode 100644
index 000000000..4b391c683
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_3_C.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_3_A.html" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="file_cycle_3_B.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("C");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_4_A.html b/dom/html/test/imports/file_cycle_4_A.html
new file mode 100644
index 000000000..0668bdf80
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_4_A.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_4_B.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("A");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_4_B.html b/dom/html/test/imports/file_cycle_4_B.html
new file mode 100644
index 000000000..596e5c3e7
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_4_B.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_4_C.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("B");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_4_C.html b/dom/html/test/imports/file_cycle_4_C.html
new file mode 100644
index 000000000..7c676e85c
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_4_C.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_4_D.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("C");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_4_D.html b/dom/html/test/imports/file_cycle_4_D.html
new file mode 100644
index 000000000..31ae5de32
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_4_D.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_4_B.html" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="file_cycle_4_E.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("D");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_cycle_4_E.html b/dom/html/test/imports/file_cycle_4_E.html
new file mode 100644
index 000000000..42cd3c296
--- /dev/null
+++ b/dom/html/test/imports/file_cycle_4_E.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+ <link rel="import" href="file_cycle_4_C.html" onload="loaded()" onerror="failed()"></link>
+</head>
+<body>
+ <script>
+ order.push("E");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_element_upgrade.html b/dom/html/test/imports/file_element_upgrade.html
new file mode 100644
index 000000000..b41bd0a42
--- /dev/null
+++ b/dom/html/test/imports/file_element_upgrade.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en-US">
+<head>
+</head>
+<body>
+ <x-foo></x-foo>
+ <script>
+ var prototype = Object.create(HTMLElement.prototype);
+ prototype.createdCallback = function() {
+ createdCallbackCalled = true;
+ }
+ document.registerElement('x-foo', {prototype: prototype});
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/file_encoding.html b/dom/html/test/imports/file_encoding.html
new file mode 100644
index 000000000..d97bb0437
--- /dev/null
+++ b/dom/html/test/imports/file_encoding.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<head>
+<meta charset="EUC-KR">
+</head>
+<body>Ignore my encoding</body> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importA1.html b/dom/html/test/imports/file_importA1.html
new file mode 100644
index 000000000..ecce6f061
--- /dev/null
+++ b/dom/html/test/imports/file_importA1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importA2.html" id="A2" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("A1");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importA2.html b/dom/html/test/imports/file_importA2.html
new file mode 100644
index 000000000..d03e80a4b
--- /dev/null
+++ b/dom/html/test/imports/file_importA2.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ </head>
+ <body>
+ <script>
+ order.push("A2");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importB1.html b/dom/html/test/imports/file_importB1.html
new file mode 100644
index 000000000..82fb55f9f
--- /dev/null
+++ b/dom/html/test/imports/file_importB1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importB2.html" id="B2" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("B1");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importB2.html b/dom/html/test/imports/file_importB2.html
new file mode 100644
index 000000000..01b6cc215
--- /dev/null
+++ b/dom/html/test/imports/file_importB2.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ </head>
+ <body>
+ <script>
+ order.push("B2");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importC1.html b/dom/html/test/imports/file_importC1.html
new file mode 100644
index 000000000..9ac117e65
--- /dev/null
+++ b/dom/html/test/imports/file_importC1.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importC2.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("C1");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importC10.html b/dom/html/test/imports/file_importC10.html
new file mode 100644
index 000000000..801d0f085
--- /dev/null
+++ b/dom/html/test/imports/file_importC10.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importE.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("C10");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importC2.html b/dom/html/test/imports/file_importC2.html
new file mode 100644
index 000000000..f0193be44
--- /dev/null
+++ b/dom/html/test/imports/file_importC2.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importC3.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("C2");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importC3.html b/dom/html/test/imports/file_importC3.html
new file mode 100644
index 000000000..eb942b707
--- /dev/null
+++ b/dom/html/test/imports/file_importC3.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importC4.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("C3");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importC4.html b/dom/html/test/imports/file_importC4.html
new file mode 100644
index 000000000..5a172772a
--- /dev/null
+++ b/dom/html/test/imports/file_importC4.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importC5.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("C4");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importC5.html b/dom/html/test/imports/file_importC5.html
new file mode 100644
index 000000000..c29dc24ba
--- /dev/null
+++ b/dom/html/test/imports/file_importC5.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importC6.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("C5");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importC6.html b/dom/html/test/imports/file_importC6.html
new file mode 100644
index 000000000..a53b62bb4
--- /dev/null
+++ b/dom/html/test/imports/file_importC6.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importC7.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("C6");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importC7.html b/dom/html/test/imports/file_importC7.html
new file mode 100644
index 000000000..1c7d60114
--- /dev/null
+++ b/dom/html/test/imports/file_importC7.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importC8.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("C7");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importC8.html b/dom/html/test/imports/file_importC8.html
new file mode 100644
index 000000000..04bef617d
--- /dev/null
+++ b/dom/html/test/imports/file_importC8.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importC9.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("C8");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importC9.html b/dom/html/test/imports/file_importC9.html
new file mode 100644
index 000000000..1a2749755
--- /dev/null
+++ b/dom/html/test/imports/file_importC9.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importC10.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("C9");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importD.html b/dom/html/test/imports/file_importD.html
new file mode 100644
index 000000000..a4fbda536
--- /dev/null
+++ b/dom/html/test/imports/file_importD.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <body>
+ <script>
+ order.push("D");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_importE.html b/dom/html/test/imports/file_importE.html
new file mode 100644
index 000000000..6a8792acf
--- /dev/null
+++ b/dom/html/test/imports/file_importE.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en-US">
+ <head>
+ <link rel="import" href="file_importD.html" onload="loaded()" onerror="failed()"></link>
+ </head>
+ <body>
+ <script>
+ order.push("E");
+ </script>
+ </body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/file_simple_import.html b/dom/html/test/imports/file_simple_import.html
new file mode 100644
index 000000000..d9358bc38
--- /dev/null
+++ b/dom/html/test/imports/file_simple_import.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<head>
+</head>
+<body>Simple import</body> \ No newline at end of file
diff --git a/dom/html/test/imports/mochitest.ini b/dom/html/test/imports/mochitest.ini
new file mode 100644
index 000000000..88ad3a6f5
--- /dev/null
+++ b/dom/html/test/imports/mochitest.ini
@@ -0,0 +1,52 @@
+[DEFAULT]
+support-files =
+ file_importA1.html
+ file_importA2.html
+ file_importB1.html
+ file_importB2.html
+ file_importC1.html
+ file_importC2.html
+ file_importC3.html
+ file_importC4.html
+ file_importC5.html
+ file_importC6.html
+ file_importC7.html
+ file_importC8.html
+ file_importC9.html
+ file_importC10.html
+ file_importD.html
+ file_importE.html
+ file_cycle_1_A.html
+ file_cycle_1_B.html
+ file_cycle_1_C.html
+ file_cycle_2_A.html
+ file_cycle_2_B.html
+ file_cycle_2_C.html
+ file_cycle_2_D.html
+ file_cycle_3_A.html
+ file_cycle_3_B.html
+ file_cycle_3_C.html
+ file_cycle_4_A.html
+ file_cycle_4_B.html
+ file_cycle_4_C.html
+ file_cycle_4_D.html
+ file_cycle_4_E.html
+ file_encoding.html
+ file_simple_import.html
+ file_blocking_DOMContentLoaded_A.html
+ file_blocking_DOMContentLoaded_B.html
+ file_blocking_DOMContentLoaded_C.html
+ file_blocking_DOMContentLoaded_D.html
+ file_element_upgrade.html
+ file_CSP_sandbox.html
+ file_CSP_sandbox_import.html
+
+[test_cycle_1.html]
+[test_cycle_2.html]
+[test_cycle_3.html]
+[test_cycle_4.html]
+[test_blocking_DOMContentLoaded.html]
+[test_encoding.html]
+[test_defaultView.html]
+[test_element_upgrade.html]
+[test_CSP_sandbox.html]
diff --git a/dom/html/test/imports/test_CSP_sandbox.html b/dom/html/test/imports/test_CSP_sandbox.html
new file mode 100644
index 000000000..c1df21289
--- /dev/null
+++ b/dom/html/test/imports/test_CSP_sandbox.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1106713
+-->
+<head>
+ <title>Test for Bug 1106713</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1106713">Mozilla Bug 1106713</a>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ function go() {
+ var ifr = document.getElementById('iframe1').contentWindow;
+ ok(!ifr.scriptExecuted, "script is not allowed to run");
+ SimpleTest.finish();
+ }
+
+ </script>
+ <iframe src='file_CSP_sandbox.html' sandbox="allow-same-origin" onload="go()" id="iframe1"></iframe>
+</body>
+</html>
+
diff --git a/dom/html/test/imports/test_blocking_DOMContentLoaded.html b/dom/html/test/imports/test_blocking_DOMContentLoaded.html
new file mode 100644
index 000000000..9fa32e5ca
--- /dev/null
+++ b/dom/html/test/imports/test_blocking_DOMContentLoaded.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1093028
+-->
+<head>
+ <title>Test for Bug 1093028</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1093028">Mozilla Bug 1093028</a>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var counter = 0;
+ var fcounter = 0;
+ var order = [];
+ function loaded() {
+ counter++;
+ }
+ function failed() {
+ fcounter++;
+ }
+ </script>
+ <link rel="import" href="file_blocking_DOMContentLoaded_A.html" onload="loaded()" onerror="failed()"></link>
+ <script type="text/javascript">
+ is(counter, 4, "Imports are loaded");
+ is(fcounter, 0, "No error in imports");
+ var expected = ["AS0","BS0","CS0","DS0"];
+ for (i in expected)
+ is(order[i], expected[i], "import " + i + " should be " + expected[i]);
+ SimpleTest.finish();
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/test_cycle_1.html b/dom/html/test/imports/test_cycle_1.html
new file mode 100644
index 000000000..5d170a7de
--- /dev/null
+++ b/dom/html/test/imports/test_cycle_1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1061469
+-->
+<head>
+ <title>Test for Bug 1061469</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var counter = 0;
+ var fcounter = 0;
+ var order = [];
+ function loaded() {
+ counter++;
+ }
+ function failed() {
+ fcounter++;
+ }
+ </script>
+ <link rel="import" href="file_cycle_1_A.html" onload="loaded()" onerror="failed()"></link>
+ <script type="text/javascript">
+ is(counter, 6, "Imports are loaded");
+ is(fcounter, 0, "No error in imports");
+ var expected = ["C","B","A"];
+ for (i in expected)
+ is(order[i], expected[i], "import " + i + " should be " + expected[i]);
+ SimpleTest.finish();
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/test_cycle_2.html b/dom/html/test/imports/test_cycle_2.html
new file mode 100644
index 000000000..23daa5953
--- /dev/null
+++ b/dom/html/test/imports/test_cycle_2.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1061469
+-->
+<head>
+ <title>Test for Bug 1061469</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var counter = 0;
+ var fcounter = 0;
+ var order = [];
+ function loaded() {
+ counter++;
+ }
+ function failed() {
+ fcounter++;
+ }
+ </script>
+ <link rel="import" href="file_cycle_2_A.html" onload="loaded()" onerror="failed()"></link>
+ <script type="text/javascript">
+ is(counter, 5, "Imports are loaded");
+ is(fcounter, 0, "No error in imports");
+ var expected = ["C","D","B","A"];
+ for (i in expected)
+ is(order[i], expected[i], "import " + i + " should be " + expected[i]);
+ SimpleTest.finish();
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/test_cycle_3.html b/dom/html/test/imports/test_cycle_3.html
new file mode 100644
index 000000000..8db664601
--- /dev/null
+++ b/dom/html/test/imports/test_cycle_3.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1061469
+-->
+<head>
+ <title>Test for Bug 1061469</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var counter = 0;
+ var fcounter = 0;
+ var order = [];
+ function loaded() {
+ counter++;
+ }
+ function failed() {
+ fcounter++;
+ }
+ </script>
+ <link rel="import" href="file_cycle_3_A.html" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="file_cycle_3_B.html" onload="loaded()" onerror="failed()"></link>
+ <script type="text/javascript">
+ is(counter, 6, "Imports are loaded");
+ is(fcounter, 0, "No error in imports");
+ var expected = ["B","C","A"];
+ for (i in expected)
+ is(order[i], expected[i], "import " + i + " should be " + expected[i]);
+ SimpleTest.finish();
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/test_cycle_4.html b/dom/html/test/imports/test_cycle_4.html
new file mode 100644
index 000000000..441ffbac8
--- /dev/null
+++ b/dom/html/test/imports/test_cycle_4.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1061469
+-->
+<head>
+ <title>Test for Bug 1061469</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var counter = 0;
+ var fcounter = 0;
+ var order = [];
+ function loaded() {
+ counter++;
+ }
+ function failed() {
+ fcounter++;
+ }
+ </script>
+ <link rel="import" href="file_cycle_4_A.html" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="file_cycle_4_D.html" onload="loaded()" onerror="failed()"></link>
+ <script type="text/javascript">
+ is(counter, 8, "Imports are loaded");
+ is(fcounter, 0, "No error in imports");
+ var expected = ["E","D","C","B","A"];
+ for (i in expected)
+ is(order[i], expected[i], "import " + i + " should be " + expected[i]);
+ SimpleTest.finish();
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/test_defaultView.html b/dom/html/test/imports/test_defaultView.html
new file mode 100644
index 000000000..5f9c02bd8
--- /dev/null
+++ b/dom/html/test/imports/test_defaultView.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1061469
+-->
+<head>
+ <title>Test for Bug 1061469</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var success = false;
+ function loaded() {
+ success = true;
+ }
+ function failed() {
+ ok(false, "Import loading failed");
+ }
+ </script>
+ <link rel="import" href="file_simple_import.html" id="import" onload="loaded()" onerror="failed()"></link>
+ <script type="text/javascript">
+ document.defaultView;
+ is(document.getElementById("import").import.defaultView, null, "defaultView is always null for imports");
+ SimpleTest.finish();
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/imports/test_element_upgrade.html b/dom/html/test/imports/test_element_upgrade.html
new file mode 100644
index 000000000..006d56d35
--- /dev/null
+++ b/dom/html/test/imports/test_element_upgrade.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1081107
+-->
+<head>
+ <title>Test for Bug 1081107</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1081107">Mozilla Bug 1081107</a>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var counter = 0;
+ var fcounter = 0;
+ var createdCallbackCalled = false;
+ function loaded() {
+ counter++;
+ }
+ function failed() {
+ fcounter++;
+ }
+ </script>
+ <link rel="import" href="file_element_upgrade.html" onload="loaded()" onerror="failed()"></link>
+ <script type="text/javascript">
+ is(counter, 1, "Imports are loaded");
+ is(fcounter, 0, "No error in imports");
+ ok(createdCallbackCalled, "custom element in import has been upgraded");
+ SimpleTest.finish();
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/imports/test_encoding.html b/dom/html/test/imports/test_encoding.html
new file mode 100644
index 000000000..fa4033f20
--- /dev/null
+++ b/dom/html/test/imports/test_encoding.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1061469
+-->
+<head>
+ <title>Test for Bug 1061469</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1061469">Mozilla Bug 1061469</a>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var success = false;
+ function loaded() {
+ success = true;
+ }
+ function failed() {
+ ok(false, "Import loading failed");
+ }
+ </script>
+ <link rel="import" href="file_encoding.html" id="import" onload="loaded()" onerror="failed()"></link>
+ <script type="text/javascript">
+ is(document.getElementById("import").import.characterSet, "UTF-8", "characterSet should be UTF-8 for imports");
+ SimpleTest.finish();
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/mochitest.ini b/dom/html/test/mochitest.ini
new file mode 100644
index 000000000..99b425df8
--- /dev/null
+++ b/dom/html/test/mochitest.ini
@@ -0,0 +1,608 @@
+[DEFAULT]
+support-files =
+ 347174transform.xsl
+ 347174transformable.xml
+ allowMedia.sjs
+ bug100533_iframe.html
+ bug100533_load.html
+ bug196523-subframe.html
+ bug199692-nested-d2.html
+ bug199692-nested.html
+ bug199692-popup.html
+ bug199692-scrolled.html
+ bug242709_iframe.html
+ bug242709_load.html
+ bug277724_iframe1.html
+ bug277724_iframe2.xhtml
+ bug277890_iframe.html
+ bug277890_load.html
+ bug340800_iframe.txt
+ bug369370-popup.png
+ bug372098-link-target.html
+ bug392567.jar
+ bug392567.jar^headers^
+ bug441930_iframe.html
+ bug445004-inner.html
+ bug445004-inner.js
+ bug445004-outer-abs.html
+ bug445004-outer-rel.html
+ bug445004-outer-write.html
+ bug446483-iframe.html
+ bug448564-echo.sjs
+ bug448564-iframe-1.html
+ bug448564-iframe-2.html
+ bug448564-iframe-3.html
+ bug448564-submit.js
+ bug499092.html
+ bug499092.xml
+ bug514856_iframe.html
+ bug1260704_iframe.html
+ bug1260704_iframe_empty.html
+ bug1292522_iframe.html
+ bug1292522_page.html
+ bug1315146-iframe.html
+ bug1315146-main.html
+ ../../plugins/test/mochitest/plugin-utils.js
+ test_non-ascii-cookie.html^headers^
+ file_bug209275_1.html
+ file_bug209275_2.html
+ file_bug209275_3.html
+ file_bug297761.html
+ file_bug417760.png
+ file_bug893537.html
+ file_bug1260704.png
+ file_formSubmission_img.jpg
+ file_formSubmission_text.txt
+ file_fullscreen-api.html
+ file_fullscreen-backdrop.html
+ file_fullscreen-denied-inner.html
+ file_fullscreen-denied.html
+ file_fullscreen-esc-exit-inner.html
+ file_fullscreen-esc-exit.html
+ file_fullscreen-hidden.html
+ file_fullscreen-lenient-setters.html
+ file_fullscreen-multiple-inner.html
+ file_fullscreen-multiple.html
+ file_fullscreen-navigation.html
+ file_fullscreen-nested.html
+ file_fullscreen-prefixed.html
+ file_fullscreen-plugins.html
+ file_fullscreen-rollback.html
+ file_fullscreen-scrollbar.html
+ file_fullscreen-selector.html
+ file_fullscreen-svg-element.html
+ file_fullscreen-top-layer.html
+ file_fullscreen-unprefix-disabled-inner.html
+ file_fullscreen-unprefix-disabled.html
+ file_fullscreen-utils.js
+ file_iframe_sandbox_a_if1.html
+ file_iframe_sandbox_a_if10.html
+ file_iframe_sandbox_a_if11.html
+ file_iframe_sandbox_a_if12.html
+ file_iframe_sandbox_a_if13.html
+ file_iframe_sandbox_a_if14.html
+ file_iframe_sandbox_a_if15.html
+ file_iframe_sandbox_a_if16.html
+ file_iframe_sandbox_a_if17.html
+ file_iframe_sandbox_a_if18.html
+ file_iframe_sandbox_a_if19.html
+ file_iframe_sandbox_a_if2.html
+ file_iframe_sandbox_a_if3.html
+ file_iframe_sandbox_a_if4.html
+ file_iframe_sandbox_a_if5.html
+ file_iframe_sandbox_a_if6.html
+ file_iframe_sandbox_a_if7.html
+ file_iframe_sandbox_a_if8.html
+ file_iframe_sandbox_a_if9.html
+ file_iframe_sandbox_b_if1.html
+ file_iframe_sandbox_b_if2.html
+ file_iframe_sandbox_b_if3.html
+ file_iframe_sandbox_c_if1.html
+ file_iframe_sandbox_c_if2.html
+ file_iframe_sandbox_c_if3.html
+ file_iframe_sandbox_c_if4.html
+ file_iframe_sandbox_c_if5.html
+ file_iframe_sandbox_c_if6.html
+ file_iframe_sandbox_c_if7.html
+ file_iframe_sandbox_c_if8.html
+ file_iframe_sandbox_c_if9.html
+ file_iframe_sandbox_close.html
+ file_iframe_sandbox_d_if1.html
+ file_iframe_sandbox_d_if10.html
+ file_iframe_sandbox_d_if11.html
+ file_iframe_sandbox_d_if12.html
+ file_iframe_sandbox_d_if13.html
+ file_iframe_sandbox_d_if14.html
+ file_iframe_sandbox_d_if15.html
+ file_iframe_sandbox_d_if16.html
+ file_iframe_sandbox_d_if17.html
+ file_iframe_sandbox_d_if18.html
+ file_iframe_sandbox_d_if19.html
+ file_iframe_sandbox_d_if2.html
+ file_iframe_sandbox_d_if20.html
+ file_iframe_sandbox_d_if21.html
+ file_iframe_sandbox_d_if22.html
+ file_iframe_sandbox_d_if23.html
+ file_iframe_sandbox_d_if3.html
+ file_iframe_sandbox_d_if4.html
+ file_iframe_sandbox_d_if5.html
+ file_iframe_sandbox_d_if6.html
+ file_iframe_sandbox_d_if7.html
+ file_iframe_sandbox_d_if8.html
+ file_iframe_sandbox_d_if9.html
+ file_iframe_sandbox_e_if1.html
+ file_iframe_sandbox_e_if10.html
+ file_iframe_sandbox_e_if11.html
+ file_iframe_sandbox_e_if12.html
+ file_iframe_sandbox_e_if13.html
+ file_iframe_sandbox_e_if14.html
+ file_iframe_sandbox_e_if15.html
+ file_iframe_sandbox_e_if16.html
+ file_iframe_sandbox_e_if2.html
+ file_iframe_sandbox_e_if3.html
+ file_iframe_sandbox_e_if4.html
+ file_iframe_sandbox_e_if5.html
+ file_iframe_sandbox_e_if6.html
+ file_iframe_sandbox_e_if7.html
+ file_iframe_sandbox_e_if8.html
+ file_iframe_sandbox_e_if9.html
+ file_iframe_sandbox_f_if1.html
+ file_iframe_sandbox_f_if2.html
+ file_iframe_sandbox_f_if2.html^headers^
+ file_iframe_sandbox_fail.js
+ file_iframe_sandbox_form_fail.html
+ file_iframe_sandbox_form_pass.html
+ file_iframe_sandbox_g_if1.html
+ file_iframe_sandbox_h_if1.html
+ file_iframe_sandbox_j_if1.html
+ file_iframe_sandbox_j_if2.html
+ file_iframe_sandbox_j_if3.html
+ file_iframe_sandbox_k_if1.html
+ file_iframe_sandbox_k_if2.html
+ file_iframe_sandbox_k_if3.html
+ file_iframe_sandbox_k_if4.html
+ file_iframe_sandbox_k_if5.html
+ file_iframe_sandbox_k_if6.html
+ file_iframe_sandbox_k_if7.html
+ file_iframe_sandbox_k_if8.html
+ file_iframe_sandbox_k_if9.html
+ file_iframe_sandbox_navigation_fail.html
+ file_iframe_sandbox_navigation_pass.html
+ file_iframe_sandbox_navigation_start.html
+ file_iframe_sandbox_open_window_fail.html
+ file_iframe_sandbox_open_window_pass.html
+ file_iframe_sandbox_pass.js
+ file_iframe_sandbox_redirect.html
+ file_iframe_sandbox_redirect.html^headers^
+ file_iframe_sandbox_redirect_target.html
+ file_iframe_sandbox_refresh.html
+ file_iframe_sandbox_refresh.html^headers^
+ file_iframe_sandbox_top_navigation_fail.html
+ file_iframe_sandbox_top_navigation_pass.html
+ file_iframe_sandbox_window_form_fail.html
+ file_iframe_sandbox_window_form_pass.html
+ file_iframe_sandbox_window_navigation_fail.html
+ file_iframe_sandbox_window_navigation_pass.html
+ file_iframe_sandbox_window_top_navigation_pass.html
+ file_iframe_sandbox_window_top_navigation_fail.html
+ file_iframe_sandbox_worker.js
+ file_imports_basics.html
+ file_imports_redirect.html
+ file_imports_redirect.html^headers^
+ file_imports_redirected.html
+ file_srcdoc-2.html
+ file_srcdoc.html
+ file_window_open_close_outer.html
+ file_window_open_close_inner.html
+ formSubmission_chrome.js
+ form_submit_server.sjs
+ formData_worker.js
+ formData_test.js
+ image.png
+ image-allow-credentials.png
+ image-allow-credentials.png^headers^
+ nnc_lockup.gif
+ reflect.js
+ file_ignoreuserfocus.html
+ simpleFileOpener.js
+ file_mozaudiochannel.html
+ file_bug1166138_1x.png
+ file_bug1166138_2x.png
+ file_bug1166138_def.png
+
+[test_a_text.html]
+[test_anchor_href_cache_invalidation.html]
+[test_applet_attributes_reflection.html]
+[test_base_attributes_reflection.html]
+[test_bug100533.html]
+[test_bug109445.html]
+[test_bug109445.xhtml]
+[test_bug1297.html]
+[test_bug1366.html]
+[test_bug1400.html]
+[test_bug143220.html]
+[test_bug182279.html]
+[test_bug2082.html]
+[test_bug209275.xhtml]
+skip-if = toolkit == 'android' #TIMED_OUT
+[test_bug237071.html]
+[test_bug242709.html]
+[test_bug24958.html]
+[test_bug274626.html]
+[test_bug277724.html]
+[test_bug277890.html]
+[test_bug287465.html]
+[test_bug295561.html]
+[test_bug297761.html]
+[test_bug300691-1.html]
+[test_bug300691-2.html]
+[test_bug300691-3.xhtml]
+[test_bug330705-1.html]
+[test_bug332246.html]
+[test_bug332893-1.html]
+[test_bug332893-2.html]
+[test_bug332893-3.html]
+[test_bug332893-4.html]
+[test_bug332893-5.html]
+[test_bug332893-6.html]
+[test_bug332893-7.html]
+[test_bug3348.html]
+[test_bug340800.html]
+[test_bug347174.html]
+[test_bug347174_write.html]
+[test_bug347174_xsl.html]
+[test_bug347174_xslp.html]
+[test_bug353415-1.html]
+[test_bug353415-2.html]
+[test_bug371375.html]
+[test_bug372098.html]
+[test_bug373589.html]
+[test_bug375003-1.html]
+[test_bug375003-2.html]
+[test_bug377624.html]
+[test_bug383383.html]
+[test_bug383383_2.xhtml]
+[test_bug384419.html]
+[test_bug386496.html]
+[test_bug386728.html]
+[test_bug386996.html]
+[test_bug388558.html]
+[test_bug388746.html]
+[test_bug388794.html]
+[test_bug389797.html]
+[test_bug390975.html]
+[test_bug391994.html]
+[test_bug392567.html]
+[test_bug394700.html]
+[test_bug395107.html]
+[test_bug401160.xhtml]
+[test_bug405242.html]
+[test_bug406596.html]
+[test_bug417760.html]
+[test_bug421640.html]
+[test_bug424698.html]
+[test_bug428135.xhtml]
+[test_bug430351.html]
+[test_bug430392.html]
+[test_bug441930.html]
+[test_bug442801.html]
+[test_bug448166.html]
+[test_bug456229.html]
+[test_bug458037.xhtml]
+[test_bug460568.html]
+[test_bug481335.xhtml]
+skip-if = toolkit == 'android' #TIMED_OUT
+[test_bug500885.html]
+[test_bug514856.html]
+skip-if = toolkit == 'android'
+[test_bug518122.html]
+[test_bug519987.html]
+[test_bug523771.html]
+[test_bug529819.html]
+[test_bug529859.html]
+[test_bug535043.html]
+[test_bug536891.html]
+[test_bug536895.html]
+[test_bug546995.html]
+[test_bug547850.html]
+[test_bug551846.html]
+[test_bug555567.html]
+[test_bug556645.html]
+[test_bug557087-1.html]
+[test_bug557087-2.html]
+skip-if = toolkit == 'android' #TIMED_OUT
+[test_bug557087-3.html]
+[test_bug557087-4.html]
+[test_bug557087-5.html]
+[test_bug557087-6.html]
+[test_bug557620.html]
+[test_bug558788-1.html]
+[test_bug558788-2.html]
+[test_bug560112.html]
+[test_bug561634.html]
+[test_bug561636.html]
+[test_bug561640.html]
+[test_bug564001.html]
+[test_bug566046.html]
+[test_bug567938-1.html]
+[test_bug567938-2.html]
+[test_bug567938-3.html]
+[test_bug567938-4.html]
+[test_bug569955.html]
+[test_bug573969.html]
+[test_bug579079.html]
+[test_bug582412-1.html]
+[test_bug582412-2.html]
+[test_bug583514.html]
+[test_bug583533.html]
+[test_bug586763.html]
+[test_bug586786.html]
+[test_bug587469.html]
+[test_bug589.html]
+[test_bug590353-1.html]
+[test_bug590353-2.html]
+[test_bug590363.html]
+[test_bug592802.html]
+[test_bug593689.html]
+[test_bug595429.html]
+[test_bug595447.html]
+[test_bug595449.html]
+[test_bug596350.html]
+[test_bug596511.html]
+[test_bug598643.html]
+[test_bug598833-1.html]
+[test_bug600155.html]
+[test_bug601030.html]
+[test_bug605124-1.html]
+[test_bug605124-2.html]
+[test_bug605125-1.html]
+[test_bug605125-2.html]
+[test_bug606817.html]
+[test_bug607145.html]
+[test_bug610212.html]
+[test_bug610687.html]
+[test_bug611189.html]
+[test_bug612730.html]
+skip-if = toolkit == 'android' # form control not selected/checked with synthesizeMouse
+[test_bug613113.html]
+[test_bug613019.html]
+[test_bug613722.html]
+[test_bug613979.html]
+[test_bug615595.html]
+[test_bug615833.html]
+skip-if = toolkit == 'android' || os == 'mac' #TIMED_OUT # form control not selected/checked with synthesizeMouse, osx(bug 1275664)
+[test_bug617528.html]
+[test_bug618948.html]
+[test_bug619278.html]
+[test_bug622558.html]
+[test_bug622597.html]
+[test_bug623291.html]
+[test_bug6296.html]
+[test_bug629801.html]
+[test_bug633058.html]
+[test_bug636336.html]
+[test_bug641219.html]
+[test_bug643051.html]
+[test_bug646157.html]
+[test_bug649134.html]
+# This extra subdirectory is needed due to the nature of this test.
+# With the bug, the test loads the base URL of the bug649134/file_*.sjs
+# files, and the mochitest server responds with the contents of index.html if
+# it exists in that case, which we use to detect failure.
+# We cannot have index.html in this directory because it would prevent
+# running the tests here.
+support-files =
+ bug649134/file_bug649134-1.sjs
+ bug649134/file_bug649134-2.sjs
+ bug649134/index.html
+[test_bug651956.html]
+[test_bug658746.html]
+[test_bug659596.html]
+[test_bug659743.xml]
+[test_bug660663.html]
+[test_bug660959-1.html]
+[test_bug660959-2.html]
+[test_bug660959-3.html]
+[test_bug666200.html]
+[test_bug666666.html]
+[test_bug669012.html]
+[test_bug674558.html]
+[test_bug674927.html]
+[test_bug677463.html]
+[test_bug677658.html]
+[test_bug682886.html]
+[test_bug691.html]
+[test_bug694.html]
+[test_bug694503.html]
+[test_bug696.html]
+[test_bug717819.html]
+[test_bug742030.html]
+[test_bug742549.html]
+[test_bug745685.html]
+[test_bug763626.html]
+[test_bug780993.html]
+[test_bug787134.html]
+[test_bug797113.html]
+[test_bug803677.html]
+[test_bug821307.html]
+[test_bug827126.html]
+[test_bug838582.html]
+[test_bug839371.html]
+[test_bug839913.html]
+[test_bug841466.html]
+[test_bug845057.html]
+[test_bug869040.html]
+[test_bug870787.html]
+[test_bug874758.html]
+[test_bug879319.html]
+[test_bug885024.html]
+[test_bug893537.html]
+[test_bug95530.html]
+[test_bug969346.html]
+[test_bug982039.html]
+[test_bug1003539.html]
+[test_bug1045270.html]
+[test_bug1146116.html]
+[test_bug1264157.html]
+[test_bug1287321.html]
+[test_change_crossorigin.html]
+[test_checked.html]
+[test_dir_attributes_reflection.html]
+[test_dl_attributes_reflection.html]
+[test_element_prototype.html]
+[test_embed_attributes_reflection.html]
+[test_focusshift_button.html]
+[test_formData.html]
+[test_formSubmission.html]
+skip-if = toolkit == 'android' #TIMED_OUT
+[test_formSubmission2.html]
+skip-if = toolkit == 'android'
+[test_formelements.html]
+[test_fullscreen-api.html]
+tags = fullscreen
+skip-if = toolkit == 'android'
+[test_fullscreen-api-race.html]
+tags = fullscreen
+skip-if = toolkit == 'android' # just copy the conditions from the test above
+[test_hidden.html]
+[test_html_attributes_reflection.html]
+[test_htmlcollection.html]
+[test_iframe_sandbox_general.html]
+tags = openwindow
+[test_iframe_sandbox_inheritance.html]
+tags = openwindow
+[test_iframe_sandbox_modal.html]
+tags = openwindow
+skip-if = toolkit == 'android' || e10s #modal tests fail on android
+[test_iframe_sandbox_navigation.html]
+tags = openwindow
+[test_iframe_sandbox_navigation2.html]
+tags = openwindow
+[test_iframe_sandbox_plugins.html]
+skip-if = toolkit == 'android' # plugins not supported
+[test_iframe_sandbox_popups.html]
+tags = openwindow
+[test_iframe_sandbox_popups_inheritance.html]
+tags = openwindow
+skip-if = toolkit == 'android' # bug 939642
+[test_iframe_sandbox_redirect.html]
+[test_iframe_sandbox_refresh.html]
+[test_iframe_sandbox_same_origin.html]
+[test_iframe_sandbox_workers.html]
+[test_img_attributes_reflection.html]
+[test_imageSrcSet.html]
+[test_imports_basics.html]
+[test_imports_redirect.html]
+[test_imports_nonhttp.html]
+[test_imports_nested.html]
+[test_imports_nested_2.html]
+[test_li_attributes_reflection.html]
+[test_link_attributes_reflection.html]
+[test_link_sizes.html]
+[test_map_attributes_reflection.html]
+[test_meta_attributes_reflection.html]
+[test_mod_attributes_reflection.html]
+[test_mozaudiochannel.html]
+[test_named_options.html]
+[test_nested_invalid_fieldsets.html]
+[test_object_attributes_reflection.html]
+[test_object_plugin_nav.html]
+skip-if = toolkit == 'android' # plugins not supported
+[test_ol_attributes_reflection.html]
+[test_option_defaultSelected.html]
+[test_option_selected_state.html]
+[test_param_attributes_reflection.html]
+[test_q_attributes_reflection.html]
+[test_restore_from_parser_fragment.html]
+[test_rowscollection.html]
+[test_srcdoc-2.html]
+[test_srcdoc.html]
+[test_style_attributes_reflection.html]
+[test_track.html]
+[test_ul_attributes_reflection.html]
+[test_input_files_not_nsIFile.html]
+[test_ignoreuserfocus.html]
+[test_fragment_form_pointer.html]
+[test_bug1682.html]
+[test_bug1823.html]
+[test_bug57600.html]
+[test_bug196523.html]
+[test_bug199692.html]
+skip-if = toolkit == 'android' #bug 811644
+[test_bug172261.html]
+[test_bug255820.html]
+[test_bug259332.html]
+[test_bug311681.html]
+[test_bug311681.xhtml]
+[test_bug324378.html]
+[test_bug332848.xhtml]
+[test_bug340017.xhtml]
+[test_bug359657.html]
+[test_bug369370.html]
+skip-if = toolkit == "android" || toolkit == "windows" # disabled on Windows because of bug 1234520
+[test_bug380383.html]
+[test_bug391777.html]
+skip-if = toolkit == 'android' || e10s
+[test_bug402680.html]
+[test_bug403868.html]
+[test_bug403868.xhtml]
+[test_bug435128.html]
+skip-if = true # Disabled for timeouts.
+[test_bug463104.html]
+[test_form-parsing.html]
+[test_viewport.html]
+[test_documentAll.html]
+[test_document-element-inserted.html]
+[test_document.watch.html]
+[test_bug445004.html]
+skip-if = true || toolkit == 'android' # Disabled permanently (bug 559932).
+[test_bug446483.html]
+skip-if = toolkit == 'android'
+[test_bug448564.html]
+[test_bug478251.html]
+[test_bug481440.html]
+[test_bug481647.html]
+[test_bug482659.html]
+[test_bug486741.html]
+[test_bug489532.html]
+[test_bug497242.xhtml]
+[test_bug499092.html]
+[test_bug512367.html]
+[test_bug677495.html]
+[test_bug677495-1.html]
+[test_bug741266.html]
+skip-if = toolkit == "android" || toolkit == "windows" # Android: needs control of popup window size, windows(bug 1234520)
+[test_non-ascii-cookie.html]
+support-files = file_cookiemanager.js
+[test_bug765780.html]
+[test_bug871161.html]
+support-files = file_bug871161-1.html file_bug871161-2.html
+[test_bug1013316.html]
+[test_hash_encoded.html]
+[test_bug1081037.html]
+[test_window_open_close.html]
+tags = openwindow
+[test_viewport_resize.html]
+[test_image_clone_load.html]
+[test_bug1203668.html]
+[test_bug1166138.html]
+[test_bug1230665.html]
+[test_filepicker_default_directory.html]
+skip-if = toolkit == 'android'
+[test_bug1233598.html]
+[test_bug1250401.html]
+[test_bug1260664.html]
+[test_bug1261673.html]
+skip-if = (os == 'android' || os == 'mac')
+[test_bug1261674-1.html]
+skip-if = (os == 'android' || os == 'mac')
+[test_bug1261674-2.html]
+skip-if = (os == 'android' || os == 'mac')
+[test_bug1260704.html]
+[test_allowMedia.html]
+[test_bug1292522_same_domain_with_different_port_number.html]
+[test_bug1295719_event_sequence_for_arrow_keys.html]
+skip-if = os == "android" # up/down arrow keys not supported on android
+[test_bug1295719_event_sequence_for_number_keys.html]
+[test_bug1310865.html]
+[test_bug1315146.html]
diff --git a/dom/html/test/nnc_lockup.gif b/dom/html/test/nnc_lockup.gif
new file mode 100644
index 000000000..f746bb71d
--- /dev/null
+++ b/dom/html/test/nnc_lockup.gif
Binary files differ
diff --git a/dom/html/test/reflect.js b/dom/html/test/reflect.js
new file mode 100644
index 000000000..abc2697a9
--- /dev/null
+++ b/dom/html/test/reflect.js
@@ -0,0 +1,625 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * reflect.js is a collection of methods to test HTML attribute reflection.
+ * Each of attribute is reflected differently, depending on various parameters,
+ * see:
+ * http://www.whatwg.org/html/#reflecting-content-attributes-in-idl-attributes
+ *
+ * Do not forget to add these line at the beginning of each new reflect* method:
+ * ok(attr in element, attr + " should be an IDL attribute of this element");
+ * is(typeof element[attr], <type>, attr + " IDL attribute should be a <type>");
+ */
+
+/**
+ * Checks that a given attribute is correctly reflected as a string.
+ *
+ * @param aParameters Object object containing the parameters, which are:
+ * - element Element node to test
+ * - attribute String name of the attribute
+ * OR
+ * attribute Object object containing two attributes, 'content' and 'idl'
+ * - otherValues Array [optional] other values to test in addition of the default ones
+ * - extendedAttributes Object object which can have 'TreatNullAs': "EmptyString"
+ */
+function reflectString(aParameters)
+{
+ var element = aParameters.element;
+ var contentAttr = typeof aParameters.attribute === "string"
+ ? aParameters.attribute : aParameters.attribute.content;
+ var idlAttr = typeof aParameters.attribute === "string"
+ ? aParameters.attribute : aParameters.attribute.idl;
+ var otherValues = aParameters.otherValues !== undefined
+ ? aParameters.otherValues : [];
+ var treatNullAs = aParameters.extendedAttributes ?
+ aParameters.extendedAttributes.TreatNullAs : null;
+
+ ok(idlAttr in element,
+ idlAttr + " should be an IDL attribute of this element");
+ is(typeof element[idlAttr], "string",
+ "'" + idlAttr + "' IDL attribute should be a string");
+
+ // Tests when the attribute isn't set.
+ is(element.getAttribute(contentAttr), null,
+ "When not set, the content attribute should be null.");
+ is(element[idlAttr], "",
+ "When not set, the IDL attribute should return the empty string");
+
+ /**
+ * TODO: as long as null stringification doesn't follow the WebIDL
+ * specifications, don't add it to the loop below and keep it here.
+ */
+ element.setAttribute(contentAttr, null);
+ is(element.getAttribute(contentAttr), "null",
+ "null should have been stringified to 'null' for '" + contentAttr + "'");
+ is(element[idlAttr], "null",
+ "null should have been stringified to 'null' for '" + idlAttr + "'");
+ element.removeAttribute(contentAttr);
+
+ element[idlAttr] = null;
+ if (treatNullAs == "EmptyString") {
+ is(element.getAttribute(contentAttr), "",
+ "null should have been stringified to '' for '" + contentAttr + "'");
+ is(element[idlAttr], "",
+ "null should have been stringified to '' for '" + idlAttr + "'");
+ } else {
+ is(element.getAttribute(contentAttr), "null",
+ "null should have been stringified to 'null' for '" + contentAttr + "'");
+ is(element[idlAttr], "null",
+ "null should have been stringified to 'null' for '" + contentAttr + "'");
+ }
+ element.removeAttribute(contentAttr);
+
+ // Tests various strings.
+ var stringsToTest = [
+ // [ test value, expected result ]
+ [ "", "" ],
+ [ "null", "null" ],
+ [ "undefined", "undefined" ],
+ [ "foo", "foo" ],
+ [ contentAttr, contentAttr ],
+ [ idlAttr, idlAttr ],
+ // TODO: uncomment this when null stringification will follow the specs.
+ // [ null, "null" ],
+ [ undefined, "undefined" ],
+ [ true, "true" ],
+ [ false, "false" ],
+ [ 42, "42" ],
+ // ES5, verse 8.12.8.
+ [ { toString: function() { return "foo" } },
+ "foo" ],
+ [ { valueOf: function() { return "foo" } },
+ "[object Object]" ],
+ [ { valueOf: function() { return "quux" },
+ toString: undefined },
+ "quux" ],
+ [ { valueOf: function() { return "foo" },
+ toString: function() { return "bar" } },
+ "bar" ]
+ ];
+
+ otherValues.forEach(function(v) { stringsToTest.push([v, v]) });
+
+ stringsToTest.forEach(function([v, r]) {
+ element.setAttribute(contentAttr, v);
+ is(element[idlAttr], r,
+ "IDL attribute '" + idlAttr + "' should return the value it has been set to.");
+ is(element.getAttribute(contentAttr), r,
+ "Content attribute '" + contentAttr + "'should return the value it has been set to.");
+ element.removeAttribute(contentAttr);
+
+ element[idlAttr] = v;
+ is(element[idlAttr], r,
+ "IDL attribute '" + idlAttr + "' should return the value it has been set to.");
+ is(element.getAttribute(contentAttr), r,
+ "Content attribute '" + contentAttr + "' should return the value it has been set to.");
+ element.removeAttribute(contentAttr);
+ });
+
+ // Tests after removeAttribute() is called. Should be equivalent with not set.
+ is(element.getAttribute(contentAttr), null,
+ "When not set, the content attribute should be null.");
+ is(element[idlAttr], "",
+ "When not set, the IDL attribute should return the empty string");
+}
+
+/**
+ * Checks that a given attribute name for a given element is correctly reflected
+ * as an unsigned int.
+ *
+ * @param aParameters Object object containing the parameters, which are:
+ * - element Element node to test on
+ * - attribute String name of the attribute
+ * - nonZero Boolean whether the attribute should be non-null
+ * - defaultValue Integer [optional] default value, if different from the default one
+ */
+function reflectUnsignedInt(aParameters)
+{
+ var element = aParameters.element;
+ var attr = aParameters.attribute;
+ var nonZero = aParameters.nonZero;
+ var defaultValue = aParameters.defaultValue;
+ var fallback = aParameters.fallback;
+
+ if (defaultValue === undefined) {
+ if (nonZero) {
+ defaultValue = 1;
+ } else {
+ defaultValue = 0;
+ }
+ }
+
+ if (fallback === undefined) {
+ fallback = false;
+ }
+
+ ok(attr in element, attr + " should be an IDL attribute of this element");
+ is(typeof element[attr], "number", attr + " IDL attribute should be a number");
+
+ // Check default value.
+ is(element[attr], defaultValue, "default value should be " + defaultValue);
+ ok(!element.hasAttribute(attr), attr + " shouldn't be present");
+
+ var values = [ 1, 3, 42, 2147483647 ];
+
+ for (var value of values) {
+ element[attr] = value;
+ is(element[attr], value, "." + attr + " should be equals " + value);
+ is(element.getAttribute(attr), String(value),
+ "@" + attr + " should be equals " + value);
+
+ element.setAttribute(attr, value);
+ is(element[attr], value, "." + attr + " should be equals " + value);
+ is(element.getAttribute(attr), String(value),
+ "@" + attr + " should be equals " + value);
+ }
+
+ // -3000000000 is equivalent to 1294967296 when using the IDL attribute.
+ element[attr] = -3000000000;
+ is(element[attr], 1294967296, "." + attr + " should be equals to 1294967296");
+ is(element.getAttribute(attr), "1294967296",
+ "@" + attr + " should be equals to 1294967296");
+
+ // When setting the content attribute, it's a string so it will be invalid.
+ element.setAttribute(attr, -3000000000);
+ is(element.getAttribute(attr), "-3000000000",
+ "@" + attr + " should be equals to " + -3000000000);
+ is(element[attr], defaultValue,
+ "." + attr + " should be equals to " + defaultValue);
+
+ // When interpreted as unsigned 32-bit integers, all of these fall between
+ // 2^31 and 2^32 - 1, so per spec they return the default value.
+ var nonValidValues = [ -2147483648, -1, 3147483647];
+
+ for (var value of nonValidValues) {
+ element[attr] = value;
+ is(element.getAttribute(attr), String(defaultValue),
+ "@" + attr + " should be equals to " + defaultValue);
+ is(element[attr], defaultValue,
+ "." + attr + " should be equals to " + defaultValue);
+ }
+
+ for (var values of nonValidValues) {
+ element.setAttribute(attr, values[0]);
+ is(element.getAttribute(attr), String(values[0]),
+ "@" + attr + " should be equals to " + values[0]);
+ is(element[attr], defaultValue,
+ "." + attr + " should be equals to " + defaultValue);
+ }
+
+ // Setting to 0 should throw an error if nonZero is true.
+ var caught = false;
+ try {
+ element[attr] = 0;
+ } catch(e) {
+ caught = true;
+ is(e.name, "IndexSizeError", "exception should be IndexSizeError");
+ is(e.code, DOMException.INDEX_SIZE_ERR, "exception code should be INDEX_SIZE_ERR");
+ }
+
+ if (nonZero && !fallback) {
+ ok(caught, "an exception should have been caught");
+ } else {
+ ok(!caught, "no exception should have been caught");
+ }
+
+ // If 0 is set in @attr, it will be ignored when calling .attr.
+ element.setAttribute(attr, "0");
+ is(element.getAttribute(attr), "0", "@" + attr + " should be equals to 0");
+ if (nonZero) {
+ is(element[attr], defaultValue,
+ "." + attr + " should be equals to " + defaultValue);
+ } else {
+ is(element[attr], 0, "." + attr + " should be equals to 0");
+ }
+}
+
+/**
+ * Checks that a given attribute is correctly reflected as limited to known
+ * values enumerated attribute.
+ *
+ * @param aParameters Object object containing the parameters, which are:
+ * - element Element node to test on
+ * - attribute String name of the attribute
+ * OR
+ * attribute Object object containing two attributes, 'content' and 'idl'
+ * - validValues Array valid values we support
+ * - invalidValues Array invalid values
+ * - defaultValue String [optional] default value when no valid value is set
+ * OR
+ * defaultValue Object [optional] object containing two attributes, 'invalid' and 'missing'
+ * - unsupportedValues Array [optional] valid values we do not support
+ * - nullable boolean [optional] whether the attribute is nullable
+ */
+function reflectLimitedEnumerated(aParameters)
+{
+ var element = aParameters.element;
+ var contentAttr = typeof aParameters.attribute === "string"
+ ? aParameters.attribute : aParameters.attribute.content;
+ var idlAttr = typeof aParameters.attribute === "string"
+ ? aParameters.attribute : aParameters.attribute.idl;
+ var validValues = aParameters.validValues;
+ var invalidValues = aParameters.invalidValues;
+ var defaultValueInvalid = aParameters.defaultValue === undefined
+ ? "" : typeof aParameters.defaultValue === "string"
+ ? aParameters.defaultValue : aParameters.defaultValue.invalid
+ var defaultValueMissing = aParameters.defaultValue === undefined
+ ? "" : typeof aParameters.defaultValue === "string"
+ ? aParameters.defaultValue : aParameters.defaultValue.missing
+ var unsupportedValues = aParameters.unsupportedValues !== undefined
+ ? aParameters.unsupportedValues : [];
+ var nullable = aParameters.nullable;
+
+ ok(idlAttr in element, idlAttr + " should be an IDL attribute of this element");
+ if (nullable) {
+ // The missing value default is null, which is typeof == "object"
+ is(typeof element[idlAttr], "object", "'" + idlAttr + "' IDL attribute should be null, which has typeof == object");
+ is(element[idlAttr], null, "'" + idlAttr + "' IDL attribute should be null");
+ } else {
+ is(typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string");
+ }
+
+ if (nullable) {
+ element.setAttribute(contentAttr, "something");
+ // Now it will be a string
+ is(typeof element[idlAttr], "string", "'" + idlAttr + "' IDL attribute should be a string");
+ }
+
+ // Explicitly check the default value.
+ element.removeAttribute(contentAttr);
+ is(element[idlAttr], defaultValueMissing,
+ "When no attribute is set, the value should be the default value.");
+
+ // Check valid values.
+ validValues.forEach(function (v) {
+ element.setAttribute(contentAttr, v);
+ is(element[idlAttr], v,
+ "'" + v + "' should be accepted as a valid value for " + idlAttr);
+ is(element.getAttribute(contentAttr), v,
+ "Content attribute should return the value it has been set to.");
+ element.removeAttribute(contentAttr);
+
+ element.setAttribute(contentAttr, v.toUpperCase());
+ is(element[idlAttr], v,
+ "Enumerated attributes should be case-insensitive.");
+ is(element.getAttribute(contentAttr), v.toUpperCase(),
+ "Content attribute should not be lower-cased.");
+ element.removeAttribute(contentAttr);
+
+ element[idlAttr] = v;
+ is(element[idlAttr], v,
+ "'" + v + "' should be accepted as a valid value for " + idlAttr);
+ is(element.getAttribute(contentAttr), v,
+ "Content attribute should return the value it has been set to.");
+ element.removeAttribute(contentAttr);
+
+ element[idlAttr] = v.toUpperCase();
+ is(element[idlAttr], v,
+ "Enumerated attributes should be case-insensitive.");
+ is(element.getAttribute(contentAttr), v.toUpperCase(),
+ "Content attribute should not be lower-cased.");
+ element.removeAttribute(contentAttr);
+ });
+
+ // Check invalid values.
+ invalidValues.forEach(function (v) {
+ element.setAttribute(contentAttr, v);
+ is(element[idlAttr], defaultValueInvalid,
+ "When the content attribute is set to an invalid value, the default value should be returned.");
+ is(element.getAttribute(contentAttr), v,
+ "Content attribute should not have been changed.");
+ element.removeAttribute(contentAttr);
+
+ element[idlAttr] = v;
+ is(element[idlAttr], defaultValueInvalid,
+ "When the value is set to an invalid value, the default value should be returned.");
+ is(element.getAttribute(contentAttr), v,
+ "Content attribute should not have been changed.");
+ element.removeAttribute(contentAttr);
+ });
+
+ // Check valid values we currently do not support.
+ // Basically, it's like the checks for the valid values but with some todo's.
+ unsupportedValues.forEach(function (v) {
+ element.setAttribute(contentAttr, v);
+ todo_is(element[idlAttr], v,
+ "'" + v + "' should be accepted as a valid value for " + idlAttr);
+ is(element.getAttribute(contentAttr), v,
+ "Content attribute should return the value it has been set to.");
+ element.removeAttribute(contentAttr);
+
+ element.setAttribute(contentAttr, v.toUpperCase());
+ todo_is(element[idlAttr], v,
+ "Enumerated attributes should be case-insensitive.");
+ is(element.getAttribute(contentAttr), v.toUpperCase(),
+ "Content attribute should not be lower-cased.");
+ element.removeAttribute(contentAttr);
+
+ element[idlAttr] = v;
+ todo_is(element[idlAttr], v,
+ "'" + v + "' should be accepted as a valid value for " + idlAttr);
+ is(element.getAttribute(contentAttr), v,
+ "Content attribute should return the value it has been set to.");
+ element.removeAttribute(contentAttr);
+
+ element[idlAttr] = v.toUpperCase();
+ todo_is(element[idlAttr], v,
+ "Enumerated attributes should be case-insensitive.");
+ is(element.getAttribute(contentAttr), v.toUpperCase(),
+ "Content attribute should not be lower-cased.");
+ element.removeAttribute(contentAttr);
+ });
+
+ if (nullable) {
+ is(defaultValueMissing, null,
+ "Missing default value should be null for nullable attributes");
+ ok(validValues.length > 0, "We better have at least one valid value");
+ element.setAttribute(contentAttr, validValues[0]);
+ ok(element.hasAttribute(contentAttr),
+ "Should have content attribute: we just set it");
+ element[idlAttr] = null;
+ ok(!element.hasAttribute(contentAttr),
+ "Should have removed content attribute");
+ }
+}
+
+/**
+ * Checks that a given attribute is correctly reflected as a boolean.
+ *
+ * @param aParameters Object object containing the parameters, which are:
+ * - element Element node to test on
+ * - attribute String name of the attribute
+ * OR
+ * attribute Object object containing two attributes, 'content' and 'idl'
+ */
+function reflectBoolean(aParameters)
+{
+ var element = aParameters.element;
+ var contentAttr = typeof aParameters.attribute === "string"
+ ? aParameters.attribute : aParameters.attribute.content;
+ var idlAttr = typeof aParameters.attribute === "string"
+ ? aParameters.attribute : aParameters.attribute.idl;
+
+ ok(idlAttr in element,
+ idlAttr + " should be an IDL attribute of this element");
+ is(typeof element[idlAttr], "boolean",
+ idlAttr + " IDL attribute should be a boolean");
+
+ // Tests when the attribute isn't set.
+ is(element.getAttribute(contentAttr), null,
+ "When not set, the content attribute should be null.");
+ is(element[idlAttr], false,
+ "When not set, the IDL attribute should return false");
+
+ /**
+ * Test various values.
+ * Each value to test is actually an object containing a 'value' property
+ * containing the value to actually test, a 'stringified' property containing
+ * the stringified value and a 'result' property containing the expected
+ * result when the value is set to the IDL attribute.
+ */
+ var valuesToTest = [
+ { value: true, stringified: "true", result: true },
+ { value: false, stringified: "false", result: false },
+ { value: "true", stringified: "true", result: true },
+ { value: "false", stringified: "false", result: true },
+ { value: "foo", stringified: "foo", result: true },
+ { value: idlAttr, stringified: idlAttr, result: true },
+ { value: contentAttr, stringified: contentAttr, result: true },
+ { value: "null", stringified: "null", result: true },
+ { value: "undefined", stringified: "undefined", result: true },
+ { value: "", stringified: "", result: false },
+ { value: undefined, stringified: "undefined", result: false },
+ { value: null, stringified: "null", result: false },
+ { value: +0, stringified: "0", result: false },
+ { value: -0, stringified: "0", result: false },
+ { value: NaN, stringified: "NaN", result: false },
+ { value: 42, stringified: "42", result: true },
+ { value: Infinity, stringified: "Infinity", result: true },
+ { value: -Infinity, stringified: "-Infinity", result: true },
+ // ES5, verse 9.2.
+ { value: { toString: function() { return "foo" } }, stringified: "foo",
+ result: true },
+ { value: { valueOf: function() { return "foo" } },
+ stringified: "[object Object]", result: true },
+ { value: { valueOf: function() { return "quux" }, toString: undefined },
+ stringified: "quux", result: true },
+ { value: { valueOf: function() { return "foo" },
+ toString: function() { return "bar" } }, stringified: "bar",
+ result: true },
+ { value: { valueOf: function() { return false } },
+ stringified: "[object Object]", result: true },
+ { value: { foo: false, bar: false }, stringified: "[object Object]",
+ result: true },
+ { value: { }, stringified: "[object Object]", result: true },
+ ];
+
+ valuesToTest.forEach(function(v) {
+ element.setAttribute(contentAttr, v.value);
+ is(element[idlAttr], true,
+ "IDL attribute should return always return 'true' if the content attribute has been set");
+ is(element.getAttribute(contentAttr), v.stringified,
+ "Content attribute should return the stringified value it has been set to.");
+ element.removeAttribute(contentAttr);
+
+ element[idlAttr] = v.value;
+ is(element[idlAttr], v.result, "IDL attribute should return " + v.result);
+ is(element.getAttribute(contentAttr), v.result ? "" : null,
+ v.result ? "Content attribute should return the empty string."
+ : "Content attribute should return null.");
+ is(element.hasAttribute(contentAttr), v.result,
+ v.result ? contentAttr + " should not be present"
+ : contentAttr + " should be present");
+ element.removeAttribute(contentAttr);
+ });
+
+ // Tests after removeAttribute() is called. Should be equivalent with not set.
+ is(element.getAttribute(contentAttr), null,
+ "When not set, the content attribute should be null.");
+ is(element[contentAttr], false,
+ "When not set, the IDL attribute should return false");
+}
+
+/**
+ * Checks that a given attribute name for a given element is correctly reflected
+ * as an signed integer.
+ *
+ * @param aParameters Object object containing the parameters, which are:
+ * - element Element node to test on
+ * - attribute String name of the attribute
+ * - nonNegative Boolean true if the attribute is limited to 'non-negative numbers', false otherwise
+ * - defaultValue Integer [optional] default value, if one exists
+ */
+function reflectInt(aParameters)
+{
+ // Expected value returned by .getAttribute() when |value| has been previously passed to .setAttribute().
+ function expectedGetAttributeResult(value) {
+ return String(value);
+ }
+
+ function stringToInteger(value, nonNegative, defaultValue) {
+ // Parse: Ignore leading whitespace, find [+/-][numbers]
+ var result = /^[ \t\n\f\r]*([\+\-]?[0-9]+)/.exec(value);
+ if (result) {
+ var resultInt = parseInt(result[1], 10);
+ if ((nonNegative ? 0 : -0x80000000) <= resultInt && resultInt <= 0x7FFFFFFF) {
+ // If the value is within allowed value range for signed/unsigned
+ // integer, return it -- but add 0 to it to convert a possible -0 into
+ // +0, the only zero present in the signed integer range.
+ return resultInt + 0;
+ }
+ }
+ return defaultValue;
+ }
+
+ // Expected value returned by .getAttribute(attr) or .attr if |value| has been set via the IDL attribute.
+ function expectedIdlAttributeResult(value) {
+ // This returns the result of calling the ES ToInt32 algorithm on value.
+ return value << 0;
+ }
+
+ var element = aParameters.element;
+ var attr = aParameters.attribute;
+ var nonNegative = aParameters.nonNegative;
+
+ var defaultValue = aParameters.defaultValue !== undefined
+ ? aParameters.defaultValue
+ : nonNegative ? -1 : 0;
+
+ ok(attr in element, attr + " should be an IDL attribute of this element");
+ is(typeof element[attr], "number", attr + " IDL attribute should be a number");
+
+ // Check default value.
+ is(element[attr], defaultValue, "default value should be " + defaultValue);
+ ok(!element.hasAttribute(attr), attr + " shouldn't be present");
+
+ /**
+ * Test various values.
+ * value: The test value that will be set using both setAttribute(value) and
+ * element[attr] = value
+ */
+ var valuesToTest = [
+ // Test numeric inputs up to max signed integer
+ 0, 1, 55555, 2147483647, +42,
+ // Test string inputs up to max signed integer
+ "0", "1", "777777", "2147483647", "+42",
+ // Test negative numeric inputs up to min signed integer
+ -0, -1, -3333, -2147483648,
+ // Test negative string inputs up to min signed integer
+ "-0", "-1", "-222", "-2147483647", "-2147483648",
+ // Test numeric inputs that are outside legal 32 bit signed values
+ -2147483649, -3000000000, -4294967296, 2147483649, 4000000000, -4294967297,
+ // Test string inputs with extra padding
+ " 1111111", " 23456 ",
+ // Test non-numeric string inputs
+ "", " ", "+", "-", "foo", "+foo", "-foo", "+ foo", "- foo", "+-2", "-+2", "++2", "--2", "hello1234", "1234hello",
+ "444 world 555", "why 567 what", "-3 nots", "2e5", "300e2", "42+-$", "+42foo", "-514not", "\vblah", "0x10FFFF", "-0xABCDEF",
+ // Test decimal numbers
+ 1.2345, 42.0, 3456789.1, -2.3456, -6789.12345, -2147483649.1234,
+ // Test decimal strings
+ "1.2345", "42.0", "3456789.1", "-2.3456", "-6789.12345", "-2147483649.1234",
+ // Test special values
+ undefined, null, NaN, Infinity, -Infinity,
+ ];
+
+ valuesToTest.forEach(function(v) {
+ var intValue = stringToInteger(v, nonNegative, defaultValue);
+
+ element.setAttribute(attr, v);
+
+ is(element.getAttribute(attr), expectedGetAttributeResult(v), element.localName + ".setAttribute(" +
+ attr + ", " + v + "), " + element.localName + ".getAttribute(" + attr + ") ");
+
+ is(element[attr], intValue, element.localName +
+ ".setAttribute(" + attr + ", " + v + "), " + element.localName + "[" + attr + "] ");
+ element.removeAttribute(attr);
+
+ if (nonNegative && expectedIdlAttributeResult(v) < 0) {
+ try {
+ element[attr] = v;
+ ok(false, element.localName + "[" + attr + "] = " + v + " should throw IndexSizeError");
+ } catch(e) {
+ is(e.name, "IndexSizeError", element.localName + "[" + attr + "] = " + v +
+ " should throw IndexSizeError");
+ is(e.code, DOMException.INDEX_SIZE_ERR, element.localName + "[" + attr + "] = " + v +
+ " should throw INDEX_SIZE_ERR");
+ }
+ } else {
+ element[attr] = v;
+ is(element[attr], expectedIdlAttributeResult(v), element.localName + "[" + attr + "] = " + v +
+ ", " + element.localName + "[" + attr + "] ");
+ is(element.getAttribute(attr), String(expectedIdlAttributeResult(v)),
+ element.localName + "[" + attr + "] = " + v + ", " +
+ element.localName + ".getAttribute(" + attr + ") ");
+ }
+ element.removeAttribute(attr);
+ });
+
+ // Tests after removeAttribute() is called. Should be equivalent with not set.
+ is(element.getAttribute(attr), null,
+ "When not set, the content attribute should be null.");
+ is(element[attr], defaultValue,
+ "When not set, the IDL attribute should return default value.");
+}
+
+/**
+ * Checks that a given attribute is correctly reflected as a url.
+ *
+ * @param aParameters Object object containing the parameters, which are:
+ * - element Element node to test
+ * - attribute String name of the attribute
+ * OR
+ * attribute Object object containing two attributes, 'content' and 'idl'
+ */
+function reflectURL(aParameters)
+{
+ var element = aParameters.element;
+ var contentAttr = typeof aParameters.attribute === "string"
+ ? aParameters.attribute : aParameters.attribute.content;
+ var idlAttr = typeof aParameters.attribute === "string"
+ ? aParameters.attribute : aParameters.attribute.idl;
+
+ element[idlAttr] = "";
+ is(element[idlAttr], document.URL, "Empty string should resolve to document URL");
+}
diff --git a/dom/html/test/simpleFileOpener.js b/dom/html/test/simpleFileOpener.js
new file mode 100644
index 000000000..eeffdb6a1
--- /dev/null
+++ b/dom/html/test/simpleFileOpener.js
@@ -0,0 +1,32 @@
+var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
+Cu.importGlobalProperties(["File"]);
+
+var file;
+
+addMessageListener("file.open", function (stem) {
+ try {
+ if (!file) {
+ file = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIProperties).get("TmpD", Ci.nsIFile);
+ file.append(stem);
+ file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
+ }
+ sendAsyncMessage("file.opened", {
+ fullPath: file.path,
+ leafName: file.leafName,
+ domFile: File.createFromNsIFile(file),
+ });
+ } catch(e) {
+ sendAsyncMessage("fail", e.toString());
+ }
+});
+
+addMessageListener("file.remove", function () {
+ try {
+ file.remove(/* recursive: */ false);
+ file = undefined;
+ sendAsyncMessage("file.removed", null);
+ } catch(e) {
+ sendAsyncMessage("fail", e.toString());
+ }
+});
diff --git a/dom/html/test/test_a_text.html b/dom/html/test/test_a_text.html
new file mode 100644
index 000000000..5ffc1995f
--- /dev/null
+++ b/dom/html/test/test_a_text.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for a.text</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+ <link rel="help" href="http://www.whatwg.org/html/#dom-a-text"/>
+</head>
+<body>
+<div id="content">
+<a href="a">a b c</a>
+<a href="b">a <!--b--> c</a>
+<a href="c">a <b>b</b> c</a>
+</div>
+<pre id="test">
+<script>
+var d = document.getElementById("content")
+ .appendChild(document.createElement("a"));
+d.href = "d";
+d.appendChild(document.createTextNode("a "));
+d.appendChild(document.createTextNode("b "));
+d.appendChild(document.createTextNode("c "));
+var expected = ["a b c", "a c", "a b c", "a b c "];
+var list = document.getElementById("content").getElementsByTagName("a");
+for (var i = 0, il = list.length; i < il; ++i) {
+ is(list[i].text, list[i].textContent);
+ is(list[i].text, expected[i]);
+
+ list[i].text = "x";
+ is(list[i].text, "x");
+ is(list[i].textContent, "x");
+ is(list[i].firstChild.data, "x");
+ is(list[i].childNodes.length, 1);
+
+ list[i].textContent = "y";
+ is(list[i].text, "y");
+ is(list[i].textContent, "y");
+ is(list[i].firstChild.data, "y");
+ is(list[i].childNodes.length, 1);
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_allowMedia.html b/dom/html/test/test_allowMedia.html
new file mode 100644
index 000000000..f4e7b5c67
--- /dev/null
+++ b/dom/html/test/test_allowMedia.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=759964
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 759964</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 759964 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runNextTest);
+
+var SJS = "http://mochi.test:8888/tests/dom/html/test/allowMedia.sjs";
+var TEST_PAGE = "data:text/html,<audio src='" + SJS + "?audio'></audio>";
+
+var Ci = Components.interfaces;
+
+function runNextTest() {
+ var test = tests.shift();
+ if (!test) {
+ SimpleTest.finish();
+ return;
+ }
+ test();
+}
+
+var tests = [
+
+ // Set allowMedia = false, load a page with <audio>, verify the <audio>
+ // doesn't load its source.
+ function basic() {
+ var iframe = insertIframe();
+ SpecialPowers.allowMedia(iframe.contentWindow, false);
+ loadIframe(iframe, TEST_PAGE, function () {
+ verifyPass();
+ iframe.remove();
+ runNextTest();
+ });
+ },
+
+ // Set allowMedia = false on parent docshell, load a page with <audio> in a
+ // child iframe, verify the <audio> doesn't load its source.
+ function inherit() {
+ SpecialPowers.allowMedia(window, false);
+
+ var iframe = insertIframe();
+ loadIframe(iframe, TEST_PAGE, function () {
+ verifyPass();
+ iframe.remove();
+ SpecialPowers.allowMedia(window, true);
+ runNextTest();
+ });
+ },
+
+ // In a display:none iframe, set allowMedia = false, load a page with <audio>,
+ // verify the <audio> doesn't load its source.
+ function displayNone() {
+ var iframe = insertIframe();
+ iframe.style.display = "none";
+ SpecialPowers.allowMedia(iframe.contentWindow, false);
+ loadIframe(iframe, TEST_PAGE, function () {
+ verifyPass();
+ iframe.remove();
+ runNextTest();
+ });
+ },
+];
+
+function insertIframe() {
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ return iframe;
+}
+
+function loadIframe(iframe, url, onDone) {
+ iframe.setAttribute("src", url);
+ iframe.addEventListener("load", onDone);
+}
+
+function verifyPass() {
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", SJS, false);
+ xhr.send();
+ is(xhr.responseText, "PASS", "<audio> source should not have been loaded.");
+}
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=759964">Mozilla Bug 759964</a>
+<p id="display">
+</p>
+</body>
+</html>
diff --git a/dom/html/test/test_anchor_href_cache_invalidation.html b/dom/html/test/test_anchor_href_cache_invalidation.html
new file mode 100644
index 000000000..554f35e10
--- /dev/null
+++ b/dom/html/test/test_anchor_href_cache_invalidation.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for anchor cache invalidation</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <a id="x" href="http://example.com"></a>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+is($("x").href, "http://example.com/");
+is($("x").host, "example.com");
+
+$("x").href = "http://www.example.com";
+
+is($("x").href, "http://www.example.com/");
+is($("x").host, "www.example.com");
+
+$("x").setAttribute("href", "http://www.example.net/");
+is($("x").host, "www.example.net");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_anchor_ping.html b/dom/html/test/test_anchor_ping.html
new file mode 100644
index 000000000..4a39bcefe
--- /dev/null
+++ b/dom/html/test/test_anchor_ping.html
@@ -0,0 +1,309 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=786347
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 786347</title>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <script type="application/javascript;version=1.8">
+
+ /** Test for Bug 786347 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/NetUtil.jsm");
+Cu.import("resource://testing-common/httpd.js");
+Cu.import("resource://gre/modules/Promise.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
+
+addLoadEvent(function () {
+ Task.spawn(function run_tests() {
+ while (tests.length) {
+ let test = tests.shift();
+ info("-- running " + test.name);
+ yield Task.spawn(test);
+ }
+
+ SimpleTest.finish();
+ });
+});
+
+let tests = [
+
+ // Ensure that sending pings is enabled.
+ function* setup() {
+ Services.prefs.setBoolPref("browser.send_pings", true);
+ Services.prefs.setIntPref("browser.send_pings.max_per_link", -1);
+ Services.prefs.setBoolPref("security.mixed_content.block_active_content", false);
+ // The server we create can't handle the priming HEAD requests
+ Services.prefs.setBoolPref("security.mixed_content.send_hsts_priming", false);
+
+ SimpleTest.registerCleanupFunction(() => {
+ Services.prefs.clearUserPref("browser.send_pings");
+ Services.prefs.clearUserPref("browser.send_pings.max_per_link");
+ Services.prefs.clearUserPref("security.mixed_content.block_active_content");
+ Services.prefs.clearUserPref("security.mixed_content.send_hsts_priming");
+ });
+ },
+
+ // If both the address of the document containing the hyperlink being audited
+ // and ping URL have the same origin then the request must include a Ping-From
+ // HTTP header with, as its value, the address of the document containing the
+ // hyperlink, and a Ping-To HTTP header with, as its value, the target URL.
+ // The request must not include a Referer (sic) HTTP header.
+ function* same_origin() {
+ let from = "/ping-from/" + Math.random();
+ let to = "/ping-to/" + Math.random();
+ let ping = "/ping/" + Math.random();
+
+ let base;
+ let server = new HttpServer();
+
+ // The page that contains the link.
+ createFromPathHandler(server, from, to, () => ping);
+
+ // The page that the link's href points to.
+ let promiseHref = createToPathHandler(server, to);
+
+ // The ping we want to receive.
+ let promisePing = createPingPathHandler(server, ping, () => {
+ return {from: base + from, to: base + to};
+ });
+
+ // Start the server, get its base URL and run the test.
+ server.start(-1);
+ base = "http://localhost:" + server.identity.primaryPort;
+ navigate(base + from);
+
+ // Wait until the target and ping url have loaded.
+ yield Promise.all([promiseHref, promisePing]);
+
+ // Cleanup.
+ yield stopServer(server);
+ },
+
+ // If the origins are different, but the document containing the hyperlink
+ // being audited was not retrieved over an encrypted connection then the
+ // request must include a Referer (sic) HTTP header with, as its value, the
+ // address of the document containing the hyperlink, a Ping-From HTTP header
+ // with the same value, and a Ping-To HTTP header with, as its value, target
+ // URL.
+ function* diff_origin() {
+ let from = "/ping-from/" + Math.random();
+ let to = "/ping-to/" + Math.random();
+ let ping = "/ping/" + Math.random();
+
+ // We will use two servers to simulate two different origins.
+ let base, base2;
+ let server = new HttpServer();
+ let server2 = new HttpServer();
+
+ // The page that contains the link.
+ createFromPathHandler(server, from, to, () => base2 + ping);
+
+ // The page that the link's href points to.
+ let promiseHref = createToPathHandler(server, to);
+
+ // Start the first server and get its base URL.
+ server.start(-1);
+ base = "http://localhost:" + server.identity.primaryPort;
+
+ // The ping we want to receive.
+ let promisePing = createPingPathHandler(server2, ping, () => {
+ return {referrer: base + from, from: base + from, to: base + to};
+ });
+
+ // Start the second server, get its base URL and run the test.
+ server2.start(-1);
+ base2 = "http://localhost:" + server2.identity.primaryPort;
+ navigate(base + from);
+
+ // Wait until the target and ping url have loaded.
+ yield Promise.all([promiseHref, promisePing]);
+
+ // Cleanup.
+ yield stopServer(server);
+ yield stopServer(server2);
+ },
+
+ // If the origins are different and the document containing the hyperlink
+ // being audited was retrieved over an encrypted connection then the request
+ // must include a Ping-To HTTP header with, as its value, target URL. The
+ // request must neither include a Referer (sic) HTTP header nor include a
+ // Ping-From HTTP header.
+ function* diff_origin_secure_referrer() {
+ let ping = "/ping/" + Math.random();
+ let server = new HttpServer();
+
+ // The ping we want to receive.
+ let promisePing = createPingPathHandler(server, ping, () => {
+ return {to: "https://example.com/"};
+ });
+
+ // Start the server and run the test.
+ server.start(-1);
+
+ // The referrer will be loaded using a secure channel.
+ navigate("https://example.com/chrome/dom/html/test/" +
+ "file_anchor_ping.html?" + "http://localhost:" +
+ server.identity.primaryPort + ping);
+
+ // Wait until the ping has been sent.
+ yield promisePing;
+
+ // Cleanup.
+ yield stopServer(server);
+ },
+
+ // Test that the <a ping> attribute is properly tokenized using ASCII white
+ // space characters as separators.
+ function* tokenize_white_space() {
+ let from = "/ping-from/" + Math.random();
+ let to = "/ping-to/" + Math.random();
+
+ let base;
+ let server = new HttpServer();
+
+ let pings = [
+ "/ping1/" + Math.random(),
+ "/ping2/" + Math.random(),
+ "/ping3/" + Math.random(),
+ "/ping4/" + Math.random()
+ ];
+
+ // The page that contains the link.
+ createFromPathHandler(server, from, to, () => {
+ return " " + pings[0] + " \r " + pings[1] + " \t " +
+ pings[2] + " \n " + pings[3] + " ";
+ });
+
+ // The page that the link's href points to.
+ let promiseHref = createToPathHandler(server, to);
+
+ // The pings we want to receive.
+ let pingPathHandlers = createPingPathHandlers(server, pings, () => {
+ return {from: base + from, to: base + to};
+ });
+
+ // Start the server, get its base URL and run the test.
+ server.start(-1);
+ base = "http://localhost:" + server.identity.primaryPort;
+ navigate(base + from);
+
+ // Wait until the target and ping url have loaded.
+ yield Promise.all([promiseHref, ...pingPathHandlers]);
+
+ // Cleanup.
+ yield stopServer(server);
+ }
+];
+
+// Navigate the iframe used for testing to a new URL.
+function navigate(uri) {
+ document.getElementById("frame").src = uri;
+}
+
+// Registers a path handler for the given server that will serve a page
+// containing an <a ping> element. The page will automatically simulate
+// clicking the link after it has loaded.
+function createFromPathHandler(server, path, href, lazyPing) {
+ server.registerPathHandler(path, function (request, response) {
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.setHeader("Content-Type", "text/html;charset=utf-8", false);
+ response.setHeader("Cache-Control", "no-cache", false);
+
+ let body = '<body onload="document.body.firstChild.click()">' +
+ '<a href="' + href + '" ping="' + lazyPing() + '"></a></body>';
+ response.write(body);
+ });
+}
+
+// Registers a path handler for the given server that will serve a simple empty
+// page we can use as the href attribute for links. It returns a promise that
+// will be resolved once the page has been requested.
+function createToPathHandler(server, path) {
+ let deferred = Promise.defer();
+
+ server.registerPathHandler(path, function (request, response) {
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.setHeader("Content-Type", "text/html;charset=utf-8", false);
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.write("OK");
+
+ deferred.resolve();
+ });
+
+ return deferred.promise;
+}
+
+// Register multiple path handlers for the given server that will receive
+// pings as sent when an <a ping> element is clicked. This method uses
+// createPingPathHandler() defined below to ensure all headers are sent
+// and received as expected.
+function createPingPathHandlers(server, paths, lazyHeaders) {
+ return Array.from(paths, (path) => createPingPathHandler(server, path, lazyHeaders));
+}
+
+// Registers a path handler for the given server that will receive pings as
+// sent when an <a ping> element has been clicked. It will check that the
+// correct http method has been used, the post data is correct and all headers
+// are given as expected. It returns a promise that will be resolved once the
+// ping has been received.
+function createPingPathHandler(server, path, lazyHeaders) {
+ let deferred = Promise.defer();
+
+ server.registerPathHandler(path, function (request, response) {
+ let headers = lazyHeaders();
+
+ is(request.method, "POST", "correct http method used");
+ is(request.getHeader("Ping-To"), headers.to, "valid ping-to header");
+
+ if ("from" in headers) {
+ is(request.getHeader("Ping-From"), headers.from, "valid ping-from header");
+ } else {
+ ok(!request.hasHeader("Ping-From"), "no ping-from header");
+ }
+
+ if ("referrer" in headers) {
+ is(request.getHeader("Referer"), headers.referrer, "valid referer header");
+ } else {
+ ok(!request.hasHeader("Referer"), "no referer header");
+ }
+
+ let bs = request.bodyInputStream;
+ let body = NetUtil.readInputStreamToString(bs, bs.available());
+ is(body, "PING", "correct body sent");
+
+ response.setStatusLine(request.httpVersion, 200, "OK");
+ response.setHeader("Content-Type", "text/html;charset=utf-8", false);
+ response.setHeader("Cache-Control", "no-cache", false);
+ response.write("OK");
+
+ deferred.resolve();
+ });
+
+ return deferred.promise;
+}
+
+// Returns a promise that is resolved when the given http server instance has
+// been stopped.
+function stopServer(server) {
+ let deferred = Promise.defer();
+ server.stop(deferred.resolve);
+ return deferred.promise;
+}
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=786347">Mozilla Bug 786347</a>
+<p id="display"></p>
+<iframe id="frame" />
+</body>
+</html>
diff --git a/dom/html/test/test_applet_attributes_reflection.html b/dom/html/test/test_applet_attributes_reflection.html
new file mode 100644
index 000000000..dd04a2022
--- /dev/null
+++ b/dom/html/test/test_applet_attributes_reflection.html
@@ -0,0 +1,86 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLAppletElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLAppletElement attributes reflection **/
+
+// .align (String)
+reflectString({
+ element: document.createElement("applet"),
+ attribute: "align",
+});
+
+// .alt (String)
+reflectString({
+ element: document.createElement("applet"),
+ attribute: "alt",
+});
+
+// .archive (String)
+reflectString({
+ element: document.createElement("applet"),
+ attribute: "archive",
+});
+
+// .code (String)
+reflectString({
+ element: document.createElement("applet"),
+ attribute: "code",
+});
+
+// .codeBase (URL)
+reflectURL({
+ element: document.createElement("applet"),
+ attribute: "codeBase",
+});
+
+// .height (String)
+reflectString({
+ element: document.createElement("applet"),
+ attribute: "height",
+});
+
+// .hspace (unsigned int)
+reflectUnsignedInt({
+ element: document.createElement("applet"),
+ attribute: "hspace",
+});
+
+// .name (String)
+reflectString({
+ element: document.createElement("applet"),
+ attribute: "name",
+});
+
+// .object (URL)
+reflectURL({
+ element: document.createElement("applet"),
+ attribute: "object",
+});
+
+// .vspace (unsigned int)
+reflectUnsignedInt({
+ element: document.createElement("applet"),
+ attribute: "vspace",
+});
+
+// .width (String)
+reflectString({
+ element: document.createElement("applet"),
+ attribute: "width",
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_audio_wakelock.html b/dom/html/test/test_audio_wakelock.html
new file mode 100644
index 000000000..a45f2405b
--- /dev/null
+++ b/dom/html/test/test_audio_wakelock.html
@@ -0,0 +1,125 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=868943
+-->
+<head>
+ <title>Test for Bug 868943</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=868943">Mozilla Bug 868943</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 868943 **/
+
+function testAudioPlayPause() {
+ var lockState = true;
+ var count = 0;
+
+ var content = document.getElementById('content');
+
+ var audio = document.createElement('audio');
+ audio.src = "wakelock.ogg";
+ content.appendChild(audio);
+
+ var startDate;
+ function testAudioPlayListener(topic, state) {
+ is(topic, "cpu", "#1 Audio element locked the target == cpu");
+ var locked = state == "locked-foreground" ||
+ state == "locked-background";
+
+ var s = locked ? "locked" : "unlocked";
+ is(locked, lockState, "#1 Audio element " + s + " the cpu");
+ count++;
+
+ // count == 1 is when the cpu wakelock is created
+ // count == 2 is when the cpu wakelock is released
+
+ if (count == 1) {
+ // The next step is to unlock the resource.
+ lockState = false;
+ audio.pause();
+ startDate = new Date();
+ return;
+ }
+
+ is(count, 2, "The count should be 2 which indicates wakelock release");
+
+ if (count == 2) {
+ var diffDate = (new Date() - startDate);
+ ok(diffDate > 200, "#1 There was at least 200 milliseconds between the stop and the wakelock release");
+
+ content.removeChild(audio);
+ navigator.mozPower.removeWakeLockListener(testAudioPlayListener);
+ runTests();
+ }
+ };
+
+ navigator.mozPower.addWakeLockListener(testAudioPlayListener);
+ audio.play();
+}
+
+function testAudioPlay() {
+ var lockState = true;
+ var count = 0;
+
+ var content = document.getElementById('content');
+
+ var audio = document.createElement('audio');
+ audio.src = "wakelock.ogg";
+ content.appendChild(audio);
+
+ function testAudioPlayListener(topic, state) {
+ is(topic, "cpu", "#2 Audio element locked the target == cpu");
+ var locked = state == "locked-foreground" ||
+ state == "locked-background";
+
+ var s = locked ? "locked" : "unlocked";
+ is(locked, lockState, "#2 Audio element " + s + " the cpu");
+ count++;
+
+ // count == 1 is when the cpu wakelock is created: the wakelock must be
+ // created when the media element starts playing.
+ // count == 2 is when the cpu wakelock is released.
+
+ if (count == 1) {
+ // The next step is to unlock the resource.
+ lockState = false;
+ } else if (count == 2) {
+ content.removeChild(audio);
+ navigator.mozPower.removeWakeLockListener(testAudioPlayListener);
+ runTests();
+ }
+ };
+
+ navigator.mozPower.addWakeLockListener(testAudioPlayListener);
+ audio.play();
+}
+
+var tests = [ testAudioPlayPause, testAudioPlay ];
+function runTests() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var test = tests.pop();
+ test();
+};
+
+SpecialPowers.pushPrefEnv({"set": [["media.wakelock_timeout", 500]]}, runTests);
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_base_attributes_reflection.html b/dom/html/test/test_base_attributes_reflection.html
new file mode 100644
index 000000000..e8398f88a
--- /dev/null
+++ b/dom/html/test/test_base_attributes_reflection.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLBaseElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLBaseElement attributes reflection **/
+
+// .href is sort of like a URL reflection, but with some special rules. Watch
+// out for that!
+reflectURL({
+ element: document.createElement("base"),
+ attribute: "href"
+});
+
+// .target
+reflectString({
+ element: document.createElement("base"),
+ attribute: "target"
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1003539.html b/dom/html/test/test_bug1003539.html
new file mode 100644
index 000000000..041e813d2
--- /dev/null
+++ b/dom/html/test/test_bug1003539.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1003539
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1003539</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1003539 **/
+// Refering to this specification: http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#dom-table-insertrow
+var tab;
+tab = document.createElement("table");
+tab.createTHead();
+tab.insertRow();
+is(tab.innerHTML, '<thead></thead><tbody><tr></tr></tbody>', "Row should be inserted in the tbody.");
+
+tab = document.createElement("table");
+tab.createTBody();
+tab.createTBody();
+tab.insertRow();
+is(tab.innerHTML, '<tbody></tbody><tbody><tr></tr></tbody>', "Row should be inserted in the last tbody.");
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1003539">Mozilla Bug 1003539</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug100533.html b/dom/html/test/test_bug100533.html
new file mode 100644
index 000000000..d5e45fa47
--- /dev/null
+++ b/dom/html/test/test_bug100533.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=100533
+-->
+<head>
+ <title>Test for Bug 100533</title>
+ <script type="text/javascript" src="/MochiKit/Base.js"></script>
+ <script type="text/javascript" src="/MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="/MochiKit/Style.js"></script>
+ <script type="text/javascript" src="/MochiKit/Signal.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=100533">Mozilla Bug 100533</a>
+<p id="display"></p>
+<div id="content" >
+
+<button id="thebutton">Test</button>
+<iframe style='display: none;' src='bug100533_iframe.html' id='a'></iframe>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+/** Test for Bug 100533 **/
+var submitIframeForm = function() {
+ $('a').contentDocument.getElementById('b').submit();
+}
+
+submitted = function() {
+ ok(true, "Finished. Form submits when located in iframe set to display:none;");
+ SimpleTest.finish();
+};
+
+addLoadEvent(function() {
+ connect("thebutton", "click", submitIframeForm);
+ signal("thebutton", "click");
+});
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug1013316.html b/dom/html/test/test_bug1013316.html
new file mode 100644
index 000000000..bb7aa928f
--- /dev/null
+++ b/dom/html/test/test_bug1013316.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1013316
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1013316</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1013316 **/
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(function() {
+ is(Object.keys(document.all).length, 15, "We have 15 indexed props");
+ var props = Object.getOwnPropertyNames(document.all);
+ is(props.length, 20, "Should have five names");
+ is(props[15], "display", "display first");
+ is(props[16], "content", "content second");
+ is(props[17], "bar", "bar third");
+ is(props[18], "foo", "foo fourth");
+ is(props[19], "test", "test fifth");
+
+ is(Object.keys(document.images).length, 2, "We have 2 indexed props");
+ props = Object.getOwnPropertyNames(document.images);
+ is(props.length, 5, "Should have 3 names");
+ is(props[2], "display", "display first on document.images");
+ is(props[3], "bar", "bar second on document.images");
+ is(props[4], "foo", "foo third on document.images");
+ SimpleTest.finish();
+ })
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1013316">Mozilla Bug 1013316</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <img id="display">
+ <img name="foo" id="bar">
+ <div name="baz">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1045270.html b/dom/html/test/test_bug1045270.html
new file mode 100644
index 000000000..9011f91ec
--- /dev/null
+++ b/dom/html/test/test_bug1045270.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+ <!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1045270
+-->
+ <head>
+ <title>Test for Bug 583514</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1045270">Mozilla Bug 1045270</a>
+ <p id="display"></p>
+ <div id="content">
+ <input type=number>
+ </div>
+ <pre id="test">
+ <script type="application/javascript">
+
+ /** Test for Bug 1045270 **/
+
+ var input = document.querySelector("input");
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.waitForFocus(function() {
+ input.focus();
+ input.addEventListener("input", function() {
+ // reframe
+ document.body.style.display = "none";
+ document.body.style.display = "";
+ document.body.offsetLeft; // flush
+ }, false);
+ synthesizeKey("1", {});
+ SimpleTest.executeSoon(function() {
+ synthesizeKey("2", {});
+ SimpleTest.executeSoon(function() {
+ is(input.value, "12", "Reframe should restore focus and selection properly");
+ SimpleTest.finish();
+ });
+ });
+ });
+
+ </script>
+ </pre>
+ </body>
+</html>
diff --git a/dom/html/test/test_bug1081037.html b/dom/html/test/test_bug1081037.html
new file mode 100644
index 000000000..9d8782580
--- /dev/null
+++ b/dom/html/test/test_bug1081037.html
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1081037
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1081037</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1081037 **/
+
+function shouldThrow(fun, msg, ex, todo) {
+ try {
+ fun();
+ ok(todo, msg);
+ } catch (e) {
+ ok(new RegExp(ex).test(e), msg + " (thrown:" + e + ")")
+ }
+}
+
+var Foo = document.registerElement('x-foo', {
+ prototype: {bar: 5}
+});
+
+Foo.prototype.bar = 6;
+var foo = new Foo();
+is(foo.bar, 6, "prototype of the ctor returned from registerElement works");
+
+var protoDesc = Object.getOwnPropertyDescriptor(Foo, "prototype");
+is(protoDesc.configurable, false, "proto should be non-configurable");
+is(protoDesc.enumerable, false, "proto should be non-enumerable");
+is(protoDesc.writable, false, "proto should be non-writable");
+
+// TODO: FIXME!
+shouldThrow(function() {
+ document.registerElement('x-foo2', {
+ prototype: Foo.prototype
+ });
+ },
+ "if proto is an interface prototype object, registerElement should throw",
+ "not supported",
+ /* todo = */ true);
+
+var nonConfigReadonlyProto = Object.create(HTMLElement.prototype,
+ { constructor: { configurable: false, writable: false, value: 42 } });
+
+shouldThrow(function() {
+ document.registerElement('x-nonconfig-readonly', {
+ prototype: nonConfigReadonlyProto
+ });
+ },
+ "non-configurable and not-writable constructor property",
+ "not supported");
+
+
+// this is not defined in current spec:
+var readonlyProto = Object.create(HTMLElement.prototype,
+ { constructor: { configurable: true, writable: false, value: 42 } });
+
+var Readonly = document.registerElement('x-nonconfig-readonly', {
+ prototype: readonlyProto
+});
+
+is(Readonly.prototype, readonlyProto, "configurable readonly constructor property");
+
+var handler = {
+ getOwnPropertyDescriptor: function(target, name) {
+ return name == "constructor" ? undefined : Object.getOwnPropertyDescriptor(target,name);
+ },
+ defineProperty: function(target, name, propertyDescriptor) {
+ if (name == "constructor") {
+ throw "spec this";
+ }
+
+ return Object.defineProperty(target, name, propertyDescriptor);
+ },
+ has: function(target, name) {
+ if (name == "constructor") {
+ return false;
+ }
+ return name in target;
+ }
+};
+var proxy = new Proxy({}, handler);
+
+shouldThrow(function() {
+ document.registerElement('x-proxymagic', {
+ prototype: proxy
+ });
+ },
+ "proxy magic",
+ "spec this");
+
+var getOwn = 0;
+var defineProp = 0;
+var handler2 = {
+ getOwnPropertyDescriptor: function(target, name) {
+ if (name == "constructor") {
+ getOwn++;
+ }
+ return Object.getOwnPropertyDescriptor(target,name);
+ },
+ defineProperty: function(target, name, propertyDescriptor) {
+ if (name == "constructor") {
+ defineProp++;
+ }
+ return Object.defineProperty(target, name, propertyDescriptor);
+ }
+};
+var proxy2 = new Proxy({}, handler2);
+
+document.registerElement('x-proxymagic2', {
+ prototype: proxy2
+});
+
+is(getOwn, 1, "number of getOwnPropertyDescriptor calls from registerElement: " + getOwn);
+is(defineProp, 1, "number of defineProperty calls from registerElement: " + defineProp);
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1081037">Mozilla Bug 1081037</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug109445.html b/dom/html/test/test_bug109445.html
new file mode 100644
index 000000000..27ffe2294
--- /dev/null
+++ b/dom/html/test/test_bug109445.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=109445
+-->
+<head>
+ <title>Test for Bug 109445</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=109445">Mozilla Bug 109445</a>
+<p id="display">
+<map name=a>
+<area shape=rect coords=25,25,75,75 href=#x>
+</map>
+<map id=b>
+<area shape=rect coords=25,25,75,75 href=#y>
+</map>
+<map name=a>
+<area shape=rect coords=25,25,75,75 href=#FAIL>
+</map>
+<map id=b>
+<area shape=rect coords=25,25,75,75 href=#FAIL>
+</map>
+
+<img usemap=#a src=image.png>
+<img usemap=#b src=image.png>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 109445 **/
+SimpleTest.waitForExplicitFinish();
+var images = document.getElementsByTagName("img");
+var second = false;
+onhashchange = function() {
+ if (!second) {
+ second = true;
+ is(location.hash, "#x", "First map");
+ SimpleTest.waitForFocus(() => synthesizeMouse(images[1], 50, 50, {}));
+ } else {
+ is(location.hash, "#y", "Second map");
+ SimpleTest.finish();
+ }
+};
+SimpleTest.waitForFocus(() => synthesizeMouse(images[0], 50, 50, {}));
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug109445.xhtml b/dom/html/test/test_bug109445.xhtml
new file mode 100644
index 000000000..b1524c8ea
--- /dev/null
+++ b/dom/html/test/test_bug109445.xhtml
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=109445
+-->
+<head>
+ <title>Test for Bug 109445</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=109445">Mozilla Bug 109445</a>
+<p id="display">
+<map name="a">
+<area shape="rect" coords="25,25,75,75" href="#x"/>
+</map>
+<map id="b">
+<area shape="rect" coords="25,25,75,75" href="#y"/>
+</map>
+<map name="a">
+<area shape="rect" coords="25,25,75,75" href="#FAIL"/>
+</map>
+<map id="b">
+<area shape="rect" coords="25,25,75,75" href="#FAIL"/>
+</map>
+
+<img usemap="#a" src="image.png"/>
+<img usemap="#b" src="image.png"/>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 109445 **/
+SimpleTest.waitForExplicitFinish();
+var images = document.getElementsByTagName("img");
+var second = false;
+onhashchange = function() {
+ if (!second) {
+ second = true;
+ is(location.hash, "#x", "First map");
+ SimpleTest.waitForFocus(() => synthesizeMouse(images[1], 50, 50, {}));
+ } else {
+ is(location.hash, "#y", "Second map");
+ SimpleTest.finish();
+ }
+};
+SimpleTest.waitForFocus(() => synthesizeMouse(images[0], 50, 50, {}));
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1146116.html b/dom/html/test/test_bug1146116.html
new file mode 100644
index 000000000..a4a4431cf
--- /dev/null
+++ b/dom/html/test/test_bug1146116.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1146116
+-->
+<head>
+ <title>Test for Bug 1146116</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1146116">Mozilla Bug 1146116</a>
+<p id="display">
+ <input type="file" id="file">
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript;version=1.7">
+/** Test for bug 1146116 **/
+
+SimpleTest.waitForExplicitFinish();
+
+const helperURL = SimpleTest.getTestFileURL("simpleFileOpener.js");
+const helper = SpecialPowers.loadChromeScript(helperURL);
+helper.addMessageListener("fail", function onFail(message) {
+ is(message, null, "chrome script failed");
+ SimpleTest.finish();
+});
+helper.addMessageListener("file.opened", onFileOpened);
+helper.sendAsyncMessage("file.open", "test_bug1146116.txt");
+
+function getGlobal(thing) {
+ return SpecialPowers.unwrap(SpecialPowers.Cu.getGlobalForObject(thing));
+}
+
+function onFileOpened(message) {
+ const file = message.domFile;
+ const elem = document.getElementById("file");
+ is(getGlobal(elem), window,
+ "getGlobal() works as expected");
+ isnot(getGlobal(file), window,
+ "File from MessageManager is wrapped");
+ SpecialPowers.wrap(elem).mozSetFileArray([file]);
+ is(getGlobal(elem.files[0]), window,
+ "File read back from input element is not wrapped");
+ helper.addMessageListener("file.removed", onFileRemoved);
+ helper.sendAsyncMessage("file.remove", null);
+}
+
+function onFileRemoved() {
+ helper.destroy();
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1166138.html b/dom/html/test/test_bug1166138.html
new file mode 100644
index 000000000..889416775
--- /dev/null
+++ b/dom/html/test/test_bug1166138.html
@@ -0,0 +1,130 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1166138
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1166138</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SpawnTask.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1166138">Mozilla Bug 1166138</a>
+ <p id="display"></p>
+ <div id="content" style="display: none">
+ </div>
+
+ <img srcset="file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x"
+ src="file_bug1166138_def.png"
+ onload="onLoad()">
+
+ <script type="application/javascript">
+ var img1x = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_1x.png";
+ var img2x = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_2x.png";
+ var imgdef = "http://mochi.test:8888/tests/dom/html/test/file_bug1166138_def.png";
+ var onLoadCallback = null;
+ var done = false;
+
+ var startPromise = new Promise((a) => {
+ onLoadCallback = () => {
+ var image = document.querySelector('img');
+ // If we aren't starting at 2x scale, resize to 2x scale, and wait for a load
+ if (image.currentSrc != img2x) {
+ onLoadCallback = a;
+ SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]});
+ } else {
+ a();
+ }
+ };
+ });
+
+ // if aLoad is true, waits for a load event. Otherwise, spins the event loop twice to
+ // ensure that no events were queued to be fired.
+ function spin(aLoad) {
+ if (aLoad) {
+ return new Promise((a) => {
+ ok(!onLoadCallback, "Shouldn't be an existing callback");
+ onLoadCallback = a;
+ });
+ } else {
+ return new Promise((a) => SimpleTest.executeSoon(() => SimpleTest.executeSoon(a)));
+ }
+ }
+
+ function onLoad() {
+ if (done) return;
+ ok(onLoadCallback, "Expected a load event");
+ if (onLoadCallback) {
+ var cb = onLoadCallback;
+ onLoadCallback = null;
+ cb();
+ }
+ }
+
+ add_task(function* () {
+ yield startPromise;
+ var image = document.querySelector('img');
+ is(image.currentSrc, img2x, "initial scale must be 2x");
+
+ SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]});
+ yield spin(true);
+ is(image.currentSrc, img1x, "pre-existing img tag to 1x");
+
+ SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]});
+ yield spin(true);
+ is(image.currentSrc, img2x, "pre-existing img tag to 2x");
+
+ // Try removing & re-adding the image
+ document.body.removeChild(image);
+
+ SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]});
+ yield spin(false); // No load should occur because the element is unbound
+
+ document.body.appendChild(image);
+ yield spin(true);
+ is(image.currentSrc, img1x, "remove and re-add tag after changing to 1x");
+
+ document.body.removeChild(image);
+ SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 2]]});
+ yield spin(false); // No load should occur because the element is unbound
+
+ document.body.appendChild(image);
+ yield spin(true);
+ is(image.currentSrc, img2x, "remove and re-add tag after changing to 2x");
+
+ // get rid of the srcset attribute! It should become the default
+ image.removeAttribute('srcset');
+ yield spin(true);
+ is(image.currentSrc, imgdef, "remove srcset attribute");
+
+ // Setting srcset again should return it to the correct value
+ image.setAttribute('srcset', "file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x");
+ yield spin(true);
+ is(image.currentSrc, img2x, "restore srcset attribute");
+
+ // Create a new image
+ var newImage = document.createElement('img');
+ // Switch load listening over to newImage
+ newImage.addEventListener('load', onLoad);
+ image.removeEventListener('load', onLoad);
+
+ document.body.appendChild(newImage);
+ yield spin(false); // no load event should fire - as the image has no attributes
+ is(newImage.currentSrc, "", "New element with no attributes");
+ newImage.setAttribute('srcset', "file_bug1166138_1x.png 1x, file_bug1166138_2x.png 2x");
+ yield spin(true);
+ is(newImage.currentSrc, img2x, "Adding srcset attribute");
+
+ SpecialPowers.pushPrefEnv({'set': [['layout.css.devPixelsPerPx', 1]]});
+ yield spin(true);
+ is(newImage.currentSrc, img1x, "new image after switching to 1x");
+ is(image.currentSrc, img1x, "old image after switching to 1x");
+
+ // Clear the listener
+ done = true;
+ });
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1203668.html b/dom/html/test/test_bug1203668.html
new file mode 100644
index 000000000..8d9ad9a63
--- /dev/null
+++ b/dom/html/test/test_bug1203668.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1203668
+-->
+<head>
+ <title>Test for Bug 1203668</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1203668">Mozilla Bug 1203668</a>
+<p id="display"></p>
+<div id="content">
+ <select class="select" multiple>
+ <option value="foo" selected>foo</option>
+ <option value="bar" selected>bar</option>
+ </select>
+ <select class="select" multiple>
+ <option value="foo">foo</option>
+ <option value="bar" selected>bar</option>
+ </select>
+ <select class="select" multiple>
+ <option value="foo">foo</option>
+ <option value="bar">bar</option>
+ </select>
+ <select class="select" size=1>
+ <option value="foo">foo</option>
+ <option value="bar" selected>bar</option>
+ </select>
+ <select class="select" size=1>
+ <option value="foo">foo</option>
+ <option value="bar">bar</option>
+ </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1203668 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest()
+{
+ var selects = document.querySelectorAll('.select');
+ for (i=0; i < selects.length; i++) {
+ var select = selects[i];
+ select.value = "bogus"
+ is(select.selectedIndex, -1, "no option is selected");
+ is(select.children[0].selected, false, "first option is not selected");
+ is(select.children[1].selected, false, "second option is not selected");
+ }
+
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForFocus(runTest);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1230665.html b/dom/html/test/test_bug1230665.html
new file mode 100644
index 000000000..2bad51cdb
--- /dev/null
+++ b/dom/html/test/test_bug1230665.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+ <title>Test for Bug 1230665</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script>
+SimpleTest.waitForExplicitFinish();
+
+SimpleTest.waitForFocus(function() {
+ document.getElementById("flexbutton1").focus();
+ synthesizeKey("VK_TAB", { });
+ var e = document.getElementById("flexbutton2");
+ is(document.activeElement, e, "focus in flexbutton2 after TAB");
+
+ document.getElementById("gridbutton1").focus();
+ synthesizeKey("VK_TAB", { });
+ e = document.getElementById("gridbutton2");
+ is(document.activeElement, e, "focus in gridbutton2 after TAB");
+
+ SimpleTest.finish();
+});
+
+</script>
+
+<div tabindex="0" style="display:flex">
+ <button id="flexbutton1"></button>
+ text <!-- this text will force a :-moz-anonymous-flex-item frame -->
+ <div style="">
+ <button id="flexbutton2"></button>
+ </div>
+</div>
+
+
+<div tabindex="0" style="display:grid">
+ <button id="gridbutton1"></button>
+ text <!-- this text will force a :-moz-anonymous-grid-item frame -->
+ <div style="">
+ <button id="gridbutton2"></button>
+ </div>
+</div>
+
+</body>
+</html>
diff --git a/dom/html/test/test_bug1233598.html b/dom/html/test/test_bug1233598.html
new file mode 100644
index 000000000..c193219ed
--- /dev/null
+++ b/dom/html/test/test_bug1233598.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1233598
+-->
+<head>
+ <title>Test for Bug 1233598</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1233598">Mozilla Bug 1233598</a>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1233598 **/
+
+var i; // must be out here to trigger the leak
+
+function runTest()
+{
+ i = document.createElement("input");
+ i.setAttribute("type", "file");
+ i.getFilesAndDirectories(); // returns a promise
+ ok(true, "Are we leaking?");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set":[["dom.input.dirpicker", true]]}, runTest);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1250401.html b/dom/html/test/test_bug1250401.html
new file mode 100644
index 000000000..ec9fc6cbf
--- /dev/null
+++ b/dom/html/test/test_bug1250401.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1250401
+-->
+<head>
+ <title>Test for Bug 1250401</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1250401">Bug 1250401</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 1250401 **/
+function test_add() {
+ var select = document.createElement("select");
+
+ var g1 = document.createElement("optgroup");
+ var o1 = document.createElement("option");
+ g1.appendChild(o1);
+ select.appendChild(g1);
+
+ var g2 = document.createElement("optgroup");
+ var o2 = document.createElement("option");
+ g2.appendChild(o2);
+ select.add(g2, 0);
+
+ is(select.children.length, 1, "Select has 1 item");
+ is(select.firstChild, g1, "First item is g1");
+ is(select.firstChild.children.length, 2, "g2 has 2 children");
+ is(select.firstChild.children[0], g2, "g1 has 2 children: g2");
+ is(select.firstChild.children[1], o1, "g1 has 2 children: o1");
+ is(o1.index, 0, "o1.index should be 0");
+ is(o2.index, 0, "o2.index should be 0");
+}
+
+function test_append() {
+ var select = document.createElement("select");
+
+ var g1 = document.createElement("optgroup");
+ var o1 = document.createElement("option");
+ g1.appendChild(o1);
+ select.appendChild(g1);
+
+ var g2 = document.createElement("optgroup");
+ var o2 = document.createElement("option");
+ g2.appendChild(o2);
+ g1.appendChild(g2);
+
+ is(select.children.length, 1, "Select has 1 item");
+ is(select.firstChild, g1, "First item is g1");
+ is(select.firstChild.children.length, 2, "g2 has 2 children");
+ is(select.firstChild.children[0], o1, "g1 has 2 children: o1");
+ is(select.firstChild.children[1], g2, "g1 has 2 children: g1");
+ is(o1.index, 0, "o1.index should be 0");
+ is(o2.index, 0, "o2.index should be 0");
+}
+
+function test_no_select() {
+ var g1 = document.createElement("optgroup");
+ var o1 = document.createElement("option");
+ g1.appendChild(o1);
+
+ var g2 = document.createElement("optgroup");
+ var o2 = document.createElement("option");
+ g2.appendChild(o2);
+ g1.appendChild(g2);
+
+ is(g1.children.length, 2, "g2 has 2 children");
+ is(g1.children[0], o1, "g1 has 2 children: o1");
+ is(g1.children[1], g2, "g1 has 2 children: g1");
+ is(o1.index, 0, "o1.index should be 0");
+ is(o2.index, 0, "o2.index should be 0");
+}
+
+function test_no_parent() {
+ var o1 = document.createElement("option");
+ var o2 = document.createElement("option");
+
+ is(o1.index, 0, "o1.index should be 0");
+ is(o2.index, 0, "o2.index should be 0");
+}
+
+test_add();
+test_append();
+test_no_select();
+test_no_parent();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1260664.html b/dom/html/test/test_bug1260664.html
new file mode 100644
index 000000000..f03432895
--- /dev/null
+++ b/dom/html/test/test_bug1260664.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1260664
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1260664</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1260664">Mozilla Bug 1260664</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1260664 **/
+SpecialPowers.setBoolPref("network.http.enablePerElementReferrer", true);
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+function runTests() {
+ var elements = [ "iframe", "img", "a", "area", "link" ];
+
+ for (var i = 0; i < elements.length; ++i) {
+ reflectLimitedEnumerated({
+ element: document.createElement(elements[i]),
+ attribute: { content: "referrerpolicy", idl: "referrerPolicy" },
+ validValues: [ "no-referrer",
+ "origin",
+ /** These 2 below values are still invalid, please see
+ Bug 1178337 - Valid referrer attribute values **/
+ /** "no-referrer-when-downgrade",
+ "origin-when-cross-origin", **/
+ "unsafe-url" ],
+ invalidValues: [
+ "", " orIgin ", " unsafe-uRl ", " No-RefeRRer ", " fOoBaR "
+ ],
+ defaultValue: "",
+ });
+ }
+
+ SpecialPowers.clearUserPref("network.http.enablePerElementReferrer");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1260704.html b/dom/html/test/test_bug1260704.html
new file mode 100644
index 000000000..36eead3a2
--- /dev/null
+++ b/dom/html/test/test_bug1260704.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1260704
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1260704</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="text/javascript">
+ /** Test for Bug 1260704 **/
+
+function runTests() {
+ let testIdx = -1;
+ let testUrls = [
+ "bug1260704_iframe.html?noDefault=true&isMap=true",
+ "bug1260704_iframe.html?noDefault=true&isMap=false",
+ "bug1260704_iframe.html?noDefault=false&isMap=true",
+ "bug1260704_iframe.html?noDefault=false&isMap=false"
+ ];
+
+ let runningTest = false;
+ let iframe = document.getElementById("testFrame");
+ let iframeWin = iframe.contentWindow;
+ let rect;
+ let x;
+ let y;
+
+ window.addEventListener("message", event => {
+ if (event.data == "started") {
+ ok(!runningTest, "Start to test " + testIdx);
+ runningTest = true;
+ rect = iframeWin.document.getElementById("testImage").getBoundingClientRect();
+ x = rect.width / 2;
+ y = rect.height / 2;
+ synthesizeMouseAtPoint(rect.left + x, rect.top + y, { type: 'mousedown' }, iframeWin);
+ synthesizeMouseAtPoint(rect.left + x, rect.top + y, { type: 'mouseup' }, iframeWin);
+ }
+ else if (runningTest && event.data == "empty_frame_loaded") {
+ ok(testUrls[testIdx].includes("noDefault=false"), "Page unload");
+ let search = iframeWin.location.search;
+ if (testUrls[testIdx].includes("isMap=true")) {
+ // url trigger by image with ismap attribute should contains coordinates
+ // try to parse coordinates and check them with small tolerance
+ let coorStr = search.split("?");
+ let coordinates = coorStr[1].split(",");
+ ok(Math.abs(coordinates[0] - x) <= 1, "expect X=" + x + " got " + coordinates[0]);
+ ok(Math.abs(coordinates[1] - y) <= 1, "expect Y=" + y + " got " + coordinates[1]);
+ } else {
+ ok(search == "", "expect empty search string got:" + search);
+ }
+ nextTest();
+ }
+ else if (runningTest && event.data == "finished") {
+ ok(testUrls[testIdx].includes("noDefault=true"), "Page should not leave");
+ nextTest();
+ }
+ }, false);
+
+ function nextTest() {
+ testIdx++;
+ runningTest = false;
+ if (testIdx >= testUrls.length) {
+ SimpleTest.finish();
+ } else {
+ ok(true, "Test " + testIdx + " - Set url to " + testUrls[testIdx]);
+ iframeWin.location.href = testUrls[testIdx];
+ }
+ }
+ nextTest();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+ </script>
+</head>
+<body>
+
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<iframe id="testFrame" src="about:blank" width="400" height="400">
+</iframe>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1261673.html b/dom/html/test/test_bug1261673.html
new file mode 100644
index 000000000..006b229e1
--- /dev/null
+++ b/dom/html/test/test_bug1261673.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1261673
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1261673</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1261673">Mozilla Bug 1261673</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<input id="test_number" type="number" value=5>
+<script type="text/javascript">
+
+/** Test for Bug 1261673 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+function runTests() {
+ let input = window.document.getElementById("test_number");
+
+ // focus: whether the target input element is focused
+ // deltaY: deltaY of WheelEvent
+ // deltaMode: deltaMode of WheelEvent
+ // valueChanged: expected value changes after input element handled the wheel event
+ let params = [
+ {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: -1},
+ {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 1},
+ {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE, valueChanged: -1},
+ {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE, valueChanged: 1},
+ {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL, valueChanged: 0},
+ {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL, valueChanged: 0},
+ {focus: false, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 0},
+ {focus: false, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 0}
+ ];
+
+ let testIdx = 0;
+ let result = parseInt(input.value);
+ let numberChange = 0;
+ let expectChange = 0;
+
+ input.addEventListener("change", () => {
+ ++numberChange;
+ }, false);
+
+ function runNext() {
+ let p = params[testIdx];
+ (p["focus"]) ? input.focus() : input.blur();
+ expectChange = p["valueChanged"] == 0 ? expectChange : expectChange + 1;
+ result += parseInt(p["valueChanged"]);
+ synthesizeWheel(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] });
+ window.postMessage("finished", "http://mochi.test:8888");
+ testIdx++;
+ }
+
+ window.addEventListener("message", event => {
+ if (event.data == "finished") {
+ ok(input.value == result,
+ "Handle wheel in number input test-" + testIdx + " expect " + result +
+ " get " + input.value);
+ ok(numberChange == expectChange,
+ "UA should fire change event when input's value changed, expect " + expectChange + " get " + numberChange);
+ (testIdx >= params.length) ? SimpleTest.finish() : runNext();
+ }
+ });
+ runNext();
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1261674-1.html b/dom/html/test/test_bug1261674-1.html
new file mode 100644
index 000000000..3745c1930
--- /dev/null
+++ b/dom/html/test/test_bug1261674-1.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1261674
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1261674</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1261674">Mozilla Bug 1261674</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<input id="test_input" type="range" value=5 max=10 min=0>
+<script type="text/javascript">
+
+/** Test for Bug 1261674 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+function runTests() {
+ let input = window.document.getElementById("test_input");
+
+ // focus: whether the target input element is focused
+ // deltaY: deltaY of WheelEvent
+ // deltaMode: deltaMode of WheelEvent
+ // valueChanged: expected value changes after input element handled the wheel event
+ let params = [
+ {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: -1},
+ {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 1},
+ {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE, valueChanged: -1},
+ {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE, valueChanged: 1},
+ {focus: true, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL, valueChanged: 0},
+ {focus: true, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL, valueChanged: 0},
+ {focus: false, deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 0},
+ {focus: false, deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE, valueChanged: 0}
+ ];
+
+ let testIdx = 0;
+ let result = parseInt(input.value);
+ let rangeChange = 0;
+ let expectChange = 0;
+
+ input.addEventListener("change", () => {
+ ++rangeChange;
+ }, false);
+
+ function runNext() {
+ let p = params[testIdx];
+ (p["focus"]) ? input.focus() : input.blur();
+ expectChange = p["valueChanged"] == 0 ? expectChange : expectChange + 1;
+ result += parseInt(p["valueChanged"]);
+ sendWheelAndPaint(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] }, () => {
+ ok(input.value == result,
+ "Handle wheel in range input test-" + testIdx + " expect " + result + " get " + input.value);
+ ok(rangeChange == expectChange,
+ "UA should fire change event when input's value changed, expect " + expectChange + " get " + rangeChange);
+ (++testIdx >= params.length) ? SimpleTest.finish() : runNext();
+ });
+ }
+
+ input.addEventListener("input", () => {
+ ok(input.value == result,
+ "Test-" + testIdx + " receive input event, expect " + result + " get " + input.value);
+ }, false);
+
+ runNext();
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1261674-2.html b/dom/html/test/test_bug1261674-2.html
new file mode 100644
index 000000000..ffb42ee6d
--- /dev/null
+++ b/dom/html/test/test_bug1261674-2.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1261674
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1261674</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1261674">Mozilla Bug 1261674</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<input id="test_input" type="range" max=0 min=10>
+<script type="text/javascript">
+
+/** Test for Bug 1261674 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+function runTests() {
+ let input = window.document.getElementById("test_input");
+
+ // deltaY: deltaY of WheelEvent
+ // deltaMode: deltaMode of WheelEvent
+ let params = [
+ {deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE},
+ {deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE},
+ {deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE},
+ {deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PAGE},
+ {deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL},
+ {deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_PIXEL},
+ {deltaY: 1.0, deltaMode: WheelEvent.DOM_DELTA_LINE},
+ {deltaY: -1.0, deltaMode: WheelEvent.DOM_DELTA_LINE}
+ ];
+
+ let testIdx = 0;
+ let result = parseInt(input.value);
+ let rangeChange = 0;
+
+ input.addEventListener("change", () => {
+ ++rangeChange;
+ }, false);
+
+ function runNext() {
+ let p = params[testIdx];
+ (p["focus"]) ? input.focus() : input.blur();
+ sendWheelAndPaint(input, 1, 1, { deltaY: p["deltaY"], deltaMode: p["deltaMode"] }, () => {
+ ok(input.value == result,
+ "Handle wheel in range input test-" + testIdx + " expect " + result + " get " + input.value);
+ ok(rangeChange == 0, "Wheel event should not trigger change event when max < min");
+ testIdx++;
+ (testIdx >= params.length) ? SimpleTest.finish() : runNext();
+ });
+ }
+
+ input.addEventListener("input", () => {
+ ok(false, "Wheel event should be no effect to range input element with max < min");
+ }, false);
+
+ runNext();
+}
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1264157.html b/dom/html/test/test_bug1264157.html
new file mode 100644
index 000000000..a087b0f41
--- /dev/null
+++ b/dom/html/test/test_bug1264157.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=535043
+-->
+<head>
+ <title>Test for Bug 535043</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ input {
+ outline: 2px solid lime;
+ }
+ input:in-range {
+ outline: 2px solid red;
+ }
+ input:out-of-range {
+ outline: 2px solid orange;
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=535043">Mozilla Bug 535043</a>
+<p id="display"></p>
+<div id="content">
+
+</head>
+<body>
+ <input type="number" value=0 min=0 max=10> Active in-range
+ <br><br>
+ <input type="number" value=0 min=0 max=10 disabled> Disabled in-range
+ <br><br>
+ <input type="number" value=0 min=0 max=10 readonly> Read-only in-range
+ <br><br>
+ <input type="number" value=11 min=0 max=10> Active out-of-range
+ <br><br>
+ <input type="number" value=11 min=0 max=10 disabled> Disabled out-of-range
+ <br><br>
+ <input type="number" value=11 min=0 max=10 readonly> Read-only out-of-range
+</div>
+<pre id="test">
+<script type="text/javascript">
+
+/** Test for Bug 1264157 **/
+SimpleTest.waitForFocus(function() {
+ // Check the initial values.
+ let active = [].slice.call(document.querySelectorAll("input:not(:disabled):not(:-moz-read-only)"));
+ let disabled = [].slice.call(document.querySelectorAll("input:disabled"));
+ let readonly = [].slice.call(document.querySelectorAll("input:-moz-read-only"));
+ ok(active.length == 2, "Test is messed up: missing non-disabled/non-readonly inputs");
+ ok(disabled.length == 2, "Test is messed up: missing disabled inputs");
+ ok(readonly.length == 2, "Test is messed up: missing readonly inputs");
+
+ is(document.querySelectorAll("input:in-range").length, 1,
+ "Wrong number of in-range elements selected.");
+ is(document.querySelectorAll("input:out-of-range").length, 1,
+ "Wrong number of out-of-range elements selected.");
+
+ // Dynamically change the values to see if that works too.
+ active[0].value = -1;
+ is(document.querySelectorAll("input:in-range").length, 0,
+ "Wrong number of in-range elements selected after value changed.");
+ is(document.querySelectorAll("input:out-of-range").length, 2,
+ "Wrong number of out-of-range elements selected after value changed.");
+ active[0].value = 0;
+ is(document.querySelectorAll("input:in-range").length, 1,
+ "Wrong number of in-range elements selected after value changed back.");
+ is(document.querySelectorAll("input:out-of-range").length, 1,
+ "Wrong number of out-of-range elements selected after value changed back.");
+
+ // Dynamically change the attributes to see if that works too.
+ disabled.forEach(function(e) { e.removeAttribute("disabled"); });
+ readonly.forEach(function(e) { e.removeAttribute("readonly"); });
+ active.forEach(function(e) { e.setAttribute("readonly", true); });
+
+ is(document.querySelectorAll("input:in-range").length, 2,
+ "Wrong number of in-range elements selected after attribute changed.");
+ is(document.querySelectorAll("input:out-of-range").length, 2,
+ "Wrong number of out-of-range elements selected after attribute changed.");
+
+ SimpleTest.finish();
+});
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1287321.html b/dom/html/test/test_bug1287321.html
new file mode 100644
index 000000000..2de0bd0f2
--- /dev/null
+++ b/dom/html/test/test_bug1287321.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1287321
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1287321</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 1287321 **/
+
+ function test() {
+ var r = document.getElementById("range");
+ var rect = r.getBoundingClientRect();
+ var y = parseInt((rect.height / 2));
+ var movement = parseInt(rect.width / 10);
+ var x = movement;
+ synthesizeMouse(r, x, y, { type: "mousedown" });
+ x += movement;
+ var eventCount = 0;
+ r.oninput = function() {
+ ++eventCount;
+ }
+ synthesizeMouse(r, x, y, { type: "mousemove" });
+ is(eventCount, 1, "Got the expected input event");
+
+ x += movement;
+ synthesizeMouse(r, x, y, { type: "mousemove" });
+ is(eventCount, 2, "Got the expected input event");
+
+ synthesizeMouse(r, x, y, { type: "mousemove" });
+ is(eventCount, 2, "Got the expected input event");
+
+ x += movement;
+ synthesizeMouse(r, x, y, { type: "mousemove" });
+ is(eventCount, 3, "Got the expected input event");
+
+ synthesizeMouse(r, x, y, { type: "mouseup" });
+ is(eventCount, 3, "Got the expected input event");
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.waitForFocus(test);
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1287321">Mozilla Bug 1287321</a>
+<input type="range" id="range">
+</body>
+</html>
diff --git a/dom/html/test/test_bug1292522_same_domain_with_different_port_number.html b/dom/html/test/test_bug1292522_same_domain_with_different_port_number.html
new file mode 100644
index 000000000..0dec91558
--- /dev/null
+++ b/dom/html/test/test_bug1292522_same_domain_with_different_port_number.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1292522
+If we set domain using document.domain = "...", a page and iframe must be
+treated as the same domain if they differ in port number,
+e.g. test1.example.org:8000 and test2.example.org:80 are the same domain if
+document.domain = "example.org".
+-->
+<head>
+ <title>Test for Bug 1292522</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1292522">Mozilla Bug 1292522</a>
+ <p id="display"></p>
+
+ <pre id="test">
+ <script class="testbody" type="text/javascript">
+
+ if (navigator.platform.startsWith("Linux")) {
+ SimpleTest.expectAssertions(0, 1);
+ }
+ SimpleTest.waitForExplicitFinish();
+ window.addEventListener("message", onMessageReceived, false);
+
+ var page;
+
+ function onMessageReceived(event)
+ {
+ is(event.data, "testiframe", "Must be able to access the variable," +
+ " because page and iframe are the " +
+ "same domain.");
+ page.close();
+ SimpleTest.finish();
+ }
+
+ page = window.open("http://test1.example.org:8000/tests/dom/html/test/bug1292522_page.html");
+ </script>
+ </pre>
+ </body>
+</html>
diff --git a/dom/html/test/test_bug1295719_event_sequence_for_arrow_keys.html b/dom/html/test/test_bug1295719_event_sequence_for_arrow_keys.html
new file mode 100644
index 000000000..b780cb913
--- /dev/null
+++ b/dom/html/test/test_bug1295719_event_sequence_for_arrow_keys.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1295719
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1295719</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1295719">Mozilla Bug 1295719</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<input id="test_number" type="number" value=50>
+<input id="test_range" type="range" value=50 max=100 min=0>
+<script type="text/javascript">
+
+/** Test for Bug 1295719 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+function runTests() {
+ let number = window.document.getElementById("test_number");
+ let range = window.document.getElementById("test_range");
+ let waiting_event_sequence = ["keydown", "keypress", "input", "change"];
+
+ let waiting_event_idx = 0;
+ waiting_event_sequence.forEach((eventType) => {
+ number.addEventListener(eventType, (event) => {
+ let waiting_event = waiting_event_sequence[waiting_event_idx];
+ is(waiting_event, eventType, "Waiting " + waiting_event + " get " + eventType);
+ // Input element will fire input and change events when handling keypress
+ // with keycode=arrows. When user press and hold the keyboard, we expect
+ // that input element repeatedly fires "keydown", "keypress", "input", and
+ // "change" events until user release the keyboard. Using
+ // waiting_event_sequence as a circular buffer and reset waiting_event_idx
+ // when it point to the end of buffer.
+ waiting_event_idx = waiting_event_idx == waiting_event_sequence.length -1 ? 0 : waiting_event_idx + 1;
+ }, false);
+ range.addEventListener(eventType, (event) => {
+ let waiting_event = waiting_event_sequence[waiting_event_idx];
+ is(waiting_event, eventType, "Waiting " + waiting_event + " get " + eventType);
+ waiting_event_idx = waiting_event_idx == waiting_event_sequence.length - 1 ? 0 : waiting_event_idx + 1;
+ }, false);
+ });
+
+ number.focus();
+ synthesizeKey("VK_DOWN", {type: "keydown"});
+ synthesizeKey("VK_DOWN", {type: "keydown"});
+ synthesizeKey("VK_DOWN", {type: "keyup"});
+ number.blur();
+ range.focus();
+ waiting_event_idx = 0;
+ synthesizeKey("VK_DOWN", {type: "keydown"});
+ synthesizeKey("VK_DOWN", {type: "keydown"});
+ synthesizeKey("VK_DOWN", {type: "keyup"});
+
+ SimpleTest.finish();
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1295719_event_sequence_for_number_keys.html b/dom/html/test/test_bug1295719_event_sequence_for_number_keys.html
new file mode 100644
index 000000000..2dac8c55b
--- /dev/null
+++ b/dom/html/test/test_bug1295719_event_sequence_for_number_keys.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1295719
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 1295719</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1295719">Mozilla Bug 1295719</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<input id="test_number" type="number" value=50>
+<script type="text/javascript">
+
+/** Test for Bug 1295719 **/
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTests);
+
+function runTests() {
+ let number = window.document.getElementById("test_number");
+ let waiting_event_sequence = ["keydown", "keypress", "input"];
+ let change_event_of_number = 0;
+ let keyup_event_of_number = 0;
+ let waiting_event_idx = 0;
+ waiting_event_sequence.forEach((eventType) => {
+ number.addEventListener(eventType, (event) => {
+ let waiting_event = waiting_event_sequence[waiting_event_idx];
+ is(eventType, waiting_event, "Waiting " + waiting_event + " get " + eventType);
+ // Input element will fire input event when handling keypress with
+ // keycode=numbers. When user press and hold the keyboard, we expect that
+ // input element repeatedly fires "keydown", "keypress", and "input" until
+ // user release the keyboard. Input element will fire change event when
+ // it's blurred. Using waiting_event_sequence as a circular buffer and
+ // reset waiting_event_idx when it point to the end of buffer.
+ waiting_event_idx = waiting_event_idx == waiting_event_sequence.length - 1 ? 0 : waiting_event_idx + 1;
+ }, false);
+ });
+ number.addEventListener("change", (event) => {
+ is(keyup_event_of_number, 1, "change event should be fired after blurred");
+ ++change_event_of_number;
+ }, false);
+ number.addEventListener("keyup", (event) => {
+ is(keyup_event_of_number, 0, "keyup event should be fired once");
+ is(change_event_of_number, 0, "keyup event should be fired before change event");
+ ++keyup_event_of_number;
+ }, false);
+ number.focus();
+ synthesizeKey("5", {type: "keydown"});
+ synthesizeKey("5", {type: "keydown"});
+ synthesizeKey("5", {type: "keyup"});
+ is(change_event_of_number, 0, "change event shouldn't be fired when input element is focused");
+ number.blur();
+ is(change_event_of_number, 1, "change event should be fired when input element is blurred");
+ SimpleTest.finish();
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1297.html b/dom/html/test/test_bug1297.html
new file mode 100644
index 000000000..8b9dc3039
--- /dev/null
+++ b/dom/html/test/test_bug1297.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1297
+-->
+<head>
+ <title>Test for Bug 1297</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1297">Mozilla Bug 1297</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<table border=1>
+<tr>
+<td id="td1" onmousedown="alert(this.cellIndex)">cellIndex=0</td>
+<td id="td2" onmousedown="alert(this.cellIndex)">cellIndex=1</td>
+<td id="td3" onmousedown="alert(this.cellIndex)">cellIndex=2</td>
+<tr id="tr1"
+onmousedown="alert(this.rowIndex)"><td>rowIndex=1<td>rowIndex=1<td>rowIndex=1</t
+r>
+<tr id="tr2"
+onmousedown="alert(this.rowIndex)"><td>rowIndex=2<td>rowIndex=2<td>rowIndex=2</t
+r>
+</tr>
+</table>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 1297 **/
+is($('td1').cellIndex, 0, "cellIndex / rowIndex working td1");
+is($('td2').cellIndex, 1, "cellIndex / rowIndex working td2");
+is($('td3').cellIndex, 2, "cellIndex / rowIndex working td3");
+is($('tr1').rowIndex, 1, "cellIndex / rowIndex working tr1");
+is($('tr2').rowIndex, 2, "cellIndex / rowIndex working tr2");
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug1310865.html b/dom/html/test/test_bug1310865.html
new file mode 100644
index 000000000..4dcccbfa0
--- /dev/null
+++ b/dom/html/test/test_bug1310865.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Test for Bug 1310865</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<script src="/tests/SimpleTest/EventUtils.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css">
+<input value="a
+b" type="hidden">
+<input type="hidden" value="a
+b">
+<script>
+var input1 = document.querySelector("input");
+var input2 = document.querySelector("input + input");
+var clone1 = input1.cloneNode(false);
+var clone2 = input2.cloneNode(false);
+// Newlines must not be stripped
+is(clone1.value, "a\nb");
+is(clone2.value, "a\nb");
+</script>
diff --git a/dom/html/test/test_bug1315146.html b/dom/html/test/test_bug1315146.html
new file mode 100644
index 000000000..261b815b5
--- /dev/null
+++ b/dom/html/test/test_bug1315146.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1315146
+-->
+<head>
+ <title>Test for Bug 1315146</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1315146">Mozilla Bug 1315146</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 1315146 **/
+
+SimpleTest.waitForExplicitFinish();
+onmessage = function(e) {
+ win.close();
+ is(e.data.start, 2, "Correct start offset expected");
+ is(e.data.end, 2, "Correct end offset expected");
+ SimpleTest.finish();
+};
+let win = window.open("http://test1.example.org/tests/dom/html/test/bug1315146-main.html", "_blank");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1366.html b/dom/html/test/test_bug1366.html
new file mode 100644
index 000000000..f5b4f880d
--- /dev/null
+++ b/dom/html/test/test_bug1366.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1366
+-->
+<head>
+ <title>Test for Bug 1366</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1366">Mozilla Bug 1366</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<table id="testtable" width=150 border>
+ <tbody id="testbody">
+ <tr>
+ <td>cell content</td>
+ </tr>
+ </tbody>
+</table>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 1366 **/
+$('testtable').removeChild($('testbody'));
+$('display').innerHTML = "SCRIPT: deleted first ROWGROUP\n";
+is($('testbody'), null, "deleting tbody works");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug1400.html b/dom/html/test/test_bug1400.html
new file mode 100644
index 000000000..12f36833b
--- /dev/null
+++ b/dom/html/test/test_bug1400.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1400
+-->
+<head>
+ <title>Test for Bug 1400</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1400">Mozilla Bug 1400</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 1400 **/
+
+table = document.createElement("TABLE");
+thead = table.createTHead();
+thead2 = table.createTHead();
+
+table.appendChild(thead);
+table.appendChild(thead);
+table.appendChild(thead);
+table.appendChild(thead2);
+table.appendChild(thead2);
+table.appendChild(thead2);
+table.appendChild(thead);
+table.appendChild(thead2);
+
+is(table.childNodes.length, 1,
+ "adding multiple theads results in one thead child");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug143220.html b/dom/html/test/test_bug143220.html
new file mode 100644
index 000000000..355e91ea2
--- /dev/null
+++ b/dom/html/test/test_bug143220.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=143220
+-->
+<head>
+ <title>Test for Bug 143220</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=143220">Mozilla Bug 143220</a>
+<p id="display">
+ <input type="file" id="i1">
+ <input type="file" id="i2">
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript;version=1.7">
+
+/** Test for Bug 143220 **/
+SimpleTest.waitForExplicitFinish();
+const helperURL = SimpleTest.getTestFileURL("simpleFileOpener.js");
+const helper = SpecialPowers.loadChromeScript(helperURL);
+helper.addMessageListener("fail", function onFail(message) {
+ is(message, null, "chrome script failed");
+ SimpleTest.finish();
+});
+helper.addMessageListener("file.opened", onFileOpened);
+helper.sendAsyncMessage("file.open", "test_bug143220.txt");
+
+function onFileOpened(message) {
+ const { leafName, fullPath, domFile } = message;
+
+ function initControl1() {
+ SpecialPowers.wrap($("i1")).mozSetFileArray([domFile]);
+ }
+
+ function initControl2() {
+ SpecialPowers.wrap($("i2")).mozSetFileArray([domFile]);
+ }
+
+ // Check that we can't just set the value
+ try {
+ $("i1").value = fullPath;
+ is(0, 1, "Should have thrown exception on set!");
+ } catch(e) {
+ is($("i1").value, "", "Shouldn't have value here");
+ }
+
+ initControl1();
+ initControl2();
+
+ is($("i1").value, leafName, "Leaking full value?");
+ is($("i2").value, leafName, "Leaking full value?");
+
+ helper.addMessageListener("file.removed", onFileRemoved);
+ helper.sendAsyncMessage("file.remove", null);
+}
+
+function onFileRemoved() {
+ helper.destroy();
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug1682.html b/dom/html/test/test_bug1682.html
new file mode 100644
index 000000000..c8e5b830d
--- /dev/null
+++ b/dom/html/test/test_bug1682.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1682
+-->
+<head>
+ <title>Test for Bug 1682</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1682">Mozilla Bug 1682</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 1682 **/
+var count = 1;
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function () {
+ is(count, 1, "onload executes once");
+ ++count;
+});
+addLoadEvent(SimpleTest.finish);
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug172261.html b/dom/html/test/test_bug172261.html
new file mode 100644
index 000000000..2b5d752cd
--- /dev/null
+++ b/dom/html/test/test_bug172261.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=172261
+-->
+<head>
+ <title>Test for Bug 172261</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=172261">Mozilla Bug 172261</a>
+<p id="display">
+ <iframe id="test"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+ /** Test for Bug 172261 **/
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("untriaged");
+
+ var callable = false;
+ function toggleCallable() { callable = true; }
+
+ var doTestInIframe = false;
+
+ // Shouldn't do history stuff from inside onload
+ addLoadEvent(function() { setTimeout(startTest, 10) });
+
+ function startTest() {
+ // First, create a dummy document. Use onunload handlers to make sure
+ // bfcache doesn't screw us up.
+ var doc = $("test").contentDocument;
+
+ doc.write("<html><body onunload=''>First</body></html>");
+ doc.close();
+
+ // Now write our test document
+ doc.write("<html><script>window.onerror = parent.onerror; if (parent.doTestInIframe) { parent.is(document.domain, parent.document.domain, 'Domains should match'); parent.toggleCallable(); } <" + "/script><body>Second</body></html>");
+ doc.close();
+
+ $("test").onload = goForward;
+ history.back();
+ }
+
+ function goForward() {
+ $("test").onload = doTest;
+ doTestInIframe = true;
+ history.forward();
+ }
+
+ function doTest() {
+ is($("test").contentDocument.domain, document.domain,
+ "Domains should match 2");
+ is($("test").contentDocument.location.href, location.href,
+ "Locations should match");
+ is(callable, true, "Subframe should be able to call us");
+ SimpleTest.finish();
+ }
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug182279.html b/dom/html/test/test_bug182279.html
new file mode 100644
index 000000000..56c73a676
--- /dev/null
+++ b/dom/html/test/test_bug182279.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=182279
+-->
+<head>
+ <title>Test for Bug 182279</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=182279">Moozilla Bug 182279</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+/** Test for Bug 182279 **/
+var sel = document.createElement("select");
+var opt1 = new Option();
+var opt2 = new Option();
+var opt3 = new Option();
+opt1.value = 1;
+opt2.value = 2;
+opt3.value = 3;
+sel.add(opt1, null);
+sel.add(opt2, opt1);
+sel.add(opt3);
+is(sel[0], opt2, "1st item should be 2");
+is(sel[1], opt1, "2nd item should be 1");
+is(sel[2], opt3, "3rd item should be 3");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug1823.html b/dom/html/test/test_bug1823.html
new file mode 100644
index 000000000..1297b0dd6
--- /dev/null
+++ b/dom/html/test/test_bug1823.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1823
+-->
+<head>
+ <title>Test for Bug 1823</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1823">Mozilla Bug 1823</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 1823 **/
+ok((document.location + "").indexOf("[") == -1, "location object has a toString()");
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug196523.html b/dom/html/test/test_bug196523.html
new file mode 100644
index 000000000..a380fe06c
--- /dev/null
+++ b/dom/html/test/test_bug196523.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=196523
+-->
+<head>
+ <title>Test for Bug 196523</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=196523">Mozilla Bug 196523</a>
+<script>
+ var expectedMessages = 2;
+ SimpleTest.waitForExplicitFinish();
+ window.addEventListener("message", function(e) {
+ --expectedMessages;
+ var str = e.data;
+ var idx = str.indexOf(';');
+ var val = str.substring(0, idx);
+ var msg = str.substring(idx+1);
+ ok(val == "true", msg);
+ if (!expectedMessages) { SimpleTest.finish(); }
+ }, false);
+</script>
+<p id="display">
+ <iframe src="http://test1.example.org/tests/dom/html/test/bug196523-subframe.html"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 196523 **/
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug199692.html b/dom/html/test/test_bug199692.html
new file mode 100644
index 000000000..91f99ccc4
--- /dev/null
+++ b/dom/html/test/test_bug199692.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=199692
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Test for Bug 199692</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+
+ // The popup calls MochiTest methods in this window through window.opener
+ window.open("bug199692-popup.html", "bug199692", "width=600,height=600");
+ </script>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug2082.html b/dom/html/test/test_bug2082.html
new file mode 100644
index 000000000..b693e96d1
--- /dev/null
+++ b/dom/html/test/test_bug2082.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=2082
+-->
+<head>
+ <title>Test for Bug 2082</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=2082">Mozilla Bug 2082</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<FORM name="gui" id="gui">
+<INPUT TYPE="text" NAME="field" VALUE="some value">
+</FORM>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 2082 **/
+var guiform = document.getElementById("gui");
+ok(document.getElementById("gui").hasChildNodes(), "form elements should be treated as form's children");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug209275.xhtml b/dom/html/test/test_bug209275.xhtml
new file mode 100644
index 000000000..f74e5e5fb
--- /dev/null
+++ b/dom/html/test/test_bug209275.xhtml
@@ -0,0 +1,261 @@
+<!DOCTYPE html [
+<!ATTLIST foo:base
+ id ID #IMPLIED
+>
+]>
+<html xmlns:foo="http://foo.com" xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=209275
+-->
+<head>
+ <title>Test for Bug 209275</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <style>
+ @namespace svg url("http://www.w3.org/2000/svg");
+ svg|a { fill:blue; }
+ svg|a:visited { fill:purple; }
+ </style>
+
+ <!--
+ base0 should be ignored because it's not in the XHTML namespace
+ -->
+ <foo:base id="base0" href="http://www.foo.com" />
+
+ <!--
+ baseEmpty should be ignored because it has no href and never gets one.
+ -->
+ <base id="baseEmpty" />
+
+ <!--
+ baseWrongAttrNS should be ignored because its href attribute isn't in the empty
+ namespace.
+ -->
+ <base id="baseWrongAttrNS" foo:href="http://foo.com" />
+
+ <base id="base1" />
+ <base id="base2" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=209275">Mozilla Bug 209275</a>
+<p id="display">
+</p>
+<div id="content">
+ <a href="/" id="link1">link1</a>
+ <div style="display:none">
+ <a href="/" id="link2">link2</a>
+ </div>
+ <a href="/" id="link3" style="display:none">link3</a>
+ <a href="#" id="link4">link4</a>
+ <a href="" id="colorlink">colorlink</a>
+ <a href="#" id="link5">link5</a>
+ <iframe id="iframe"></iframe>
+
+ <svg width="5cm" height="3cm" viewBox="0 0 5 3" version="1.1"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink">
+ <a xlink:href="" id="ellipselink">
+ <ellipse cx="2.5" cy="1.5" rx="2" ry="1" id="ellipse" />
+ </a>
+ </svg>
+
+</div>
+<pre id="test">
+<script type="text/javascript;version=1.7">
+<![CDATA[
+
+/** Test for Bug 209275 **/
+SimpleTest.waitForExplicitFinish();
+
+function link123HrefIs(href, testNum) {
+ is($('link1').href, href, "link1 test " + testNum);
+ is($('link2').href, href, "link2 test " + testNum);
+ is($('link3').href, href, "link3 test " + testNum);
+}
+
+var gGen;
+
+function visitedDependentComputedStyle(win, elem, property) {
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ return utils.getVisitedDependentComputedStyle(elem, "", property);
+}
+
+function getColor(elem) {
+ return visitedDependentComputedStyle(document.defaultView, elem, "color");
+}
+
+function getFill(elem) {
+ return visitedDependentComputedStyle(document.defaultView, elem, "fill");
+}
+
+function setXlinkHref(elem, href) {
+ elem.setAttributeNS("http://www.w3.org/1999/xlink", "href", href);
+}
+
+function continueTest() {
+ gGen.next();
+}
+
+var iframe = document.getElementById("iframe");
+var iframeCw = iframe.contentWindow;
+
+function run() {
+ var iframe = document.getElementById("iframe");
+ var iframeCw = iframe.contentWindow;
+
+ // First, set the visited/unvisited link/ellipse colors.
+ const unvisitedColor = "rgb(0, 0, 238)";
+ const visitedColor = "rgb(85, 26, 139)";
+ const unvisitedFill = "rgb(0, 0, 255)";
+ const visitedFill = "rgb(128, 0, 128)";
+
+ const rand = Date.now() + "-" + Math.random();
+
+ // Now we can start the tests in earnest.
+
+ var loc = location;
+ // everything from the location up to and including the final forward slash
+ var path = /(.*\/)[^\/]*/.exec(location)[1];
+
+ // Set colorlink's href so we can check that it changes colors after we
+ // change the base href.
+ $('colorlink').href = "http://example.com/" + rand;
+ setXlinkHref($("ellipselink"), "http://example.com/" + rand);
+
+ // Load http://example.com/${rand} into an iframe so we can test that changing
+ // the document's base changes the visitedness of our links.
+ iframe.onload = continueTest;
+ iframeCw.location = "http://example.com/" + rand;
+ yield undefined; // wait for onload to fire.
+
+ // Make sure things are what as we expect them at the beginning.
+ link123HrefIs("http://mochi.test:8888/", 1);
+ is($('link4').href, loc + "#", "link 4 test 1");
+ is($('link5').href, loc + "#", "link 5 test 1");
+
+ // Remove link5 from the document. We're going to test that its href changes
+ // properly when we change our base.
+ var link5 = $('link5');
+ link5.parentNode.removeChild(link5);
+
+ $('base1').href = "http://example.com";
+
+ // Were the links' hrefs updated after the base change?
+ link123HrefIs("http://example.com/", 2);
+ is($('link4').href, "http://example.com/#", "link 4 test 2");
+ is(link5.href, "http://example.com/#", "link 5 test 2");
+
+ // Were colorlink's color and ellipse's fill updated appropriately?
+ // Because link coloring is asynchronous, we wait until it is updated (or we
+ // timeout and fail anyway).
+ while (getColor($('colorlink')) != visitedColor) {
+ setTimeout(continueTest, 0);
+ yield undefined;
+ }
+ is(getColor($('colorlink')), visitedColor,
+ "Wrong link color after base change.");
+ while (getFill($('ellipselink')) != visitedFill) {
+ setTimeout(continueTest, 0);
+ yield undefined;
+ }
+ is(getFill($('ellipselink')), visitedFill,
+ "Wrong ellipse fill after base change.");
+
+ $('base1').href = "foo/";
+ // Should be interpreted relative to current URI (not the current base), so
+ // base should now be http://mochi.test:8888/foo/
+
+ link123HrefIs("http://mochi.test:8888/", 3);
+ is($('link4').href, path + "foo/#", "link 4 test 3");
+
+ // Changing base2 shouldn't affect anything, because it's not the first base
+ // tag.
+ $('base2').href = "http://example.org/bar/";
+ link123HrefIs("http://mochi.test:8888/", 4);
+ is($('link4').href, path + "foo/#", "link 4 test 4");
+
+ // If we unset base1's href attribute, the document's base should come from
+ // base2, whose href is http://example.org/bar/.
+ $('base1').removeAttribute("href");
+ link123HrefIs("http://example.org/", 5);
+ is($('link4').href, "http://example.org/bar/#", "link 4 test 5");
+
+ // If we remove base1, base2 should become the first base tag, and the hrefs
+ // of all the links should change accordingly.
+ $('base1').parentNode.removeChild($('base1'));
+ link123HrefIs("http://example.org/", 6);
+ is($('link4').href, "http://example.org/bar/#", "link 4 test 6");
+
+ // If we add a new base after base2, nothing should change.
+ var base3 = document.createElement("base");
+ base3.href = "http://base3.example.org/";
+ $('base2').parentNode.insertBefore(base3, $('base2').nextSibling);
+ link123HrefIs("http://example.org/", 7);
+ is($('link4').href, "http://example.org/bar/#", "link 4 test 7");
+
+ // But now if we add a new base before base 2, it should become the primary
+ // base.
+ var base4 = document.createElement("base");
+ base4.href = "http://base4.example.org/";
+ $('base2').parentNode.insertBefore(base4, $('base2'));
+ link123HrefIs("http://base4.example.org/", 8);
+ is($('link4').href, "http://base4.example.org/#", "link 4 test 8");
+
+ // Now if we remove all the base tags, the base should become the page's URI
+ // again.
+ $('base2').parentNode.removeChild($('base2'));
+ base3.parentNode.removeChild(base3);
+ base4.parentNode.removeChild(base4);
+
+ link123HrefIs("http://mochi.test:8888/", 9);
+ is($('link4').href, loc + "#", "link 4 test 9");
+
+ // Setting the href of base0 shouldn't do anything because it's not in the
+ // XHTML namespace.
+ $('base0').href = "http://bar.com";
+ link123HrefIs("http://mochi.test:8888/", 10);
+ is($('link4').href, loc + "#", "link 4 test 10");
+
+ // We load into an iframe a document with a <base href="...">, then remove
+ // the document element. Then we add an <html>, <body>, and <a>, and make
+ // sure that the <a> is resolved relative to the page's location, not its
+ // original base. We do this twice, rebuilding the document in a different
+ // way each time.
+
+ iframe.onload = null;
+ iframeCw.location = "file_bug209275_1.html";
+ yield undefined; // wait for our child to call us back.
+ is(iframeCw.document.getElementById("link").href,
+ path + "file_bug209275_1.html#",
+ "Wrong href after nuking document.");
+
+ iframeCw.location = "file_bug209275_2.html";
+ yield undefined; // wait for callback from child
+ is(iframeCw.document.getElementById("link").href,
+ "http://mochi.test:8888/",
+ "Wrong href after nuking document second time.");
+
+ // Make sure that document.open() makes the document forget about any <base>
+ // tags it has.
+ iframeCw.location = "file_bug209275_3.html";
+ yield undefined; // wait for callback from child
+ is(iframeCw.document.getElementById("link").href,
+ "http://mochi.test:8888/",
+ "Wrong href after document.open().");
+
+ SimpleTest.finish();
+ yield undefined;
+}
+
+window.addEventListener("load", function() {
+ gGen = run();
+ gGen.next();
+}, false);
+
+]]>
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug237071.html b/dom/html/test/test_bug237071.html
new file mode 100644
index 000000000..82bb68dbc
--- /dev/null
+++ b/dom/html/test/test_bug237071.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=237071
+-->
+<head>
+ <title>Test for Bug 237071</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=237071">Mozilla Bug 237071</a>
+<p id="display"></p>
+<div id="content" >
+ <ol id="theOL" start="22">
+ <li id="foo" >should be 22</li>
+ <li id="foo23">should be 23</li>
+ </ol>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+/** Test for Bug 237071 **/
+is($('theOL').start, 22, "OL start attribute mapped to .start, not just text attribute");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug242709.html b/dom/html/test/test_bug242709.html
new file mode 100644
index 000000000..af49eb93c
--- /dev/null
+++ b/dom/html/test/test_bug242709.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=242709
+-->
+<head>
+ <title>Test for Bug 242709</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=242709">Mozilla Bug 242709</a>
+<p id="display"></p>
+<div id="content">
+<iframe src="bug242709_iframe.html" id="a"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 242709 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var submitted = function() {
+ ok(true, "Disabling button after form submission doesn't prevent submitting");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug24958.html b/dom/html/test/test_bug24958.html
new file mode 100644
index 000000000..3d62dae18
--- /dev/null
+++ b/dom/html/test/test_bug24958.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=24958
+-->
+<head>
+ <title>Test for Bug 24958</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <SCRIPT id="foo" TYPE="text/javascript">/*This space intentionally left blank*/</SCRIPT>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=24958">Mozilla Bug 24958</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 24958 **/
+ok($("foo").text, "\/*This space intentionally left blank*\/", "HTMLScriptElement.text should return text")
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug255820.html b/dom/html/test/test_bug255820.html
new file mode 100644
index 000000000..20727fee4
--- /dev/null
+++ b/dom/html/test/test_bug255820.html
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=255820
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Test for Bug 255820</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=255820">Mozilla Bug 255820</a>
+<p id="display">
+ <iframe id="f1"></iframe>
+ <iframe id="f2"></iframe>
+ <iframe id="f3"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 255820 **/
+SimpleTest.waitForExplicitFinish();
+
+is(document.characterSet, "UTF-8",
+ "Unexpected character set for our document");
+
+var testsLeft = 4;
+
+function testFinished() {
+ --testsLeft;
+ if (testsLeft == 0) {
+ SimpleTest.finish();
+ }
+}
+
+function charsetTestFinished(id, doc, charsetTarget) {
+ is(doc.characterSet, charsetTarget, "Unexpected charset for subframe " + id);
+ testFinished();
+}
+
+function f2Continue() {
+// Commented out pending discussion at the WHATWG
+// $("f2").
+// setAttribute("onload",
+// "charsetTestFinished('f2 reloaded', this.contentDocument, 'us-ascii');");
+ $("f2").
+ setAttribute("onload",
+ "testFinished();");
+ $("f2").contentWindow.location.reload();
+}
+
+function f3Continue() {
+ var doc = $("f3").contentDocument;
+ is(doc.defaultView.getComputedStyle(doc.body, "").color, "rgb(0, 180, 0)",
+ "Wrong color before reload");
+ $("f3").
+ setAttribute("onload",
+ 'var doc = this.contentDocument; ' +
+ 'is(doc.defaultView.getComputedStyle(doc.body, "").color, ' +
+ ' "rgb(0, 180, 0)",' +
+ ' "Wrong color after reload");' +
+ "charsetTestFinished('f1', this.contentDocument, 'UTF-8')");
+ $("f3").contentWindow.location.reload();
+}
+
+function runTest() {
+ var doc = $("f1").contentDocument;
+ is(doc.characterSet, "UTF-8",
+ "Unexpected initial character set for first frame");
+ doc.open();
+ doc.write('<html></html>');
+ doc.close();
+ is(doc.characterSet, "UTF-8",
+ "Unexpected character set for first frame after write");
+ $("f1").
+ setAttribute("onload",
+ "charsetTestFinished('f1', this.contentDocument, 'UTF-8')");
+ $("f1").contentWindow.location.reload();
+
+ doc = $("f2").contentDocument;
+ is(doc.characterSet, "UTF-8",
+ "Unexpected initial character set for second frame");
+ doc.open();
+ var str = '<html><head>';
+ str += '<script src="data:application/javascript,"><'+'/script>';
+ str += '<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">';
+ str += '</head><body>';
+ str += '</body></html>';
+ doc.write(str);
+ doc.close();
+ is(doc.characterSet, "UTF-8",
+ "Unexpected character set for second frame after write");
+ $("f2").
+ setAttribute("onload",
+ "charsetTestFinished('f2', this.contentDocument, 'UTF-8');" +
+ "f2Continue()");
+
+ doc = $("f3").contentDocument;
+ is(doc.characterSet, "UTF-8",
+ "Unexpected initial character set for first frame");
+ doc.open();
+ var str = '<html><head>';
+ str += '<style>body { color: rgb(255, 0, 0) }</style>';
+ str += '<link type="text/css" rel="stylesheet" href="data:text/css, body { color: rgb(0, 180, 0) }">';
+ str += '</head><body>';
+ str += '</body></html>';
+ doc.write(str);
+ doc.close();
+ is(doc.characterSet, "UTF-8",
+ "Unexpected character set for first frame after write");
+ $("f3").setAttribute("onload", "f3Continue()");
+}
+
+addLoadEvent(runTest);
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug259332.html b/dom/html/test/test_bug259332.html
new file mode 100644
index 000000000..a0ad61f40
--- /dev/null
+++ b/dom/html/test/test_bug259332.html
@@ -0,0 +1,64 @@
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=259332
+-->
+<head>
+ <title>Test for Bug 259332</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=259332">Mozilla Bug 259332</a>
+<p id="display"></p>
+<div id="content">
+ <div id="a">a
+ <div id="a">a</div>
+ <input name="a" value="a">
+ <div id="b">b</div>
+ <input name="b" value="b">
+ <div id="c">c</div>
+ </div>
+ <input name="write">
+ <input name="write">
+ <input id="write">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 259332 **/
+
+list = document.all.a;
+ok(list.length == 3, "initial a length");
+
+blist = document.all.b;
+ok(document.all.b.length == 2, "initial b length");
+document.getElementById('b').id = 'a';
+ok(document.all.b.nodeName == "INPUT", "just one b");
+
+ok(blist.length == 1, "just one b");
+ok(list.length == 4, "one more a");
+
+newDiv = document.createElement('div');
+newDiv.id = 'a';
+newDiv.innerHTML = 'a';
+list[0].appendChild(newDiv);
+ok(list.length == 5, "two more a");
+
+ok(document.all.c.textContent == 'c', "one c");
+document.all.c.id = 'a';
+ok(!document.all.c, "no c");
+ok(list.length == 6, "three more a");
+
+ok(document.all.write.length == 3, "name is write");
+
+newDiv = document.createElement('div');
+newDiv.id = 'd';
+newDiv.innerHTML = 'd';
+list[0].appendChild(newDiv);
+ok(document.all.d.textContent == 'd', "new d");
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug274626.html b/dom/html/test/test_bug274626.html
new file mode 100644
index 000000000..f4f045b21
--- /dev/null
+++ b/dom/html/test/test_bug274626.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=274626
+-->
+<head>
+ <title>Test for Bug 274626</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=274626">Mozilla Bug 274626</a>
+<br>
+
+<input id='textbox_enabled' title='hello' value='hello' />
+<input id='textbox_disabled' title='hello' value='hello' disabled/>
+
+<br>
+<input id='input_button_enabled' title='hello' value='hello' type='button' />
+<input id='input_button_disabled' title='hello' value='hello' type='button' disabled />
+
+<br>
+<input id='checkbox_enabled' title='hello' type='checkbox'>hello</input>
+<input id='checkbox_disabled' title='hello' type='checkbox' disabled >hello</input>
+
+<br>
+<button id='button_enabled' title='hello' value='hello' type='button'>test</button>
+<button id='button_disabled' title='hello' value='hello' type='button' disabled>test</button>
+
+<br>
+<textarea id='textarea_enabled' title='hello' value='hello' onclick="alert('click event');"> </textarea>
+<textarea id='textarea_disabled' title='hello' value='hello' onclick="alert('click event');" disabled></textarea>
+
+
+<br>
+<select id='select_enabled' title='hello' onclick="alert('click event');">
+ <option value='item1'>item1</option>
+ <option value='item2'>item2</option>
+</select>
+<select id='select_disabled' title='hello' onclick="alert('click event');" disabled>
+ <option value='item1'>item1</option>
+ <option value='item2'>item2</option>
+</select>
+
+<br>
+<form>
+ <fieldset id='fieldset_enabled' title='hello' onclick="alert('click event');">
+ <legend>Enabled fieldset:</legend>
+ Name: <input type='text' size='30' /><br />
+ Email: <input type='text' size='30' /><br />
+ Date of birth: <input type='text' size='10' />
+ </fieldset>
+</form>
+<form>
+ <fieldset id='fieldset_disabled' title='hello' onclick="alert('click event');" disabled>
+ <legend>Disabled fieldset:</legend>
+ Name: <input type='text' size='30' /><br />
+ Email: <input type='text' size='30' /><br />
+ Date of birth: <input type='text' size='10' />
+ </fieldset>
+</form>
+
+<script class="testbody" type="application/javascript">
+
+/** Test for Bug 274626 **/
+
+ function HandlesMouseMove(evt) {
+ evt.target.handlesMouseMove = true;
+ }
+
+ var controls=["textbox_enabled","textbox_disabled",
+ "input_button_enabled", "input_button_disabled", "checkbox_enabled",
+ "checkbox_disabled", "button_enabled", "button_disabled",
+ "textarea_enabled", "textarea_disabled", "select_enabled",
+ "select_disabled", "fieldset_enabled", "fieldset_disabled"];
+
+ for (id of controls) {
+ var ctrl = document.getElementById(id);
+ ctrl.addEventListener('mousemove', HandlesMouseMove, false);
+ ctrl.handlesMouseMove = false;
+ var evt = document.createEvent("MouseEvents");
+ evt.initMouseEvent("mousemove", true, true, window,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ ctrl.dispatchEvent(evt);
+
+ // Mouse move events are what causes tooltips to show up.
+ // Before this fix we would not allow mouse move events to go through
+ // which in turn did not allow tooltips to be displayed.
+ // This test will ensure that all HTML elements handle mouse move events
+ // so that tooltips can be displayed
+ ok(ctrl.handlesMouseMove, "Disabled element need mouse move for tooltips");
+ }
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug277724.html b/dom/html/test/test_bug277724.html
new file mode 100644
index 000000000..39b54cb7d
--- /dev/null
+++ b/dom/html/test/test_bug277724.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=277724
+-->
+<head>
+ <title>Test for Bug 277724</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=277724">Mozilla Bug 277724</a>
+<p id="display"></p>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 277724 **/
+
+var childUnloaded = false;
+
+var nodes = [
+ [ "select", HTMLSelectElement ],
+ [ "textarea", HTMLTextAreaElement ],
+ [ "text", HTMLInputElement ],
+ [ "password", HTMLInputElement ],
+ [ "checkbox", HTMLInputElement ],
+ [ "radio", HTMLInputElement ],
+ [ "image", HTMLInputElement ],
+ [ "submit", HTMLInputElement ],
+ [ "reset", HTMLInputElement ],
+ [ "button input", HTMLInputElement ],
+ [ "hidden", HTMLInputElement ],
+ [ "file", HTMLInputElement ],
+ [ "submit button", HTMLButtonElement ],
+ [ "reset button", HTMLButtonElement ],
+ [ "button", HTMLButtonElement ]
+];
+
+function soon(f) {
+ return function() { setTimeout(f, 0); }
+}
+
+function startTest(frameid) {
+ is(childUnloaded, false, "Child not unloaded yet");
+
+ var doc = $(frameid).contentDocument;
+ ok(doc instanceof Document, "Check for doc", "doc should be a document");
+
+ for (var i = 0; i < nodes.length; ++i) {
+ var id = nodes[i][0];
+ var node = doc.getElementById(id);
+ ok(node instanceof nodes[i][1],
+ "Check for " + id, id + " should be a " + nodes[i][1]);
+ is(node.disabled, false, "check for " + id + " state");
+ node.disabled = true;
+ is(node.disabled, true, "check for " + id + " state change");
+ }
+
+ $(frameid).onload = soon(function() { continueTest(frameid) });
+
+ // Do this off a timeout so it's not treated like a replace load.
+ function loadBlank() {
+ $(frameid).contentWindow.location = "about:blank";
+ }
+ setTimeout(loadBlank, 0);
+}
+
+function continueTest(frameid) {
+ is(childUnloaded, true, "Unload handler should have fired");
+ var doc = $(frameid).contentDocument;
+ ok(doc instanceof Document, "Check for doc", "doc should be a document");
+
+ for (var i = 0; i < nodes.length; ++i) {
+ var id = nodes[i][0];
+ var node = doc.getElementById(id);
+ ok(node === null,
+ "Check for " + id, id + " should be null");
+ }
+
+ $(frameid).onload = soon(function() { finishTest(frameid); });
+
+ // Do this off a timeout too. Why, I'm not sure. Something in session
+ // history creates another history state if we don't. :(
+ function goBack() {
+ $(frameid).contentWindow.history.back();
+ }
+ setTimeout(goBack, 0);
+}
+
+// XXXbz this is a nasty hack to work around the XML content sink not being
+// incremental, so that the _first_ control we test is ok but others are not.
+var testIs = is;
+var once = false;
+function flipper(a, b, c) {
+ if (once) {
+ todo(a == b, c);
+ } else {
+ once = true;
+ is(a, b, c);
+ }
+}
+
+function finishTest(frameid) {
+ var doc = $(frameid).contentDocument;
+ ok(doc instanceof Document, "Check for doc", "doc should be a document");
+
+ for (var i = 0; i < nodes.length; ++i) {
+ var id = nodes[i][0];
+ var node = doc.getElementById(id);
+ ok(node instanceof nodes[i][1],
+ "Check for " + id, id + " should be a " + nodes[i][1]);
+ //testIs(node.disabled, true, "check for " + id + " state restore");
+ }
+
+ if (frameid == "frame2") {
+ SimpleTest.finish();
+ } else {
+ childUnloaded = false;
+
+ // XXXbz this is a nasty hack to deal with the content sink. See above.
+ testIs = flipper;
+
+ $("frame2").onload = soon(function() { startTest("frame2"); });
+ $("frame2").src = "bug277724_iframe2.xhtml";
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+
+<!-- Don't use display:none, since we don't support framestate restoration
+ without a frame tree -->
+<div id="content" style="visibility: hidden">
+ <iframe src="bug277724_iframe1.html" id="frame1"
+ onload="setTimeout(function() { startTest('frame1') }, 0)"></iframe>
+ <iframe src="" id="frame2"></iframe>
+</div>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug277890.html b/dom/html/test/test_bug277890.html
new file mode 100644
index 000000000..066271bd0
--- /dev/null
+++ b/dom/html/test/test_bug277890.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=277890
+-->
+<head>
+ <title>Test for Bug 277890</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=277890">Mozilla Bug 277890</a>
+<p id="display"></p>
+<div id="content">
+<iframe src="bug277890_iframe.html" id="a"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 277890 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var submitted = function() {
+ ok(true, "Disabling button after form submission doesn't prevent submitting");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug287465.html b/dom/html/test/test_bug287465.html
new file mode 100644
index 000000000..fb5430e95
--- /dev/null
+++ b/dom/html/test/test_bug287465.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=287465
+-->
+<head>
+ <title>Test for Bug 287465</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=287465">Mozilla Bug 287465</a>
+<p id="display"></p>
+<div id="content" style="display:none">
+
+<iframe id="i1" src="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>"></iframe>
+<object id="o1" data="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'></svg>"></object>
+<iframe id="i2" src="data:text/html,<html></html>"></iframe>
+<object id="o2" data="data:text/html,<html></html>"></object>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(doTest);
+
+function doTest() {
+ function checkSVGDocument(id) {
+ var e = document.getElementById(id);
+ ok(e.contentDocument != null, "check nonnull contentDocument '" + id + "'");
+ is(e.contentDocument, e.getSVGDocument(), "check documents match '" + id + "'");
+ }
+
+ checkSVGDocument("o1");
+ checkSVGDocument("i1");
+ checkSVGDocument("o2");
+ checkSVGDocument("i2");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug295561.html b/dom/html/test/test_bug295561.html
new file mode 100644
index 000000000..e283092a7
--- /dev/null
+++ b/dom/html/test/test_bug295561.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=295561
+-->
+<head>
+ <title>Test for Bug 295561</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=295561">Mozilla Bug 295561</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+<table id="testTable">
+<thead>
+<tr id="headRow"><td></td></tr>
+</thead>
+<tfoot>
+<tr id="footRow"><td></td></tr>
+</tfoot>
+<tbody id="tBody" name="namedTBody">
+<tr id="trow" name="namedTRow">
+<td id="tcell" name="namedTCell"></td>
+<th id="tcellh" name="namedTH"></th>
+</tr>
+<tr><td></td></tr>
+</tbody>
+<tbody id="tBody2" name="namedTBody2">
+<tr id="trow2" name="namedTRow2">
+<td id="tcell2" name="namedTCell2"></td>
+<th id="tcellh2" name="namedTH2"></th>
+</tr>
+</table>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+function testItById(id, collection, collectionName) {
+ is(collection[id], $(id),
+ "Should be able to get by id '" + id + "' from " + collectionName +
+ " collection using square brackets.")
+ is(collection.namedItem(id), $(id),
+ "Should be able to get by id '" + id + "' from " + collectionName +
+ " collection using namedItem.")
+}
+
+function testItByName(name, id, collection, collectionName) {
+ is(collection[name], $(id),
+ "Should be able to get by name '" + name + "' from " + collectionName +
+ " collection using square brackets.")
+ is(collection.namedItem(name), $(id),
+ "Should be able to get by name '" + name + "' from " + collectionName +
+ " collection using namedItem.")
+}
+
+function testIt(name, id, collection, collectionName) {
+ testItByName(name, id, collection, collectionName);
+ testItById(id, collection, collectionName);
+}
+
+var table = $("testTable")
+testIt("namedTBody", "tBody", table.tBodies, "tBodies")
+testIt("namedTRow", "trow", table.rows, "table rows")
+testIt("namedTRow", "trow", $("tBody").rows, "tbody rows")
+testIt("namedTCell", "tcell", $("trow").cells, "cells")
+testIt("namedTH", "tcellh", $("trow").cells, "cells")
+testIt("namedTBody2", "tBody2", table.tBodies, "tBodies")
+testIt("namedTRow2", "trow2", table.rows, "table rows")
+testIt("namedTRow2", "trow2", $("tBody2").rows, "tbody rows")
+testIt("namedTCell2", "tcell2", $("trow2").cells, "cells")
+testIt("namedTH2", "tcellh2", $("trow2").cells, "cells")
+is(table.tBodies.length, 2, "Incorrect tBodies length");
+is(table.rows.length, 5, "Incorrect rows length");
+is(table.rows[0], $("headRow"), "THead row in wrong spot");
+is(table.rows[1], $("trow"), "First tbody row in wrong spot");
+is(table.rows[3], $("trow2"), "Second tbody row in wrong spot");
+is(table.rows[4], $("footRow"), "TFoot row in wrong spot");
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug297761.html b/dom/html/test/test_bug297761.html
new file mode 100644
index 000000000..02d79f9bc
--- /dev/null
+++ b/dom/html/test/test_bug297761.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=297761
+-->
+<head>
+ <title>Test for Bug 297761</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=297761">Mozilla Bug 297761</a>
+<p id="display"></p>
+<div id="content">
+ <iframe src="file_bug297761.html"></iframe>
+ <iframe src="file_bug297761.html"></iframe>
+ <iframe src="file_bug297761.html"></iframe>
+ <iframe src="file_bug297761.html"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 297761 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var nbTests = 4;
+var curTest = 0;
+
+function nextTest()
+{
+ if (curTest == 3) {
+ frames[curTest].document.forms[0].submit();
+ } else {
+ var el = null;
+ if (curTest == 2) {
+ el = frames[curTest].document.getElementById('i');
+ } else {
+ el = frames[curTest].document.forms[0].elements[curTest];
+ }
+
+ el.focus();
+ el.click();
+ }
+}
+
+function frameLoaded(aFrame)
+{
+ var documentLocation = location.href.replace(/\.html.*/, "\.html");
+ is(aFrame.contentWindow.location.href.replace(/\?x=0&y=0/, ""),
+ documentLocation.replace(/test_bug/, "file_bug"),
+ "form should have been submitted to the document location");
+
+ if (++curTest == nbTests) {
+ SimpleTest.finish();
+ } else {
+ nextTest();
+ }
+}
+
+function runTest()
+{
+ // Initialize event handlers.
+ var frames = document.getElementsByTagName('iframe');
+ for (var i=0; i<nbTests; ++i) {
+ frames[i].setAttribute('onload', "frameLoaded(this);");
+ }
+
+ nextTest();
+}
+
+addLoadEvent(runTest);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug300691-1.html b/dom/html/test/test_bug300691-1.html
new file mode 100644
index 000000000..40d12f9bf
--- /dev/null
+++ b/dom/html/test/test_bug300691-1.html
@@ -0,0 +1,120 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=300691
+-->
+<head>
+ <title>Test for Bug 300691</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=300691">Mozilla Bug 300691</a>
+<p id="display">
+ <textarea id="target"></textarea>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+var t = $("target");
+
+/** Test for Bug 300691 **/
+function valueIs(arg, reason) {
+ is(t.value, arg, reason);
+}
+
+function defValueIs(arg, reason) {
+ is(t.defaultValue, arg, reason);
+}
+
+valueIs("", "Nothing in the textarea");
+defValueIs("", "Nothing in the textarea 2");
+
+t.appendChild(document.createTextNode("ab"));
+valueIs("ab", "Appended textnode");
+defValueIs("ab", "Appended textnode 2");
+
+t.firstChild.data = "abcd";
+valueIs("abcd", "Modified textnode text");
+defValueIs("abcd", "Modified textnode text 2");
+
+t.appendChild(document.createTextNode("efgh"));
+valueIs("abcdefgh", "Appended another textnode");
+defValueIs("abcdefgh", "Appended another textnode 2");
+
+t.removeChild(t.lastChild);
+valueIs("abcd", "Removed textnode");
+defValueIs("abcd", "Removed textnode 2");
+
+t.appendChild(document.createTextNode("efgh"));
+valueIs("abcdefgh", "Appended yet another textnode");
+defValueIs("abcdefgh", "Appended yet another textnode 2");
+
+t.normalize();
+valueIs("abcdefgh", "Normalization changes nothing for the value");
+defValueIs("abcdefgh", "Normalization changes nothing for the value 2");
+
+t.defaultValue = "abc";
+valueIs("abc", "Just set the default value on non-edited textarea");
+defValueIs("abc", "Just set the default value on non-edited textarea 2");
+
+t.appendChild(document.createTextNode("defgh"));
+valueIs("abcdefgh", "Appended another textnode again");
+defValueIs("abcdefgh", "Appended another textnode again 2");
+
+t.focus(); // This puts the caret at the end of the textarea, and doing
+ // something like "home" in a cross-platform way is kinda hard.
+sendKey("left");
+sendKey("left");
+sendKey("left");
+sendString("Test");
+
+valueIs("abcdeTestfgh", "Typed 'Test' after three left-arrows starting from end");
+defValueIs("abcdefgh", "Typing 'Test' shouldn't affect default value");
+
+sendKey("right");
+sendKey("right");
+sendKey("back_space");
+sendKey("back_space");
+
+valueIs("abcdeTesth",
+ "Backspaced twice after two right-arrows starting from end of typing");
+defValueIs("abcdefgh", "Deleting shouldn't affect default value");
+
+t.appendChild(document.createTextNode("ijk"));
+valueIs("abcdeTesth",
+ "Appending textnode shouldn't affect value in edited textarea");
+defValueIs("abcdefghijk", "Appended textnode 3");
+
+t.lastChild.data = "lmno";
+valueIs("abcdeTesth",
+ "Modifying textnode text shouldn't affect value in edited textarea");
+defValueIs("abcdefghlmno", "Modified textnode text 3");
+
+t.removeChild(t.firstChild);
+valueIs("abcdeTesth",
+ "Removing child textnode shouldn't affect value in edited textarea");
+defValueIs("defghlmno", "Removed textnode 3");
+
+t.insertBefore(document.createTextNode("abc"), t.firstChild);
+valueIs("abcdeTesth",
+ "Inserting child textnode shouldn't affect value in edited textarea");
+defValueIs("abcdefghlmno", "Inserted a text node");
+
+t.normalize();
+valueIs("abcdeTesth", "Normalization changes nothing for the value 3");
+defValueIs("abcdefghlmno", "Normalization changes nothing for the value 4");
+
+t.defaultValue = "abc";
+valueIs("abcdeTesth", "Setting default value shouldn't affect edited textarea");
+defValueIs("abc", "Just set the default value textarea");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug300691-2.html b/dom/html/test/test_bug300691-2.html
new file mode 100644
index 000000000..6dfa42621
--- /dev/null
+++ b/dom/html/test/test_bug300691-2.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=300691
+-->
+<head>
+ <title>Test for Bug 300691</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=300691">Mozilla Bug 300691</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="text/javascript">
+ // First, setup. We'll be toggling these variables as we go.
+ var test1Ran = false;
+ var test2Ran = false;
+ var test3Ran = false;
+ var test4Ran = false;
+ var test5Ran = false;
+ var test6Ran = false;
+ var test7Ran = false;
+ var test8Ran = false;
+ var test9Ran = false;
+ var test10Ran = false;
+ var test11Ran = false;
+ var test12Ran = false;
+ var test13Ran = false;
+ var test14aRan = false;
+ var test14bRan = false;
+ var test15aRan = false;
+ var test15bRan = false;
+</script>
+<script id="test1" type="text/javascript">test1Ran = true;</script>
+<script id="test2" type="text/javascript"></script>
+<script id="test3" type="text/javascript">;</script>
+<script id="test4" type="text/javascript"> </script>
+<script id="test5" type="text/javascript"></script>
+<script id="test6" type="text/javascript"></script>
+<script id="test7" type="text/javascript"></script>
+<script id="test8" type="text/javascript"></script>
+<script id="test9" type="text/javascript"></script>
+<script id="test10" type="text/javascript" src="data:text/javascript,">
+ test10Ran = true;
+</script>
+<script id="test11" type="text/javascript"
+ src="data:text/javascript,test11Ran = true">
+ test11Ran = false;
+</script>
+<script id="test12" type="text/javascript"></script>
+<script id="test13" type="text/javascript"></script>
+<script id="test14" type="text/javascript"></script>
+<script id="test15" type="text/javascript"></script>
+<script class="testbody" type="text/javascript">
+ /** Test for Bug 300691 **/
+ $("test2").appendChild(document.createTextNode("test2Ran = true"));
+ is(test2Ran, true, "Should be 2!");
+
+ $("test3").appendChild(document.createTextNode("test3Ran = true"));
+ is(test3Ran, false, "Should have run already 3!");
+
+ $("test4").appendChild(document.createTextNode("test4Ran = true"));
+ is(test4Ran, false, "Should have run already 4!");
+
+ $("test5").appendChild(document.createTextNode(" "));
+ $("test5").appendChild(document.createTextNode("test5Ran = true"));
+ is(test5Ran, false, "Should have run already 5!");
+
+ $("test6").appendChild(document.createTextNode(" "));
+
+ $("test7").appendChild(document.createTextNode(""));
+
+ $("test8").appendChild(document.createTextNode(""));
+
+ $("test9").appendChild(document.createTextNode(""));
+
+ $("test12").src = "data:text/javascript,test12Ran = true;";
+ is(test12Ran, false, "Not yet 12!");
+
+ $("test13").setAttribute("src", "data:text/javascript,test13Ran = true;");
+ is(test13Ran, false, "Not yet 13!");
+
+ $("test14").src = "data:text/javascript,test14aRan = true;";
+ $("test14").appendChild(document.createTextNode("test14bRan = true"));
+ is(test14aRan, false, "Not yet 14a!");
+ is(test14bRan, false, "Not yet 14b!");
+
+ $("test15").src = "data:text/javascript,test15aRan = true;";
+ $("test15").appendChild(document.createTextNode("test15bRan = true"));
+ $("test15").removeAttribute("src");
+ is(test15aRan, false, "Not yet 15a!");
+ is(test15bRan, false, "Not yet 15b!");
+</script>
+<script type="text/javascript">
+ // Follow up on some of those
+ $("test6").appendChild(document.createTextNode("test6Ran = true"));
+ is(test6Ran, false, "Should have run already 6!");
+
+ $("test7").appendChild(document.createTextNode("test7Ran = true"));
+ is(test7Ran, true, "Should be 7!");
+
+ $("test8").insertBefore(document.createTextNode("test8Ran = true"),
+ $("test8").firstChild);
+ is(test8Ran, true, "Should be 8!");
+
+ $("test9").firstChild.data = "test9Ran = true";
+ is(test9Ran, true, "Should be 9!");
+</script>
+<script type="text/javascript">
+function done() {
+ is(test1Ran, true, "Should have run!");
+ is(test3Ran, false, "Already executed test3 script once");
+ is(test4Ran, false,
+ "Should have executed whitespace-only script already");
+ is(test5Ran, false,
+ "Should have executed once the whitespace node was added");
+ is(test6Ran, false,
+ "Should have executed once the whitespace node was added 2");
+ is(test10Ran, false, "Has an src; inline part shouldn't run");
+ is(test11Ran, true, "Script with src should have run");
+ is(test12Ran, true, "Setting src should execute script");
+ is(test13Ran, true, "Setting src attribute should execute script");
+ is(test14aRan, true, "src attribute takes precedence over inline content");
+ is(test14bRan, false, "src attribute takes precedence over inline content 2");
+ is(test15aRan, true,
+ "src attribute load should have started before the attribute got removed");
+ is(test15bRan, false,
+ "src attribute still got executed, so this shouldn't have been");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(done);
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug300691-3.xhtml b/dom/html/test/test_bug300691-3.xhtml
new file mode 100644
index 000000000..84c732c2b
--- /dev/null
+++ b/dom/html/test/test_bug300691-3.xhtml
@@ -0,0 +1,48 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=300691
+-->
+<head>
+ <title>Test for Bug 300691</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=300691">Mozilla Bug 300691</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="text/javascript">
+ // First, setup. We'll be toggling these variables as we go.
+ // Note that scripts don't execute immediately when you put text in them --
+ // they wait for the currently-running script to finish.
+ var test1Ran = false;
+ var test2Ran = false;
+ var test3Ran = false;
+</script>
+<script id="test1" type="text/javascript">test1Ran = true;</script>
+<script id="test2" type="text/javascript"></script>
+<script id="test3" type="text/javascript"></script>
+<script class="testbody" type="text/javascript">
+<![CDATA[
+ /** Test for Bug 300691 **/
+ $("test2").appendChild(document.createCDATASection("test2Ran = true"));
+ is(test2Ran, true, "Should be 2!");
+
+ $("test3").appendChild(document.createCDATASection(""));
+]]>
+</script>
+<script type="text/javascript">
+ // Follow up on some of those
+ $("test3").firstChild.data = "test3Ran = true";
+ is(test3Ran, true, "Should be 3!");
+</script>
+<script type="text/javascript">
+ is(test1Ran, true, "Should have run!");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug311681.html b/dom/html/test/test_bug311681.html
new file mode 100644
index 000000000..b9139a391
--- /dev/null
+++ b/dom/html/test/test_bug311681.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=311681
+-->
+<head>
+ <title>Test for Bug 311681</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=311681">Mozilla Bug 311681</a>
+<script class="testbody" type="text/javascript">
+ // Setup script
+ SimpleTest.waitForExplicitFinish();
+
+ // Make sure to trigger the hashtable case by asking for enough elements
+ // by ID.
+ for (var i = 0; i < 256; ++i) {
+ var x = document.getElementById(i);
+ }
+
+ // save off the document.getElementById function, since getting it as a
+ // property off the document it causes a content flush.
+ var fun = document.getElementById;
+
+ // Slot for our initial element with id "content"
+ var testNode;
+
+ function getCont() {
+ return fun.call(document, "content");
+ }
+
+ function testClone() {
+ // Test to make sure that if we have multiple nodes with the same ID in
+ // a document we don't forget about one of them when the other is
+ // removed.
+ var newParent = $("display");
+ var node = testNode.cloneNode(true);
+ isnot(node, testNode, "Clone should be a different node");
+
+ newParent.appendChild(node);
+
+ // Check what getElementById returns, no flushing
+ is(getCont(), node, "Should be getting new node pre-flush 1");
+
+ // Trigger a layout flush, just in case.
+ var itemHeight = newParent.offsetHeight/10;
+
+ // Check what getElementById returns now.
+ is(getCont(), node, "Should be getting new node post-flush 1");
+
+ clear(newParent);
+
+ // Check what getElementById returns, no flushing
+ is(getCont(), testNode, "Should be getting orig node pre-flush 2");
+
+ // Trigger a layout flush, just in case.
+ var itemHeight = newParent.offsetHeight/10;
+
+ // Check what getElementById returns now.
+ is(getCont(), testNode, "Should be getting orig node post-flush 2");
+
+ node = testNode.cloneNode(true);
+ newParent.appendChild(node);
+ testNode.parentNode.removeChild(testNode);
+
+ // Check what getElementById returns, no flushing
+ is(getCont(), node, "Should be getting clone pre-flush");
+
+ // Trigger a layout flush, just in case.
+ var itemHeight = newParent.offsetHeight/10;
+
+ // Check what getElementById returns now.
+ is(getCont(), node, "Should be getting clone post-flush");
+
+ }
+
+ function clear(node) {
+ while (node.hasChildNodes()) {
+ node.removeChild(node.firstChild);
+ }
+ }
+
+ addLoadEvent(testClone);
+ addLoadEvent(SimpleTest.finish);
+</script>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <script class="testbody" type="text/javascript">
+ testNode = fun.call(document, "content");
+ isnot(testNode, null, "Should have node here");
+ </script>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug311681.xhtml b/dom/html/test/test_bug311681.xhtml
new file mode 100644
index 000000000..0c7d5fd6f
--- /dev/null
+++ b/dom/html/test/test_bug311681.xhtml
@@ -0,0 +1,102 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=311681
+-->
+<head>
+ <title>Test for Bug 311681</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=311681">Mozilla Bug 311681</a>
+<script class="testbody" type="text/javascript">
+<![CDATA[
+ // Setup script
+ SimpleTest.waitForExplicitFinish();
+
+ // Make sure to trigger the hashtable case by asking for enough elements
+ // by ID.
+ for (var i = 0; i < 256; ++i) {
+ var x = document.getElementById(i);
+ }
+
+ // save off the document.getElementById function, since getting it as a
+ // property off the document it causes a content flush.
+ var fun = document.getElementById;
+
+ // Slot for our initial element with id "content"
+ var testNode;
+
+ function getCont() {
+ return fun.call(document, "content");
+ }
+
+ function testClone() {
+ // Test to make sure that if we have multiple nodes with the same ID in
+ // a document we don't forget about one of them when the other is
+ // removed.
+ var newParent = $("display");
+ var node = testNode.cloneNode(true);
+ isnot(node, testNode, "Clone should be a different node");
+
+ newParent.appendChild(node);
+
+ // Check what getElementById returns, no flushing
+ is(getCont(), node, "Should be getting new node pre-flush 1");
+
+ // Trigger a layout flush, just in case.
+ var itemHeight = newParent.offsetHeight/10;
+
+ // Check what getElementById returns now.
+ is(getCont(), node, "Should be getting new node post-flush 1");
+
+ clear(newParent);
+
+ // Check what getElementById returns, no flushing
+ is(getCont(), testNode, "Should be getting orig node pre-flush 2");
+
+ // Trigger a layout flush, just in case.
+ var itemHeight = newParent.offsetHeight/10;
+
+ // Check what getElementById returns now.
+ is(getCont(), testNode, "Should be getting orig node post-flush 2");
+
+ node = testNode.cloneNode(true);
+ newParent.appendChild(node);
+ testNode.parentNode.removeChild(testNode);
+
+ // Check what getElementById returns, no flushing
+ is(getCont(), node, "Should be getting clone pre-flush");
+
+ // Trigger a layout flush, just in case.
+ var itemHeight = newParent.offsetHeight/10;
+
+ // Check what getElementById returns now.
+ is(getCont(), node, "Should be getting clone post-flush");
+
+ }
+
+ function clear(node) {
+ while (node.hasChildNodes()) {
+ node.removeChild(node.firstChild);
+ }
+ }
+
+ addLoadEvent(testClone);
+ addLoadEvent(SimpleTest.finish);
+]]>
+</script>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <script class="testbody" type="text/javascript">
+ <![CDATA[
+ testNode = fun.call(document, "content");
+ ok(testNode != null, "Should have node here");
+ ]]>
+ </script>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug324378.html b/dom/html/test/test_bug324378.html
new file mode 100644
index 000000000..166e4f149
--- /dev/null
+++ b/dom/html/test/test_bug324378.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html id="a" id="b">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=324378
+-->
+<head id="c" id="d">
+ <head id="j" foo="k" foo="l">
+ <title>Test for Bug 324378</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body id="e" id="f">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=324378">Mozilla Bug 324378</a>
+<script>
+ var html = document.documentElement;
+ is(document.getElementsByTagName("html").length, 1,
+ "Unexpected number of htmls");
+ is(document.getElementsByTagName("html")[0], html,
+ "Unexpected <html> element");
+ is(document.getElementsByTagName("head").length, 1,
+ "Unexpected number of heads");
+ is(html.getElementsByTagName("head").length, 1,
+ "Unexpected number of heads in <html>");
+ is(document.getElementsByTagName("body").length, 1,
+ "Unexpected number of bodies");
+ is(html.getElementsByTagName("body").length, 1,
+ "Unexpected number of bodies in <html>");
+ var head = document.getElementsByTagName("head")[0];
+ var body = document.getElementsByTagName("body")[0];
+</script>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <html id="g" foo="h" foo="i">
+ <body id="m" foo="n" foo="o">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 324378 **/
+ is(document.getElementsByTagName("html").length, 1,
+ "Unexpected number of htmls after additions");
+ is(document.getElementsByTagName("html")[0], html,
+ "Unexpected <html> element");
+ is(document.documentElement, html,
+ "Unexpected root node");
+ is(document.getElementsByTagName("head").length, 1,
+ "Unexpected number of heads after additions");
+ is(document.getElementsByTagName("head")[0], head,
+ "Unexpected <head> element");
+ is(document.getElementsByTagName("body").length, 1,
+ "Unexpected number of bodies after additions");
+ is(document.getElementsByTagName("body")[0], body,
+ "Unexpected <body> element");
+
+ is(html.id, "a", "Unexpected <html> id");
+ is(head.id, "c", "Unexpected <head> id");
+ is(body.id, "e", "Unexpected <body> id");
+ is($("a"), html, "Unexpected node with id=a");
+ is($("b"), null, "Unexpected node with id=b");
+ is($("c"), head, "Unexpected node with id=c");
+ is($("d"), null, "Unexpected node with id=d");
+ is($("e"), body, "Unexpected node with id=e");
+ is($("f"), null, "Unexpected node with id=f");
+ is($("g"), null, "Unexpected node with id=g");
+ is($("j"), null, "Unexpected node with id=j");
+ is($("m"), null, "Unexpected node with id=m");
+
+ is(html.getAttribute("foo"), "h", "Unexpected 'foo' value on <html>");
+ is(head.getAttribute("foo"), null, "Unexpected 'foo' value on <head>");
+ is(body.getAttribute("foo"), "n", "Unexpected 'foo' value on <body>");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug330705-1.html b/dom/html/test/test_bug330705-1.html
new file mode 100644
index 000000000..2a5c737ed
--- /dev/null
+++ b/dom/html/test/test_bug330705-1.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=330705
+-->
+<head>
+ <title>Test for Bug 330705</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <script>
+ /* variable is true if the element is focused, false otherwise */
+ var inputFocused = false;
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=330705">Mozilla Bug 330705</a>
+<p id="display">
+ <input onfocus="inputFocused = true" onblur="inputFocused = false" type="text">
+ <button></button>
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+/** Test for Bug 330705 **/
+ SimpleTest.waitForExplicitFinish();
+ var isFocused = false;
+
+ function onLoad() {
+ document.getElementsByTagName('input')[0].focus();
+ document.getElementsByTagName('button')[0].blur();
+ ok(inputFocused == true, "the input element is still focused after blur() has been called on the unfocused element");
+ SimpleTest.finish();
+ }
+
+ addLoadEvent(onLoad);
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug332246.html b/dom/html/test/test_bug332246.html
new file mode 100644
index 000000000..e1acbe309
--- /dev/null
+++ b/dom/html/test/test_bug332246.html
@@ -0,0 +1,75 @@
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=332246
+-->
+<head>
+ <title>Test for Bug 332246 - scrollIntoView(false) doesn't work correctly for inline elements that wrap at multiple lines</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=332246">Mozilla Bug 332246</a>
+<p id="display"></p>
+<div id="content">
+
+<div id="a1" style="height: 100px; width: 100px; overflow: hidden; outline:1px dotted black;">
+<div style="height: 100px"></div>
+<a id="a2" href="#" style="display:block; background:yellow; height:200px;">Top</a>
+<div style="height: 100px"></div>
+</div>
+
+<div id="b1" style="height: 100px; width: 100px; overflow: hidden; outline:1px dotted black;">
+<div style="height: 100px"></div>
+<div id="b2" href="#" style="border:10px solid black; background:yellow; height:200px;"></div>
+<div style="height: 100px"></div>
+</div>
+
+<br>
+
+<div id="c1" style="height: 100px; width: 100px; overflow: hidden; position: relative; outline:1px dotted black;">
+<div id="c2" style="border: 10px solid black; height: 200px; width: 50px; position: absolute; top: 100px;"></div>
+<div style="height: 100px"></div>
+</div>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 332246 **/
+
+function isWithFuzz(itIs, itShouldBe, fuzz, description) {
+ ok(Math.abs(itIs - itShouldBe) <= fuzz, `${description} - expected a value between ${itShouldBe - fuzz} and ${itShouldBe + fuzz}, got ${itIs}`);
+}
+
+var a1 = document.getElementById('a1');
+var a2 = document.getElementById('a2');
+isWithFuzz(a1.scrollHeight, 400, 1, "Wrong a1.scrollHeight");
+is(a1.offsetHeight, 100, "Wrong a1.offsetHeight");
+a2.scrollIntoView(true);
+is(a1.scrollTop, 100, "Wrong scrollTop value after a2.scrollIntoView(true)");
+a2.scrollIntoView(false);
+is(a1.scrollTop, 200, "Wrong scrollTop value after a2.scrollIntoView(false)");
+
+var b1 = document.getElementById('b1');
+var b2 = document.getElementById('b2');
+isWithFuzz(b1.scrollHeight, 420, 1, "Wrong b1.scrollHeight");
+is(b1.offsetHeight, 100, "Wrong b1.offsetHeight");
+b2.scrollIntoView(true);
+is(b1.scrollTop, 100, "Wrong scrollTop value after b2.scrollIntoView(true)");
+b2.scrollIntoView(false);
+is(b1.scrollTop, 220, "Wrong scrollTop value after b2.scrollIntoView(false)");
+
+var c1 = document.getElementById('c1');
+var c2 = document.getElementById('c2');
+isWithFuzz(c1.scrollHeight, 320, 1, "Wrong c1.scrollHeight");
+is(c1.offsetHeight, 100, "Wrong c1.offsetHeight");
+c2.scrollIntoView(true);
+is(c1.scrollTop, 100, "Wrong scrollTop value after c2.scrollIntoView(true)");
+c2.scrollIntoView(false);
+isWithFuzz(c1.scrollTop, 220, 1, "Wrong scrollTop value after c2.scrollIntoView(false)");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug332848.xhtml b/dom/html/test/test_bug332848.xhtml
new file mode 100644
index 000000000..2b19e6b78
--- /dev/null
+++ b/dom/html/test/test_bug332848.xhtml
@@ -0,0 +1,86 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=332848
+-->
+<head>
+ <title>Test for Bug 332848</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=332848">Mozilla Bug 332848</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+
+/** Test for Bug 332848 **/
+
+// parseChecker will become true if we keep parsing after calling close().
+var parseChecker = false;
+
+function test() {
+ try {
+ document.open();
+ is(0, 1, "document.open succeeded");
+ } catch (e) {
+ is (e.name, "InvalidStateError",
+ "Wrong exception from document.open");
+ is (e.code, DOMException.INVALID_STATE_ERR,
+ "Wrong exception from document.open");
+ }
+
+ try {
+ document.write("aaa");
+ is(0, 1, "document.write succeeded");
+ } catch (e) {
+ is (e.name, "InvalidStateError",
+ "Wrong exception from document.write");
+ is (e.code, DOMException.INVALID_STATE_ERR,
+ "Wrong exception from document.write");
+ }
+
+ try {
+ document.writeln("aaa");
+ is(0, 1, "document.write succeeded");
+ } catch (e) {
+ is (e.name, "InvalidStateError",
+ "Wrong exception from document.write");
+ is (e.code, DOMException.INVALID_STATE_ERR,
+ "Wrong exception from document.write");
+ }
+
+ try {
+ document.close();
+ is(0, 1, "document.close succeeded");
+ } catch (e) {
+ is (e.name, "InvalidStateError",
+ "Wrong exception from document.close");
+ is (e.code, DOMException.INVALID_STATE_ERR,
+ "Wrong exception from document.close");
+ }
+}
+
+function loadTest() {
+ is(parseChecker, true, "Parsing stopped");
+ test();
+ SimpleTest.finish();
+}
+
+window.onload = loadTest;
+
+SimpleTest.waitForExplicitFinish();
+
+test();
+]]>
+</script>
+<script>
+ parseChecker = true;
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug332893-1.html b/dom/html/test/test_bug332893-1.html
new file mode 100644
index 000000000..4136c73e6
--- /dev/null
+++ b/dom/html/test/test_bug332893-1.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+
+<form id="form1">
+ <input id="F1I1" type="input" value="11"/>
+ <input id="F1I2" type="input" value="12"/>
+</form>
+<form id="form2">
+ <input id="F2I1" type="input" value="21"/>
+ <input id="F2I2" type="input" value="22"/>
+</form>
+<script>
+<!-- Create a new input, add it to the first form, move it to the 2nd form, then move it back to the first -->
+ var form1 = document.getElementById("form1");
+ var form2 = document.getElementById("form2");
+ var newInput = document.createElement("input");
+ newInput.value = "13";
+ form1.insertBefore(newInput, form1.firstChild);
+ var F2I2 = document.getElementById("F2I2");
+ form2.insertBefore(newInput, F2I2);
+ form1.insertBefore(newInput, form1.firstChild);
+
+ is(form1.elements.length, 3, "Form 1 has the correct length");
+ is(form1.elements[0].value, "13", "Form 1 element 1 is correct");
+ is(form1.elements[1].value, "11", "Form 1 element 2 is correct");
+ is(form1.elements[2].value, "12", "Form 1 element 3 is correct");
+
+ is(form2.elements.length, 2, "Form 2 has the correct length");
+ is(form2.elements[0].value, "21", "Form 2 element 1 is correct");
+ is(form2.elements[1].value, "22", "Form 2 element 2 is correct");
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug332893-2.html b/dom/html/test/test_bug332893-2.html
new file mode 100644
index 000000000..36083b6a1
--- /dev/null
+++ b/dom/html/test/test_bug332893-2.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+
+
+<form id="form1">
+ <table>
+ <tbody id="table1">
+ <tr id="F1I0"><td><input form='form1' type="input" value="10"/></td></tr>
+ <tr id="F1I1"><td><input type="input" value="11"/></td></tr>
+ <tr id="F1I2"><td><input type="input" value="12"/></td></tr>
+ </tbody>
+ </table>
+</form>
+<form id="form2">
+ <table>
+ <tbody id="table2">
+ <tr id="F2I1"><td><input type="input" value="21"/></td></tr>
+ <tr id="F2I2"><td><input type="input" value="22"/></td></tr>
+ </tbody>
+ </table>
+</form>
+
+<script>
+ var table1 = document.getElementById("table1");
+ var F1I0 = table1.getElementsByTagName("tr")[0];
+ var F1I1 = table1.getElementsByTagName("tr")[1];
+ table1.removeChild(F1I0);
+ table1.removeChild(F1I1);
+
+ var table2 = document.getElementById("table2");
+ table2.insertBefore(F1I0, table2.firstChild);
+ table2.insertBefore(F1I1, table2.firstChild);
+
+ var form1 = document.getElementById("form1");
+ var form2 = document.getElementById("form2");
+
+ is(form1.elements.length, 2, "Form 1 length is correct");
+ is(form1.elements[0].value, "12", "Form 1 first element is correct");
+ is(form1.elements[1].value, "10", "Form 2 second element is correct");
+ is(form2.elements.length, 3, "Form 2 length is correct");
+ is(form2.elements[0].value, "11", "Form 2 element 1 is correct");
+ is(form2.elements[1].value, "21", "Form 2 element 2 is correct");
+ is(form2.elements[2].value, "22", "Form 2 element 3 is correct");
+
+</script>
+
+</body>
+</html>
diff --git a/dom/html/test/test_bug332893-3.html b/dom/html/test/test_bug332893-3.html
new file mode 100644
index 000000000..372319c22
--- /dev/null
+++ b/dom/html/test/test_bug332893-3.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<form id="form1">
+ <table>
+ <tbody>
+ <tr>
+ <td>
+ <table>
+ <tbody id="table1">
+ <tr id="F1I0"><td><input form='form1' type="input" value="10"/></td></tr>
+ <tr id="F1I1"><td><input type="input" value="11"/></td></tr>
+ <tr id="F1I2"><td><input type="input" value="12"/></td></tr>
+ </tbody>
+ </table>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+</form>
+<form id="form2">
+ <table>
+ <tbody id="table2">
+ <tr id="F2I1"><td><input type="input" value="21"/></td></tr>
+ <tr id="F2I2"><td><input type="input" value="22"/></td></tr>
+ </tbody>
+ </table>
+</form>
+
+<script>
+ var table1 = document.getElementById("table1");
+ var F1I0 = table1.getElementsByTagName("tr")[0];
+ var F1I1 = table1.getElementsByTagName("tr")[1];
+ table1.removeChild(F1I0);
+ table1.removeChild(F1I1);
+
+ var table2 = document.getElementById("table2");
+ table2.insertBefore(F1I0, table2.firstChild);
+ table2.insertBefore(F1I1, table2.firstChild);
+
+ var form1 = document.getElementById("form1");
+ var form2 = document.getElementById("form2");
+
+ is(form1.elements.length, 2, "Form 1 has the correct length");
+ is(form1.elements[0].value, "12", "Form 1 element 1 is correct");
+ is(form1.elements[1].value, "10", "Form 1 element 2 is correct");
+
+ is(form2.elements.length, 3, "Form 2 has the correct length");
+ is(form2.elements[0].value, "11", "Form 2 element 1 is correct");
+ is(form2.elements[1].value, "21", "Form 2 element 2 is correct");
+ is(form2.elements[2].value, "22", "Form 2 element 2 is correct");
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug332893-4.html b/dom/html/test/test_bug332893-4.html
new file mode 100644
index 000000000..abbc60ca6
--- /dev/null
+++ b/dom/html/test/test_bug332893-4.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<form id="form1">
+ <input id="input1" type="input" name="input" value="1"/>
+ <input id="input2" type="input" name="input" value="2"/>
+ <input id="input3" type="input" name="input" value="3"/>
+</form>
+<script>
+ var input1 = document.getElementById("input1");
+ var input2 = document.getElementById("input2");
+ var form1 = document.getElementById("form1");
+ form1.insertBefore(input2, input1);
+
+ is(form1.elements["input"].length, 3, "Form 1 'input' has the correct length");
+ is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct");
+ is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct");
+ is(form1.elements["input"][2].value, "3", "Form 1 element 3 is correct");
+
+ is(form1.elements["input"][0].id, "input2", "Form 1 element 1 id is correct");
+ is(form1.elements["input"][1].id, "input1", "Form 1 element 2 id is correct");
+ is(form1.elements["input"][2].id, "input3", "Form 1 element 3 id is correct");
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug332893-5.html b/dom/html/test/test_bug332893-5.html
new file mode 100644
index 000000000..6898f9157
--- /dev/null
+++ b/dom/html/test/test_bug332893-5.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<form id="form1">
+ <input id="input1" type="input" name="input" value="1"/>
+ <input id="input" type="input" name="input_other" value="2"/>
+ <input id="input3" type="input" name="input" value="3"/>
+</form>
+<script>
+ var input1 = document.getElementById("input1");
+ var input2 = document.getElementById("input");
+ var form1 = document.getElementById("form1");
+ form1.insertBefore(input2, input1);
+
+ is(form1.elements["input"].length, 3, "Form 1 'input' has the correct length");
+ is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct");
+ is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct");
+ is(form1.elements["input"][2].value, "3", "Form 1 element 3 is correct");
+
+ is(form1.elements["input"][0].id, "input", "Form 1 element 1 id is correct");
+ is(form1.elements["input"][1].id, "input1", "Form 1 element 2 id is correct");
+ is(form1.elements["input"][2].id, "input3", "Form 1 element 3 id is correct");
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug332893-6.html b/dom/html/test/test_bug332893-6.html
new file mode 100644
index 000000000..c5e6fe376
--- /dev/null
+++ b/dom/html/test/test_bug332893-6.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<form id="form1">
+ <input id="input1" type="input" name="input" value="1"/>
+ <input id="input" type="input" name="input_other" value="2"/>
+ <input id="input3" type="input" name="input" value="3"/>
+</form>
+<script>
+ var input1 = document.getElementById("input1");
+ var input2 = document.getElementById("input");
+ var form1 = document.getElementById("form1");
+ form1.insertBefore(input2, input1);
+
+ is(form1.elements["input"].length, 3, "Form 1 'input' has the correct length");
+ is(form1.elements["input"][0].value, "2", "Form 1 element 1 is correct");
+ is(form1.elements["input"][1].value, "1", "Form 1 element 2 is correct");
+
+ is(form1.elements["input"][0].id, "input", "Form 1 element 1 id is correct");
+ is(form1.elements["input"][1].id, "input1", "Form 1 element 2 id is correct");
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug332893-7.html b/dom/html/test/test_bug332893-7.html
new file mode 100644
index 000000000..7939b34ae
--- /dev/null
+++ b/dom/html/test/test_bug332893-7.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<form id="form1">
+ <input id="input1" type="input" name="input" value="1"/>
+ <input id="input2" type="input" name="input" value="2"/>
+ <input id="input3" type="input" name="input" value="3"/>
+ <input id="input4" type="input" name="input" value="4"/>
+ <input id="input5" type="input" name="input" value="5"/>
+ <input id="input6" type="input" name="input" value="6"/>
+ <input id="input7" type="input" name="input" value="7"/>
+ <input id="input8" type="input" name="input" value="8"/>
+ <input id="input9" type="input" name="input" value="9"/>
+ <input id="input10" type="input" name="input" value="10"/>
+
+
+
+
+</form>
+<script>
+ var input1 = document.getElementById("input1");
+ var input2 = document.getElementById("input2");
+ var input3 = document.getElementById("input3");
+ var input4 = document.getElementById("input4");
+ var input5 = document.getElementById("input5");
+ var input6 = document.getElementById("input6");
+ var input7 = document.getElementById("input7");
+ var input8 = document.getElementById("input8");
+ var input9 = document.getElementById("input9");
+ var input10 = document.getElementById("input10");
+
+
+ var form1 = document.getElementById("form1");
+
+ form1.insertBefore(input2, input1);
+ form1.insertBefore(input10, input6);
+ form1.insertBefore(input8, input4);
+ form1.insertBefore(input9, input2);
+
+ is(form1.elements["input"].length, 10, "Form 1 'input' has the correct length");
+ is(form1.elements["input"][0].value, "9", "Form 1 element 1 is correct");
+ is(form1.elements["input"][1].value, "2", "Form 1 element 2 is correct");
+ is(form1.elements["input"][2].value, "1", "Form 1 element 3 is correct");
+ is(form1.elements["input"][3].value, "3", "Form 1 element 4 is correct");
+ is(form1.elements["input"][4].value, "8", "Form 1 element 5 is correct");
+ is(form1.elements["input"][5].value, "4", "Form 1 element 6 is correct");
+ is(form1.elements["input"][6].value, "5", "Form 1 element 7 is correct");
+ is(form1.elements["input"][7].value, "10", "Form 1 element 8 is correct");
+ is(form1.elements["input"][8].value, "6", "Form 1 element 9 is correct");
+ is(form1.elements["input"][9].value, "7", "Form 1 element 10 is correct");
+
+ is(form1.elements["input"][0].id, "input9", "Form 1 element 1 id is correct");
+ is(form1.elements["input"][1].id, "input2", "Form 1 element 2 id is correct");
+ is(form1.elements["input"][2].id, "input1", "Form 1 element 3 id is correct");
+ is(form1.elements["input"][3].id, "input3", "Form 1 element 4 id is correct");
+ is(form1.elements["input"][4].id, "input8", "Form 1 element 5 id is correct");
+ is(form1.elements["input"][5].id, "input4", "Form 1 element 6 id is correct");
+ is(form1.elements["input"][6].id, "input5", "Form 1 element 7 id is correct");
+ is(form1.elements["input"][7].id, "input10", "Form 1 element 8 id is correct");
+ is(form1.elements["input"][8].id, "input6", "Form 1 element 9 id is correct");
+ is(form1.elements["input"][9].id, "input7", "Form 1 element 10 id is correct");
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug3348.html b/dom/html/test/test_bug3348.html
new file mode 100644
index 000000000..50280e0a4
--- /dev/null
+++ b/dom/html/test/test_bug3348.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=3348
+-->
+<head>
+ <title>Test for Bug 3348</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=3348">Mozilla Bug 3348</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+<form id="form1">
+<input type="button" value="click here" onclick="buttonClick();">
+</form>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 3348 **/
+
+var oForm = document.getElementById("form1");
+is(oForm.tagName, "FORM", "tagName of HTML element gives tag in upper case");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug340017.xhtml b/dom/html/test/test_bug340017.xhtml
new file mode 100644
index 000000000..eabef837e
--- /dev/null
+++ b/dom/html/test/test_bug340017.xhtml
@@ -0,0 +1,27 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=340017
+-->
+<head>
+ <title>Test for Bug 340017</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=340017">Mozilla Bug 340017</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <form id="frmfoo" name="foo" action="" />
+</div>
+<pre id="test">
+<script type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 340017 **/
+is(document.foo, document.getElementById("frmfoo"),
+ "The form with name 'foo' should be a document accessible property");
+]]>
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug340800.html b/dom/html/test/test_bug340800.html
new file mode 100644
index 000000000..68e6ed0e4
--- /dev/null
+++ b/dom/html/test/test_bug340800.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=340800
+-->
+<head>
+ <title>Test for Bug 340800</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=340800">Mozilla Bug 340800</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <h1>iframe text/plain as DOM test</h1>
+
+ <div>
+
+ <iframe name="iframe1" width="100%" height="200"
+ src="bug340800_iframe.txt"></iframe>
+ </div>
+
+ <div>
+ <h2>textarea with iframe content</h2>
+ <textarea rows="10" cols="80" id="textarea1"></textarea>
+ </div>
+
+ <div>
+ <h2>div with white-space: pre and iframe content</h2>
+ <div id="div1"></div>
+ </div>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 340800 **/
+function populateIframes () {
+ var iframe, iframeBody;
+ if ((iframe = window.frames.iframe1) && (iframeBody = iframe.document.body)) {
+ $('div1').innerHTML = iframeBody.innerHTML;
+ $('textarea1').value = iframeBody.innerHTML;
+ }
+ is($('div1').firstChild.tagName, "PRE", "innerHTML from txt iframe works with div");
+ ok($('textarea1').value.indexOf("<pre>") > -1, "innerHTML from txt iframe works with textarea.value");
+ SimpleTest.finish();
+}
+
+addLoadEvent(populateIframes);
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug347174.html b/dom/html/test/test_bug347174.html
new file mode 100644
index 000000000..aadef4423
--- /dev/null
+++ b/dom/html/test/test_bug347174.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=347174
+-->
+<head>
+ <title>Test for Bug 347174</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=347174">Mozilla Bug 347174</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 347174 **/
+// simple test of readyState during loading, DOMContentLoaded, and complete
+// this test passes in IE7
+window.readyStateText = [];
+window.readyStateText.push("script tag: " + document.readyState);
+is(document.readyState, "loading", "document.readyState should be 'loading' when scripts runs initially");
+
+function attachCustomEventListener(element, eventName, command) {
+ if (window.addEventListener && !window.opera)
+ element.addEventListener(eventName, command, true);
+ else if (window.attachEvent)
+ element.attachEvent("on" + eventName, command);
+}
+
+function showMessage(msg) {
+ window.readyStateText.push(msg);
+ document.getElementById("display").innerHTML = readyStateText.join("<br>");
+}
+
+function load() {
+ is(document.readyState, "complete", "document.readyState should be 'complete' on load");
+ showMessage("load: " + document.readyState);
+ SimpleTest.finish();
+}
+
+function readyStateChange() {
+ showMessage("readyStateChange: " + document.readyState);
+}
+
+function DOMContentLoaded() {
+ is(document.readyState, "interactive", "document.readyState should be 'interactive' on DOMContentLoaded");
+ showMessage("DOMContentLoaded: " + document.readyState);
+}
+
+window.onload=load;
+
+attachCustomEventListener(document, "readystatechange", readyStateChange);
+attachCustomEventListener(document, "DOMContentLoaded", DOMContentLoaded);
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug347174_write.html b/dom/html/test/test_bug347174_write.html
new file mode 100644
index 000000000..1ff870de2
--- /dev/null
+++ b/dom/html/test/test_bug347174_write.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=347174
+-->
+<head>
+ <title>Test for Bug 347174</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=347174">Mozilla Bug 347174</a>
+<p id="display"></p>
+
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 347174 **/
+// simple test of readyState during loading, DOMContentLoaded, and complete
+// this test passes in IE7
+window.readyStateText = [];
+window.loaded = false;
+function attachCustomEventListener(element, eventName, command) {
+ if (window.addEventListener && !window.opera)
+ element.addEventListener(eventName, command, true);
+ else if (window.attachEvent)
+ element.attachEvent("on" + eventName, command);
+}
+
+function showMessage(msg) {
+ window.readyStateText.push(msg);
+ document.getElementById("display").innerHTML = readyStateText.join("<br>");
+}
+
+function frameLoad() {
+ var doc = $('iframe').contentWindow.document;
+ is(doc.readyState, "complete", "frame document.readyState should be 'complete' on load");
+ showMessage("frame load: " + doc.readyState);
+ if (window.loaded) SimpleTest.finish();
+}
+
+function load() {
+ window.loaded = true;
+
+ var imgsrc = "<img onload ='window.parent.imgLoad()' src='image.png?noCache="
+ + (new Date().getTime()) + "'>\n";
+ var doc = $('iframe').contentWindow.document;
+ doc.writeln(imgsrc);
+ doc.close();
+ showMessage("frame after document.write: " + doc.readyState);
+ isnot(doc.readyState, "complete", "frame document.readyState should not be 'complete' after document.write");
+}
+
+function imgLoad() {
+ var doc = $('iframe').contentWindow.document;
+ showMessage("frame after imgLoad: " + doc.readyState);
+ is(doc.readyState, "interactive", "frame document.readyState should still be 'interactive' after img loads");
+}
+
+window.onload=load;
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+<iframe src="404doesnotexist" id="iframe" onload="frameLoad();"></iframe>
+</body>
+</html>
diff --git a/dom/html/test/test_bug347174_xsl.html b/dom/html/test/test_bug347174_xsl.html
new file mode 100644
index 000000000..4fdfd9122
--- /dev/null
+++ b/dom/html/test/test_bug347174_xsl.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=347174
+-->
+<head>
+ <title>Test for Bug 347174</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=347174">Mozilla Bug 347174</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe src="347174transformable.xml" id="iframe"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 347174 **/
+// Test of readyState of XML document transformed via XSLT to HTML
+// this test passes in IE7
+window.readyStateText = [];
+
+function showMessage(msg) {
+ window.readyStateText.push(msg);
+ document.getElementById("display").innerHTML = readyStateText.join("<br>");
+}
+
+function frameScriptTag(readyState) {
+ isnot(readyState, "complete", "document.readyState should not be 'complete' when scripts run initially");
+ showMessage("script tag: " + readyState);
+}
+
+function frameLoad(readyState) {
+ is(readyState, "complete", "document.readyState should be 'complete' on load");
+ showMessage("load: " + readyState);
+ SimpleTest.finish();
+}
+
+function frameReadyStateChange(readyState) {
+ showMessage("readyStateChange: " + readyState);
+}
+
+function frameDOMContentLoaded(readyState) {
+ is(readyState, "interactive", "document.readyState should be 'interactive' on DOMContentLoaded");
+ showMessage("DOMContentLoaded: " + readyState);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug347174_xslp.html b/dom/html/test/test_bug347174_xslp.html
new file mode 100644
index 000000000..ea4fc79b5
--- /dev/null
+++ b/dom/html/test/test_bug347174_xslp.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=347174
+-->
+<head>
+ <title>Test for Bug 347174</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=347174">Mozilla Bug 347174</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 347174 **/
+// verifies that documents created with createDocument are born in "complete" state
+// (so we don't accidentally leave them in "interactive" state)
+window.readyStateText = [];
+
+function xmlLoaded(e) {
+ var xslDoc = document.implementation.createDocument("", "test", null);
+ xslDoc.async=false;
+ xslDoc.load("347174transform.xsl");
+
+ var processor = new XSLTProcessor();
+ processor.importStylesheet(xslDoc);
+
+ window.transformedDoc = processor.transformToDocument(xmlDoc);
+
+ showMessage("loaded: " + xmlDoc.readyState);
+ is(xmlDoc.readyState, "complete", "XML document.readyState should be 'complete' after transform");
+ SimpleTest.finish();
+}
+
+var xmlDoc = document.implementation.createDocument("", "test", null);
+showMessage("createDocument: " + xmlDoc.readyState);
+is(xmlDoc.readyState, "complete", "created document readyState should be 'complete' before being associated with a parser");
+xmlDoc.async=true;
+xmlDoc.addEventListener("load", xmlLoaded, false);
+xmlDoc.load("347174transformable.xml");
+showMessage("load called: " + xmlDoc.readyState);
+isnot(xmlDoc.readyState, "complete", "created document readyState should not be 'complete' after load called");
+
+
+function showMessage(msg) {
+ window.readyStateText.push(msg);
+ $("display").innerHTML = readyStateText.join("<br>");
+}
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug353415-1.html b/dom/html/test/test_bug353415-1.html
new file mode 100644
index 000000000..1f528ae6f
--- /dev/null
+++ b/dom/html/test/test_bug353415-1.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<iframe name="submit_frame"></iframe>
+<form method="get" id="form1" target="submit_frame" action="../../../../../blah">
+<input type="text" name="field1" value="teststring"><br>
+<input type="radio" name="field2" value="0" checked> 0
+<input type="radio" name="field3" value="1"> 1<br>
+<input type="checkbox" name="field4" value="1" checked> 1
+<input type="checkbox" name="field5" value="2"> 2
+<input type="checkbox" name="field6" value="3" checked> 3
+<select name="field7">
+<option value="1">1</option>
+<option value="2" selected>2</option>
+<option value="3">3</option>
+<option value="4">4</option>
+</select>
+<input name="field8" value="8">
+<input name="field9" value="9">
+<input type="image" name="field10">
+<label name="field11">
+<input name="field12">
+<input type="button" name="field13" value="button">
+</form>
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ document.getElementsByName('submit_frame')[0].onload = function() {
+ is(frames['submit_frame'].location.href, "http://mochi.test:8888/blah?field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=", "Submit string was correct.");
+ SimpleTest.finish();
+ };
+
+ document.forms[0].submit();
+ });
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug353415-2.html b/dom/html/test/test_bug353415-2.html
new file mode 100644
index 000000000..9e82e9df8
--- /dev/null
+++ b/dom/html/test/test_bug353415-2.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<iframe name="submit_frame"></iframe>
+<form method="get" id="form1" target="submit_frame" action="../../../../../blah">
+<table>
+<tr><td>
+<input type="text" name="field1" value="teststring"><br>
+<input type="radio" name="field2" value="0" checked> 0
+<input type="radio" name="field3" value="1"> 1<br>
+<input type="checkbox" name="field4" value="1" checked> 1
+<input type="checkbox" name="field5" value="2"> 2
+<input type="checkbox" name="field6" value="3" checked> 3
+<select name="field7">
+<option value="1">1</option>
+<option value="2" selected>2</option>
+<option value="3">3</option>
+<option value="4">4</option>
+</select>
+<input name="field8" value="8">
+<input name="field9" value="9">
+<input type="image" name="field10">
+<label name="field11"></label>
+<input name="field12">
+<input type="button" name="field13" value="button">
+<input type="hidden" name="field14" value="14">
+</td>
+<input type="text" name="field1-2" value="teststring"><br>
+<input type="radio" name="field2-2" value="0" checked> 0
+<input type="radio" name="field3-2" value="1"> 1<br>
+<input type="checkbox" name="field4-2" value="1" checked> 1
+<input type="checkbox" name="field5-2" value="2"> 2
+<input type="checkbox" name="field6-2" value="3" checked> 3
+<select name="field7-2">
+<option value="1">1</option>
+<option value="2" selected>2</option>
+<option value="3">3</option>
+<option value="4">4</option>
+</select>
+<input name="field8-2" value="8">
+<input name="field9-2" value="9">
+<input type="image" name="field10-2">
+<label name="field11-2"></label>
+<input name="field12-2">
+<input type="button" name="field13-2" value="button">
+<input type="hidden" name="field14-2" value="14">
+</tr>
+</table>
+</form>
+<script>
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ document.getElementsByName('submit_frame')[0].onload = function() {
+ is(frames['submit_frame'].location.href, "http://mochi.test:8888/blah?field1-2=teststring&field2-2=0&field4-2=1&field6-2=3&field7-2=2&field8-2=8&field9-2=9&field12-2=&field1=teststring&field2=0&field4=1&field6=3&field7=2&field8=8&field9=9&field12=&field14=14&field14-2=14", "Submit string was correct.");
+ SimpleTest.finish();
+ };
+
+ document.forms[0].submit();
+ });
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug359657.html b/dom/html/test/test_bug359657.html
new file mode 100644
index 000000000..f6fcb716e
--- /dev/null
+++ b/dom/html/test/test_bug359657.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=359657
+-->
+<head>
+ <title>Test for Bug 359657</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=359657">Mozilla Bug 359657</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+/** Test for Bug 359657 **/
+function runTest() {
+ var span = document.createElement("span");
+ $("test").insertBefore(span, $("test").firstChild);
+ ok(true, "Reachability", "We should get here without crashing");
+ is($("test").firstChild, span, "First child is correct");
+ SimpleTest.finish();
+}
+</script>
+<div>
+ <iframe src=""></iframe>
+ <!-- Important: This test needs to run async at this point. The actual test
+ is not crashing while running this test! -->
+ <script type="text/javascript" src="data:text/javascript,runTest()"></script>
+</div>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug369370.html b/dom/html/test/test_bug369370.html
new file mode 100644
index 000000000..6b27b3849
--- /dev/null
+++ b/dom/html/test/test_bug369370.html
@@ -0,0 +1,151 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=369370
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Test for Bug 369370</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+ <script type="text/javascript">
+ /*
+ * Test strategy:
+ */
+ function makeClickFor(x, y) {
+ var event = kidDoc.createEvent("mouseevent");
+ event.initMouseEvent("click",
+ true, true, kidWin, 1, // bubbles, cancelable, view, single-click
+ x, y, x, y, // screen X/Y, client X/Y
+ false, false, false, false, // no key modifiers
+ 0, null); // left click, not relatedTarget
+ return event;
+ }
+
+ function childLoaded() {
+ kidDoc = kidWin.document;
+ ok(true, "Child window loaded");
+
+ var elements = kidDoc.getElementsByTagName("img");
+ is(elements.length, 1, "looking for imagedoc img");
+ var img = elements[0];
+
+ // Need to use innerWidth/innerHeight of the window
+ // since the containing image is absolutely positioned,
+ // causing clientHeight to be zero.
+ is(kidWin.innerWidth, 400, "Checking doc width");
+ is(kidWin.innerHeight, 300, "Checking doc height");
+
+ // Image just loaded and is scaled to window size.
+ is(img.width, 400, "image width");
+ is(img.height, 300, "image height");
+ is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft");
+ is(kidDoc.body.scrollTop, 0, "Checking scrollTop");
+
+ // ========== test 1 ==========
+ // Click in the upper left to zoom in
+ var event = makeClickFor(25,25);
+ img.dispatchEvent(event);
+ ok(true, "----- click 1 -----");
+
+ is(img.width, 800, "image width");
+ is(img.height, 600, "image height");
+ is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft");
+ is(kidDoc.body.scrollTop, 0, "Checking scrollTop");
+
+ // ========== test 2 ==========
+ // Click there again to zoom out
+ event = makeClickFor(25,25);
+ img.dispatchEvent(event);
+ ok(true, "----- click 2 -----");
+
+ is(img.width, 400, "image width");
+ is(img.height, 300, "image height");
+ is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft");
+ is(kidDoc.body.scrollTop, 0, "Checking scrollTop");
+
+ // ========== test 3 ==========
+ // Click in the lower right to zoom in
+ event = makeClickFor(350, 250);
+ img.dispatchEvent(event);
+ ok(true, "----- click 3 -----");
+
+ is(img.width, 800, "image width");
+ is(img.height, 600, "image height");
+ is(kidDoc.body.scrollLeft, 400, "Checking scrollLeft");
+ is(kidDoc.body.scrollTop, 300, "Checking scrollTop");
+
+ // ========== test 4 ==========
+ // Click there again to zoom out
+ event = makeClickFor(350, 250);
+ img.dispatchEvent(event);
+ ok(true, "----- click 4 -----");
+
+ is(img.width, 400, "image width");
+ is(img.height, 300, "image height");
+ is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft");
+ is(kidDoc.body.scrollTop, 0, "Checking scrollTop");
+
+ // ========== test 5 ==========
+ // Click in the upper left to zoom in again
+ event = makeClickFor(25, 25);
+ img.dispatchEvent(event);
+ ok(true, "----- click 5 -----");
+ is(img.width, 800, "image width");
+ is(img.height, 600, "image height");
+ is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft");
+ is(kidDoc.body.scrollTop, 0, "Checking scrollTop");
+ is(img.getBoundingClientRect().top, 0, "Image is in view vertically");
+
+ // ========== test 6 ==========
+ // Now try resizing the window so the image fits vertically.
+ function test6() {
+ kidWin.addEventListener("resize", function resizeListener() {
+ kidWin.removeEventListener("resize", resizeListener);
+ // Give the image document time to respond
+ SimpleTest.executeSoon(function() {
+ is(img.height, 600, "image height");
+ is(img.getBoundingClientRect().top, 25, "Image is vertically centered");
+ test7();
+ });
+ });
+
+ var decorationSize = kidWin.outerHeight - kidWin.innerHeight;
+ kidWin.resizeTo(400, 600 + 50 + decorationSize);
+ }
+
+ // ========== test 7 ==========
+ // Now try resizing the window so the image no longer fits vertically.
+ function test7() {
+ kidWin.addEventListener("resize", function resizeListener() {
+ kidWin.removeEventListener("resize", resizeListener);
+ // Give the image document time to respond
+ SimpleTest.executeSoon(function() {
+ is(img.height, 600, "image height");
+ is(img.getBoundingClientRect().top, 0, "Image is at top again");
+ kidWin.close();
+ SimpleTest.finish();
+ });
+ });
+
+ var decorationSize = kidWin.outerHeight - kidWin.innerHeight;
+ kidWin.resizeTo(400, 300 + decorationSize);
+ }
+
+ test6();
+ }
+ var kidWin;
+ var kidDoc;
+
+ SimpleTest.waitForExplicitFinish();
+ SpecialPowers.pushPrefEnv({"set":[["browser.enable_automatic_image_resizing", true]]}, function() {
+ kidWin = window.open("bug369370-popup.png", "bug369370", "width=400,height=300,scrollbars=no");
+ // will init onload
+ ok(kidWin, "opened child window");
+ kidWin.onload = childLoaded;
+ });
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug371375.html b/dom/html/test/test_bug371375.html
new file mode 100644
index 000000000..e0e48656c
--- /dev/null
+++ b/dom/html/test/test_bug371375.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=371375
+-->
+<head>
+ <title>Test for Bug 371375</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=371375">Mozilla Bug 371375</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ /** Test for Bug 371375 **/
+ var load1Called = false;
+ var error1Called = false;
+ var s = document.createElement('script');
+ s.type = 'text/javascript';
+ s.onload = function() { load1Called = true; };
+ s.onerror = function(event) { error1Called = true; event.stopPropagation(); };
+ s.src = 'about:cache-entry?client=image&sb=0&key=http://www.google.com';
+ document.body.appendChild(s);
+
+ var load2Called = false;
+ var error2Called = false;
+ var s2 = document.createElement('script');
+ s2.type = 'text/javascript';
+ s2.onload = function() { load2Called = true; };
+ s2.onerror = function(event) { error2Called = true; event.stopPropagation(); };
+ s2.src = 'data:text/plain, var x = 1;'
+ document.body.appendChild(s2);
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(function() {
+ is(load1Called, false, "Load handler should not be called");
+ is(error1Called, true, "Error handler should be called");
+ is(load2Called, true, "Load handler for valid script should be called");
+ is(error2Called, false,
+ "Error handler for valid script should not be called");
+ SimpleTest.finish();
+ });
+</script>
+</body>
+</html>
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug372098.html b/dom/html/test/test_bug372098.html
new file mode 100644
index 000000000..1f00868a7
--- /dev/null
+++ b/dom/html/test/test_bug372098.html
@@ -0,0 +1,75 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=372098
+-->
+<head>
+ <title>Test for Bug 372098</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <base target="bug372098"></base>
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=372098">Mozilla Bug 372098</a>
+ <p id="display"></p>
+ <div id="content" style="display:none;">
+ <iframe name="bug372098"></iframe>
+ <a id="a" href="bug372098-link-target.html?a" target="">link</a>
+ <link id="link" href="bug372098-link-target.html?link" target=""/>
+ <map>
+ <area id="area" shape="default" href="bug372098-link-target.html?area" target=""/>
+ </map>
+ </div>
+ <pre id="test">
+ <script class="testbody" type="text/javascript">
+
+var a_passed = false;
+var link_passed = false;
+var area_passed = false;
+
+/* Start the test */
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(handle_load);
+
+function handle_load()
+{
+ sendMouseEvent({type:'click'}, 'a');
+}
+
+/* Finish the test */
+
+function finish_test()
+{
+ ok(a_passed, "The 'a' element used the correct target.");
+ ok(link_passed, "The 'link' element used the correct target.");
+ ok(area_passed, "The 'area' element used the correct target.");
+ SimpleTest.finish();
+}
+
+/* Callback function used by the linked document */
+
+function callback(tag)
+{
+ switch (tag) {
+ case 'a':
+ a_passed = true;
+ sendMouseEvent({type:'click'}, 'link');
+ return;
+ case 'link':
+ link_passed = true;
+ sendMouseEvent({type:'click'}, 'area');
+ return;
+ case 'area':
+ area_passed = true;
+ finish_test();
+ return;
+ }
+ throw new Error("Eh??? We only test the 'a', 'link' and 'area' elements.");
+}
+
+ </script>
+ </pre>
+
+</body>
+</html>
diff --git a/dom/html/test/test_bug373589.html b/dom/html/test/test_bug373589.html
new file mode 100644
index 000000000..eba0d9284
--- /dev/null
+++ b/dom/html/test/test_bug373589.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=373589
+-->
+<head>
+ <title>Test for Bug 373589</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=373589">Mozilla Bug 373589</a>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 373589 **/
+ var docElem = document.documentElement;
+ var body = document.body;
+ var numChildren = docElem.childNodes.length;
+ docElem.removeChild(body);
+ ok(numChildren > docElem.childNodes.length, "body was removed");
+ body.link;
+ ok(true, "didn't crash");
+ docElem.appendChild(body);
+ is(numChildren, docElem.childNodes.length, "body re-added");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug375003-1.html b/dom/html/test/test_bug375003-1.html
new file mode 100644
index 000000000..94f5aa7a8
--- /dev/null
+++ b/dom/html/test/test_bug375003-1.html
@@ -0,0 +1,156 @@
+<!DOCTYPE HTML>
+<html id="html">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=375003
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Test 1 for bug 375003</title>
+
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <style type="text/css">
+
+ html,body {
+ color:black; background-color:white; font-size:16px; padding:0; margin:0;
+ }
+
+ .s { display:block; width:20px; height:20px; background-color:lime; }
+ table { background:pink; }
+ #td5,#td6 { border:7px solid blue;}
+ </style>
+
+<script>
+var x = [ 'Left','Top','Width','Height' ];
+function test(id,s,expected) {
+ var el = document.getElementById(id);
+ for(var i = 0; i < x.length; ++i) {
+ var actual = eval('el.'+s+x[i]);
+ if (expected[i] != -1 && s+x[i]!='scrollHeight')
+ is(actual, expected[i], id+"."+s+x[i]);
+ }
+}
+function t3(id,c,o,s,pid) {
+ test(id,'client',c);
+ test(id,'offset',o);
+ test(id,'scroll',s);
+ var p = document.getElementById(id).offsetParent;
+ is(p.id, pid, id+".offsetParent");
+}
+
+function run_test() {
+ t3('span1',[0,0,20,20],[12,12,20,20],[0,0,20,20],'td1');
+ t3('td1' ,[1,1,69,44],[16,16,71,46],[0,0,69,46],'table1');
+ t3('tr1' ,[0,0,71,46],[16,16,71,46],[0,0,71,44],'table1');
+ t3('span2',[10,0,20,20],[27,12,30,20],[0,0,20,20],'td2');
+ t3('table1',[9,9,85,113],[10,10,103,131],[0,0,85,50],'body');
+ t3('div1',[10,10,-1,131],[0,0,-1,151],[0,0,-1,85],'body');
+
+ t3('span2b',[10,0,20,20],[25,-1,30,20],[0,0,20,20],'body');
+ // XXX not sure how to make reliable cross-platform tests for replaced-inline, inline
+ // t3('span2c',[10,2,18,2],[25,-1,30,6],[0,0,30,20],'body');
+ // t3('span2d',[0,0,0,0],[25,-1,10,19],[0,0,10,20],'body');
+
+ t3('span3' ,[0,0,20,20],[15,0,20,20],[0,0,20,20],'td3');
+ t3('td3' ,[0,0,35,20],[0,0,35,20],[0,0,35,20],'table3');
+ t3('tr3' ,[0,0,35,20],[0,0,35,20],[0,0,35,22],'table3');
+ t3('span4' ,[0,0,20,20],[0,0,20,20],[0,0,20,20],'td4');
+ t3('table3',[0,0,35,40],[0,0,35,40],[0,0,35,50],'div3');
+ t3('div3',[10,10,-1,40],[0,151,-1,60],[0,0,-1,70],'body');
+
+ t3('span5' ,[0,0,20,20],[1,1,20,20],[0,0,20,20],'td5');
+ t3('td5' ,[7,7,22,22],[2,2,36,36],[0,0,22,36],'table5');
+ t3('tr5' ,[0,0,36,36],[2,2,36,36],[0,0,36,22],'table5');
+ t3('span6' ,[0,0,20,20],[20,58,20,20],[0,0,20,20],'div5');
+ t3('table5',[0,0,40,78],[0,0,40,78],[0,0,40,78],'div5');
+ t3('div5',[10,10,-1,78],[0,211,-1,98],[0,0,-1,70],'body');
+
+ t3('span7' ,[0,0,20,20],[1,1,20,20],[0,0,20,20],'td7');
+ t3('td7' ,[1,1,37,22],[9,9,39,24],[0,0,37,22],'table7');
+ t3('tr7' ,[0,0,39,24],[9,9,39,24],[0,0,39,22],'table7');
+ t3('span8' ,[0,0,20,20],[26,37,20,20],[0,0,20,20],'table7');
+ t3('table7',[7,7,43,54],[10,319,57,68],[0,0,43,50],'body');
+ t3('div7',[10,10,-1,68],[0,309,-1,88],[0,0,-1,70],'body');
+
+ t3('span9' ,[0,0,20,20],[1,1,20,20],[0,0,20,20],'td9');
+ t3('td9' ,[1,1,22,22],[15,15,24,24],[0,0,22,24],'table9');
+ t3('tr9' ,[0,0,24,24],[15,15,24,24],[0,0,24,22],'table9');
+ t3('span10' ,[0,0,20,20],[17,43,20,20],[0,0,20,20],'table9');
+ t3('table9',[13,13,28,34],[10,407,54,60],[0,0,28,50],'body');
+ t3('div9',[10,10,-1,0],[0,397,-1,20],[0,0,-1,70],'body');
+
+ t3('span11' ,[0,0,20,20],[1,1,20,20],[0,0,20,20],'td11');
+ t3('td11' ,[0,0,22,22],[2,2,22,22],[0,0,22,22],'table11');
+ t3('tr11' ,[0,0,22,22],[2,2,22,22],[0,0,22,22],'table11');
+ t3('span12' ,[0,0,20,20],[28,454,20,20],[0,0,20,20],'body');
+ t3('table11',[0,0,26,30],[10,427,26,30],[0,0,26,50],'body');
+ t3('div11',[10,10,-1,30],[0,417,-1,50],[0,0,-1,70],'body');
+}
+</script>
+</head>
+<body id="body">
+
+<div id="content">
+<div id="div1" style="border:10px solid black">
+<table id="table1" cellspacing="7" cellpadding="12" border="9">
+ <tbody id="tbody1"><tr id="tr1"><td id="td1"><div class="s" id="span1"></div></td></tr></tbody>
+ <tbody id="tbody2"><tr id="tr2"><td id="td2"><div class="s" id="span2" style="margin-left:15px; border-left:10px solid blue;"></div></td></tr></tbody>
+</table>
+</div>
+
+<div id="div3" style="border:10px solid black; position:relative">
+<table id="table3" cellpadding="0" cellspacing="0" border="0">
+ <tbody id="tbody3"><tr id="tr3"><td id="td3"><div class="s" id="span3" style="margin-left:15px"></div></td></tr></tbody>
+ <tbody id="tbody4"><tr id="tr4"><td id="td4"><div class="s" id="span4"></div></td></tr></tbody>
+</table>
+</div>
+
+<div id="div5" style="border:10px solid black; position:relative">
+<table id="table5">
+ <tbody id="tbody5"><tr id="tr5"><td id="td5"><div class="s" id="span5"></div></td></tr></tbody>
+ <tbody id="tbody6"><tr id="tr6"><td id="td6"><div class="s" id="span6" style="left:10px; top:10px; position:relative"></div></td></tr></tbody>
+</table>
+</div>
+
+<div id="div7" style="border:10px solid black;">
+<table id="table7" style="position:relative" border=7>
+ <tbody id="tbody7"><tr id="tr7"><td id="td7"><div class="s" id="span7"></div></td></tr></tbody>
+ <tbody id="tbody8"><tr id="tr8"><td id="td8"><div class="s" id="span8" style="position:relative; margin-left:15px"></div></td></tr></tbody>
+</table>
+</div>
+
+<div id="div9" style="border:10px solid black;">
+<table id="table9" style="position:absolute" border="13">
+ <tbody id="tbody9"><tr id="tr9"><td id="td9"><div class="s" id="span9"></div></td></tr></tbody>
+ <tbody id="tbody10"><tr id="tr10"><td id="td10"><div class="s" id="span10" style="position:absolute"></div></td></tr></tbody>
+</table>
+</div>
+
+<div id="div11" style="border:10px solid black; ">
+<table id="table11">
+ <tbody id="tbody11"><tr id="tr11"><td id="td11"><div class="s" id="span11"></div></td></tr></tbody>
+ <tbody id="tbody12"><tr id="tr12"><td id="td12"><div class="s" id="span12" style="position:absolute;margin-left:15px"></div></td></tr></tbody>
+</table>
+</div>
+
+<div style="border:10px solid black">
+<div class="s" id="span2b" style="margin-left:15px; border-left:10px solid blue;"></div></div>
+
+<div style="border:10px solid black">
+<button id="span2c" style="margin-left:15px; border-left:10px solid blue;"></button></div>
+
+<div style="border:10px solid black">
+<span id="span2d" style="margin-left:15px; border-left:10px solid blue;"></span></div>
+</div>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=375003">Mozilla Bug 375003</a>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+run_test();
+</script>
+</pre>
+
+</body>
+</html>
diff --git a/dom/html/test/test_bug375003-2.html b/dom/html/test/test_bug375003-2.html
new file mode 100644
index 000000000..f22397a61
--- /dev/null
+++ b/dom/html/test/test_bug375003-2.html
@@ -0,0 +1,109 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=375003
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Test 2 for bug 375003</title>
+
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <style type="text/css">
+
+ html {
+ padding:0; margin:0;
+ }
+ body {
+ color:black; background-color:white; font-size:12px; padding:10px; margin:0;
+ }
+
+ #div1,#abs1,#table1 {
+ border: 20px solid lime;
+ padding: 30px;
+ width: 100px;
+ height: 60px;
+ overflow:scroll;
+ }
+ #abs1,#table2parent {
+ position:absolute;
+ left:500px;
+ }
+ #table3parent {
+ position:fixed;
+ left:300px;
+ top:100px;
+ }
+ .content {
+ display:block;
+ width:200px;
+ height:200px;
+ background:yellow;
+ border: 0px dotted black;
+ }
+</style>
+
+
+<script type="text/javascript">
+var x = [ 'Left','Top','Width','Height' ];
+function test(id,s,expected) {
+ var el = document.getElementById(id);
+ for(var i = 0; i < x.length; ++i) {
+ var actual = eval('el.'+s+x[i]);
+ if (expected[i] != -1 && s+x[i]!='scrollHeight')
+ is(actual, expected[i], id+"."+s+x[i]);
+ }
+}
+function t3(id,c,o,s,pid) {
+ test(id,'client',c);
+ test(id,'offset',o);
+ test(id,'scroll',s);
+ var p = document.getElementById(id).offsetParent;
+ is(p.id, pid, id+".offsetParent");
+}
+
+function run_test() {
+ // XXX how test clientWidth/clientHeight (the -1 below) in cross-platform manner
+ // without hard-coding the scrollbar width?
+ t3('div1',[20,20,-1,-1],[10,10,200,160],[0,0,230,20],'body');
+ t3('abs1',[20,20,-1,-1],[500,170,200,160],[0,0,230,20],'body');
+ t3('table1',[20,20,266,266],[10,170,306,306],[0,0,266,20],'body');
+ t3('table2',[0,0,206,206],[0,0,206,206],[0,0,206,20],'table2parent');
+ t3('table3',[10,10,208,208],[0,0,228,228],[0,0,208,228],'table3parent');
+ t3('table3parent',[0,0,228,228],[300,100,228,228],[0,0,228,228],'body');
+}
+</script>
+
+</head>
+<body id="body">
+<div id="content">
+<div id="div1parent">
+ <div id="div1"><span class="content">DIV</span></div>
+</div>
+
+<div id="abs1parent">
+ <div id="abs1"><span class="content">abs.pos.DIV</span></div>
+</div>
+
+<div id="table1parent">
+ <table id="table1"><tbody><tr><td id="td1"><span class="content">TABLE</span></td></tr></tbody></table>
+</div>
+
+<div id="table2parent">
+ <table id="table2"><tbody><tr><td id="td2"><span class="content">TABLE in abs</span></td></tr></tbody></table>
+</div>
+
+<div id="table3parent">
+ <table id="table3" border="10"><tbody><tr><td id="td3"><span class="content">TABLE in fixed</span></td></tr></tbody></table>
+</div>
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+run_test();
+</script>
+</pre>
+
+</body>
+</html>
diff --git a/dom/html/test/test_bug377624.html b/dom/html/test/test_bug377624.html
new file mode 100644
index 000000000..fa0a137ee
--- /dev/null
+++ b/dom/html/test/test_bug377624.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=377624
+-->
+<head>
+ <title>Test for Bug 377624</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=377624">Mozilla Bug 377624</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 377624 **/
+
+var input = document.createElement('input');
+ok("accept" in input, "'accept' is a valid input property");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug380383.html b/dom/html/test/test_bug380383.html
new file mode 100644
index 000000000..c5d9823ae
--- /dev/null
+++ b/dom/html/test/test_bug380383.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=380383
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+ <title>Test for Bug 380383</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=380383">Mozilla Bug 380383</a>
+<p id="display">
+ <iframe id="f1" name="f1"></iframe>
+ <iframe id="f2" name="f2"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+ /** Test for Bug 380383 **/
+ is($("f1").contentDocument.characterSet, "UTF-8",
+ "Unexpected charset for f1");
+
+ function runTest() {
+ is($("f2").contentDocument.characterSet, "UTF-8",
+ "Unexpected charset for f2");
+ }
+
+ addLoadEvent(runTest);
+ addLoadEvent(SimpleTest.finish);
+ SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug383383.html b/dom/html/test/test_bug383383.html
new file mode 100644
index 000000000..922dc5b4f
--- /dev/null
+++ b/dom/html/test/test_bug383383.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=383383
+-->
+<head>
+ <title>Test for Bug 383383</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=383383">Mozilla Bug 383383</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript" for=" window " event=" onload() ">
+
+var foo = "bar";
+
+</script>
+
+<script class="testbody" type="text/javascript" for="object" event="handler">
+
+// This script should fail to run
+foo = "baz";
+
+isnot(foo, "baz", "test failed");
+
+</script>
+
+<script class="testbody" type="text/javascript">
+
+ok(foo == "bar", "test passed");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug383383_2.xhtml b/dom/html/test/test_bug383383_2.xhtml
new file mode 100644
index 000000000..4dccd381c
--- /dev/null
+++ b/dom/html/test/test_bug383383_2.xhtml
@@ -0,0 +1,20 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Test for bug 383383</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+ <script>
+ SimpleTest.waitForExplicitFinish()
+ </script>
+ <script for="window" event="bar">
+ // This script should not run, but should not cause a parse error either.
+ ok(false, "Script was unexpectedly run")
+ </script>
+ <script>
+ ok(true, "Script was run as it should")
+ SimpleTest.finish()
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug384419.html b/dom/html/test/test_bug384419.html
new file mode 100644
index 000000000..c66a4c3ad
--- /dev/null
+++ b/dom/html/test/test_bug384419.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=384419
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <title>Test for bug 384419</title>
+
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+ <style type="text/css">
+ html,body {
+ color:black; background-color:white; font-size:16px; padding:0; margin:0;
+ }
+ body { margin: 10px; }
+ table { border:15px solid black; margin-left:100px; }
+</style>
+
+
+<script type="text/javascript">
+function t3(id,expected,pid) {
+ var el = document.getElementById(id);
+ var actual = el.offsetLeft;
+ is(actual, expected, id+".offsetLeft");
+
+ var p = document.getElementById(id).offsetParent;
+ is(p.id, pid, id+".offsetParent");
+}
+
+function run_test() {
+ t3('rel384419',135,'body');
+ t3('abs384419',135,'body');
+ t3('fix384419',135,'body');
+}
+</script>
+
+</head>
+<body id="body">
+<!-- It's important for the test that the tables below are directly inside body -->
+<table cellpadding="7" cellspacing="3"><tr><td width="100"><div id="rel384419" style="position:relative;border:1px solid blue">X</div> relative</table>
+<table cellpadding="7" cellspacing="3"><tr><td width="100"><div id="abs384419" style="position:absolute;border:1px solid blue">X</div> absolute</table>
+<table cellpadding="7" cellspacing="3"><tr><td width="100"><div id="fix384419" style="position:fixed;border:1px solid blue">X</div> fixed</table>
+
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+run_test();
+</script>
+</pre>
+
+<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=384419">bug 384419</a>
+
+</body>
+</html>
diff --git a/dom/html/test/test_bug386496.html b/dom/html/test/test_bug386496.html
new file mode 100644
index 000000000..2d4f14632
--- /dev/null
+++ b/dom/html/test/test_bug386496.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=386496
+-->
+<head>
+ <title>Test for Bug 386496</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <SCRIPT Type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=386496">Mozilla Bug 386496</a>
+<p id="display"></p>
+<div id="content">
+ <iframe style='display: block;' id="testIframe"
+ src="data:text/html,<div><a id='a' href='http://a.invalid/'>Link</a></div>">
+ </iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 386496 **/
+
+var frame = document.getElementById("testIframe");
+
+function testDesignMode() {
+ var unloadRequested = false;
+
+ frame.contentDocument.designMode = "on";
+
+ frame.contentWindow.addEventListener("beforeunload", function() {
+ unloadRequested = true;
+ }, false);
+
+ synthesizeMouseAtCenter(frame.contentDocument.getElementById("a"), {},
+ frame.contentWindow);
+
+ // The click has been sent. If 'beforeunload' event has been caught when we go
+ // back from the event loop that means the link has been activated.
+ setTimeout(function() {
+ ok(!unloadRequested, "The link should not be activated in designMode");
+ SimpleTest.finish();
+ }, 0);
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(testDesignMode);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug386728.html b/dom/html/test/test_bug386728.html
new file mode 100644
index 000000000..5a10b31a8
--- /dev/null
+++ b/dom/html/test/test_bug386728.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=386728
+-->
+<head>
+ <title>Test for Bug 386728</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=386728">Mozilla Bug 386728</a>
+<p id="display"></p>
+<div id="content">
+ <div id="frameContent">
+ <div id="edit">This text is editable</div>
+ <button id="button_on" onclick="document.getElementById('edit').setAttribute('contenteditable', 'true')"></button>
+ </div>
+ <iframe id="testIframe"></iframe>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 386728 **/
+
+var frame = document.getElementById("testIframe");
+
+function testContentEditable() {
+ frame.style.display = 'block';
+ var frameContent = frame.contentDocument.adoptNode(document.getElementById("frameContent"));
+ frame.contentDocument.body.appendChild(frameContent);
+ frame.contentDocument.getElementById("edit").contentEditable = "true";
+ frame.contentDocument.getElementById("edit").contentEditable = "false";
+ frame.contentDocument.getElementById("button_on").click();
+ is(frame.contentDocument.getElementById("edit").contentEditable, "true");
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(testContentEditable);
+addLoadEvent(SimpleTest.finish);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug386996.html b/dom/html/test/test_bug386996.html
new file mode 100644
index 000000000..4f667281f
--- /dev/null
+++ b/dom/html/test/test_bug386996.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=386996
+-->
+<head>
+ <title>Test for Bug 386996</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=386996">Mozilla Bug 386996</a>
+<p id="display"></p>
+<div id="content">
+ <input id="input1"><input disabled><input id="input2">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 386996 **/
+
+var frame = document.getElementById("testIframe");
+
+function testContentEditable() {
+ var focusedElement;
+ document.getElementById("input1").onfocus = function() { focusedElement = this };
+ document.getElementById("input2").onfocus = function() { focusedElement = this };
+
+ document.getElementById("input1").focus();
+ synthesizeKey("VK_TAB", {});
+
+ is(focusedElement.id, "input2");
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(testContentEditable);
+addLoadEvent(SimpleTest.finish);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug388558.html b/dom/html/test/test_bug388558.html
new file mode 100644
index 000000000..8e5258777
--- /dev/null
+++ b/dom/html/test/test_bug388558.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=388558
+-->
+<head>
+ <title>Test for Bug 388558</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=388558">Mozilla Bug 388558</a>
+<p id="display"></p>
+<div id="content">
+ <input type="text" id="input" onchange="++inputChange;">
+ <textarea id="textarea" onchange="++textareaChange;"></textarea>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 388558 **/
+var inputChange = 0;
+var textareaChange = 0;
+
+function testUserInput() {
+ var input = document.getElementById("input");
+ var textarea = SpecialPowers.wrap(document.getElementById("textarea"));
+
+ input.focus();
+ SpecialPowers.wrap(input).setUserInput("foo");
+ input.blur();
+ is(inputChange, 1, "Input element should have got one change event.");
+
+ input.focus();
+ input.value = "bar";
+ input.blur();
+ is(inputChange, 1,
+ "Change event dispatched when setting the value of the input element");
+
+ input.value = "";
+ is(inputChange, 1,
+ "Change event dispatched when setting the value of the input element (2).");
+
+ SpecialPowers.wrap(input).setUserInput("foo");
+ is(inputChange, 2,
+ "Change event dispatched when input element doesn't have focus.");
+
+ textarea.focus();
+ textarea.setUserInput("foo");
+ textarea.blur();
+ is(textareaChange, 1, "Textarea element should have got one change event.");
+
+ textarea.focus();
+ textarea.value = "bar";
+ textarea.blur();
+ is(textareaChange, 1,
+ "Change event dispatched when setting the value of the textarea element.");
+
+ textarea.value = "";
+ is(textareaChange, 1,
+ "Change event dispatched when setting the value of the textarea element (2).");
+
+ textarea.setUserInput("foo");
+ is(textareaChange, 1,
+ "Change event dispatched when textarea element doesn't have focus.");
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(testUserInput);
+addLoadEvent(SimpleTest.finish);
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug388746.html b/dom/html/test/test_bug388746.html
new file mode 100644
index 000000000..8f5e0997b
--- /dev/null
+++ b/dom/html/test/test_bug388746.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=388746
+-->
+<head>
+ <title>Test for Bug 388746</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=388746">Mozilla Bug 388746</a>
+<p id="display"></p>
+<div id="content">
+ <input>
+ <textarea></textarea>
+ <select>
+ <option>option1</option>
+ <optgroup label="optgroup">
+ <option>option2</option>
+ </optgroup>
+ </select>
+ <button>Button</button>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 388746 **/
+
+var previousEventTarget = "";
+
+function handler(evt) {
+ if (evt.eventPhase == 2) {
+ previousEventTarget = evt.target.localName.toLowerCase();
+ }
+}
+
+function testElementType(type) {
+ var el = document.getElementsByTagName(type)[0];
+ el.addEventListener("DOMAttrModified", handler, true);
+ el.setAttribute("foo", "bar");
+ ok(previousEventTarget == type,
+ type + " element should have got DOMAttrModified event.");
+}
+
+function test() {
+ testElementType("input");
+ testElementType("textarea");
+ testElementType("select");
+ testElementType("option");
+ testElementType("optgroup");
+ testElementType("button");
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(test);
+addLoadEvent(SimpleTest.finish);
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug388794.html b/dom/html/test/test_bug388794.html
new file mode 100644
index 000000000..0f3cfdbd2
--- /dev/null
+++ b/dom/html/test/test_bug388794.html
@@ -0,0 +1,104 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=388794
+-->
+<head>
+ <title>Test for Bug 388794</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ input { padding: 0; margin: 0; border: none; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=388794">Mozilla Bug 388794</a>
+<p id="display">
+ <form action="data:text/html," target="test1" method="GET">
+ <input id="test1image" type="image" name="testImage">
+ </form>
+ <form action="data:text/html," target="test2" method="GET">
+ <input id="test2image" type="image">
+ </form>
+ <form action="data:text/html," target="test3" method="GET">
+ <input id="test3image" type="image" src="nnc_lockup.gif" name="testImage">
+ </form>
+ <form action="data:text/html," target="test4" method="GET">
+ <input id="test4image" type="image" src="nnc_lockup.gif">
+ </form>
+ <form action="data:text/html," target="test5" method="GET">
+ <input id="test5image" type="image" src="nnc_lockup.gif" name="testImage">
+ </form>
+ <form action="data:text/html," target="test6" method="GET">
+ <input id="test6image" type="image" src="nnc_lockup.gif">
+ </form>
+ <iframe name="test1" id="test1"></iframe>
+ <iframe name="test2" id="test2"></iframe>
+ <iframe name="test3" id="test3"></iframe>
+ <iframe name="test4" id="test4"></iframe>
+ <iframe name="test5" id="test5"></iframe>
+ <iframe name="test6" id="test6"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 388794 **/
+SimpleTest.waitForExplicitFinish();
+
+var pendingLoads = 0;
+/* Use regex due to rounding error in Fennec with C++APZ enabled */
+var hrefs = {
+ test1: /data:text\/html,\?testImage\.x=0&testImage\.y=0/,
+ test2: /data:text\/html,\?x=0&y=0/,
+ test3: /data:text\/html,\?testImage\.x=0&testImage\.y=0/,
+ test4: /data:text\/html,\?x=0&y=0/,
+ test5: /data:text\/html,\?testImage\.x=[4-6]&testImage\.y=[4-6]/,
+ test6: /data:text\/html,\?x=[4-6]&y=[4-6]/,
+};
+
+function submitForm(idNum) {
+ $("test"+idNum).setAttribute("onload", "frameLoaded(this)");
+ $("test" + idNum + "image").focus();
+ sendKey("return");
+}
+
+function submitFormMouse(idNum) {
+ $("test"+idNum).setAttribute("onload", "frameLoaded(this)");
+ // Use 4.99 instead of 5 to guard against the possibility that the
+ // image's 'top' is exactly N + 0.5 pixels from the root. In that case
+ // we'd round up the widget mouse coordinate to N + 6, which relative
+ // to the image would be 5.5, which would get rounded up to 6 when
+ // submitting the form. Instead we round the widget mouse coordinate to
+ // N + 5, which relative to the image would be 4.5 which gets rounded up
+ // to 5.
+ synthesizeMouse($("test" + idNum + "image"), 4.99, 4.99, {});
+}
+
+addLoadEvent(function() {
+ // Need the timeout so painting has a chance to be unsuppressed.
+ setTimeout(function() {
+ submitForm(++pendingLoads);
+ submitForm(++pendingLoads);
+ submitForm(++pendingLoads);
+ submitForm(++pendingLoads);
+ submitFormMouse(++pendingLoads);
+ submitFormMouse(++pendingLoads);
+ }, 0);
+});
+
+function frameLoaded(frame) {
+ ok(hrefs[frame.name].test(frame.contentWindow.location.href),
+ "Unexpected href for frame " + frame.name, "expected to match: " + hrefs[frame.name].toString() + " got: " + frame.contentWindow.location.href);
+ if (--pendingLoads == 0) {
+ SimpleTest.finish();
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug389797.html b/dom/html/test/test_bug389797.html
new file mode 100644
index 000000000..884348b12
--- /dev/null
+++ b/dom/html/test/test_bug389797.html
@@ -0,0 +1,267 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=389797
+-->
+<head>
+ <title>Test for Bug 389797</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=389797">Mozilla Bug 389797</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 389797 **/
+var allTags = [];
+var classInfos = {};
+var interfaces = {};
+var interfacesNonClassinfo = {};
+
+function getClassName(tag) {
+ return "HTML" + classInfos[tag] + "Element";
+}
+
+function HTML_TAG(aTagName, aImplClass) {
+ allTags.push(aTagName);
+ classInfos[aTagName] = aImplClass;
+ interfaces[aTagName] = [ "nsIDOMEventTarget" ];
+
+ // Some interfaces don't appear in classinfo because other interfaces that
+ // inherit from them do.
+ interfacesNonClassinfo[aTagName] =
+ [ "nsIDOMNode",
+ "nsIDOMElement" ];
+
+ var interfaceName = "nsIDOM" + getClassName(aTagName);
+ if (interfaceName in SpecialPowers.Ci) { // no nsIDOMHTMLSpanElement
+ interfaces[aTagName].push(interfaceName);
+ interfacesNonClassinfo[aTagName].push("nsIDOMHTMLElement");
+ } else {
+ // Inherits directly from nsIDOMHTMLElement.
+ interfaces[aTagName].push("nsIDOMHTMLElement");
+ }
+
+ var interfaceNameNS = "nsIDOMNS" + getClassName(aTagName);
+ if (interfaceNameNS in SpecialPowers.Ci) {
+ interfaces[aTagName].push(interfaceNameNS);
+ }
+
+ if (arguments.length > 2) {
+ for (var i = 0; i < arguments[2].length; ++i) {
+ interfaces[aTagName].push(arguments[2][i]);
+ }
+ }
+
+ if (arguments.length > 3) {
+ for (i = 0; i < arguments[3].length; ++i) {
+ interfacesNonClassinfo[aTagName].push(arguments[3][i]);
+ }
+ }
+}
+
+const objectIfaces = [
+ "imgINotificationObserver", "nsIRequestObserver", "nsIStreamListener",
+ "nsIFrameLoaderOwner", "nsIObjectLoadingContent", "nsIChannelEventSink"
+ ];
+
+var objectIfaces2 = [];
+for (var iface of objectIfaces) {
+ objectIfaces2.push(iface);
+}
+objectIfaces2.push("nsIImageLoadingContent");
+
+/* List copy/pasted from nsHTMLTagList.h, with the second field modified to the
+ correct classinfo (instead of the impl class) in the following cases:
+
+ applet
+ base
+ blockquote
+ dir
+ dl
+ embed
+ menu
+ ol
+ param
+ q
+ ul
+ wbr
+ head
+ html
+ */
+
+HTML_TAG("a", "Anchor");
+HTML_TAG("abbr", "");
+HTML_TAG("acronym", "");
+HTML_TAG("address", "");
+HTML_TAG("applet", "Applet", [], objectIfaces);
+HTML_TAG("area", "Area");
+HTML_TAG("article", "");
+HTML_TAG("aside", "");
+HTML_TAG("b", "");
+HTML_TAG("base", "Base");
+HTML_TAG("bdo", "");
+HTML_TAG("bgsound", "Unknown");
+HTML_TAG("big", "");
+HTML_TAG("blockquote", "Quote");
+HTML_TAG("body", "Body");
+HTML_TAG("br", "BR");
+HTML_TAG("button", "Button");
+HTML_TAG("canvas", "Canvas");
+HTML_TAG("caption", "TableCaption");
+HTML_TAG("center", "");
+HTML_TAG("cite", "");
+HTML_TAG("code", "");
+HTML_TAG("col", "TableCol");
+HTML_TAG("colgroup", "TableCol");
+HTML_TAG("data", "Data");
+HTML_TAG("datalist", "DataList");
+HTML_TAG("dd", "");
+HTML_TAG("del", "Mod");
+HTML_TAG("dfn", "");
+HTML_TAG("dir", "Directory");
+HTML_TAG("div", "Div");
+HTML_TAG("dl", "DList");
+HTML_TAG("dt", "");
+HTML_TAG("em", "");
+HTML_TAG("embed", "Embed", [], objectIfaces);
+HTML_TAG("fieldset", "FieldSet");
+HTML_TAG("figcaption", "")
+HTML_TAG("figure", "")
+HTML_TAG("font", "Font");
+HTML_TAG("footer", "")
+HTML_TAG("form", "Form", [], [ "nsIWebProgressListener" ]);
+HTML_TAG("frame", "Frame", [ "nsIDOMMozBrowserFrame" ], [ "nsIFrameLoaderOwner" ]);
+HTML_TAG("frameset", "FrameSet");
+HTML_TAG("h1", "Heading");
+HTML_TAG("h2", "Heading");
+HTML_TAG("h3", "Heading");
+HTML_TAG("h4", "Heading");
+HTML_TAG("h5", "Heading");
+HTML_TAG("h6", "Heading");
+HTML_TAG("head", "Head");
+HTML_TAG("header", "")
+HTML_TAG("hgroup", "")
+HTML_TAG("hr", "HR");
+HTML_TAG("html", "Html");
+HTML_TAG("i", "");
+HTML_TAG("iframe", "IFrame", [ "nsIDOMMozBrowserFrame" ],
+ [ "nsIFrameLoaderOwner" ]);
+HTML_TAG("image", "");
+HTML_TAG("img", "Image", [ "nsIImageLoadingContent" ], []);
+HTML_TAG("input", "Input", [], [ "imgINotificationObserver",
+ "nsIImageLoadingContent",
+ "nsIDOMNSEditableElement" ]);
+HTML_TAG("ins", "Mod");
+HTML_TAG("kbd", "");
+HTML_TAG("keygen", "Span");
+HTML_TAG("label", "Label");
+HTML_TAG("legend", "Legend");
+HTML_TAG("li", "LI");
+HTML_TAG("link", "Link");
+HTML_TAG("listing", "Pre");
+HTML_TAG("main", "");
+HTML_TAG("map", "Map");
+HTML_TAG("mark", "");
+HTML_TAG("marquee", "Div");
+HTML_TAG("menu", "Menu");
+HTML_TAG("meta", "Meta");
+HTML_TAG("meter", "Meter");
+HTML_TAG("multicol", "Unknown");
+HTML_TAG("nav", "")
+HTML_TAG("nobr", "");
+HTML_TAG("noembed", "");
+HTML_TAG("noframes", "");
+HTML_TAG("noscript", "");
+HTML_TAG("object", "Object", [],
+ objectIfaces.concat([ "nsIImageLoadingContent" ]));
+HTML_TAG("ol", "OList");
+HTML_TAG("optgroup", "OptGroup");
+HTML_TAG("option", "Option");
+HTML_TAG("p", "Paragraph");
+HTML_TAG("param", "Param");
+HTML_TAG("plaintext", "");
+HTML_TAG("pre", "Pre");
+HTML_TAG("q", "Quote");
+HTML_TAG("rb", "");
+HTML_TAG("rp", "");
+HTML_TAG("rt", "");
+HTML_TAG("rtc", "");
+HTML_TAG("ruby", "");
+HTML_TAG("s", "");
+HTML_TAG("samp", "");
+HTML_TAG("script", "Script", [ "nsIScriptLoaderObserver" ], []);
+HTML_TAG("section", "")
+HTML_TAG("select", "Select", ["nsIDOMHTMLSelectElement"]);
+HTML_TAG("small", "");
+HTML_TAG("span", "Span");
+HTML_TAG("strike", "");
+HTML_TAG("strong", "");
+HTML_TAG("style", "Style");
+HTML_TAG("sub", "");
+HTML_TAG("sup", "");
+HTML_TAG("table", "Table");
+HTML_TAG("tbody", "TableSection");
+HTML_TAG("td", "TableCell");
+HTML_TAG("textarea", "TextArea", [], [ "nsIDOMNSEditableElement" ]);
+HTML_TAG("tfoot", "TableSection");
+HTML_TAG("th", "TableCell");
+HTML_TAG("thead", "TableSection");
+HTML_TAG("template", "Template");
+HTML_TAG("time", "Time");
+HTML_TAG("title", "Title");
+HTML_TAG("tr", "TableRow");
+HTML_TAG("tt", "");
+HTML_TAG("u", "");
+HTML_TAG("ul", "UList");
+HTML_TAG("var", "");
+HTML_TAG("wbr", "");
+HTML_TAG("xmp", "Pre");
+
+function tagName(aTag) {
+ return "<" + aTag + ">";
+}
+
+for (var tag of allTags) {
+ var node = document.createElement(tag);
+
+ // Have to use the proto's toString(), since HTMLAnchorElement and company
+ // override toString().
+ var nodeString = HTMLElement.prototype.toString.apply(node);
+
+ // Debug builds have extra info, so chop off after "Element" if it's followed
+ // by ' ' or ']'
+ nodeString = nodeString.replace(/Element[\] ].*/, "Element");
+
+ var classInfoString = getClassName(tag);
+ is(nodeString, "[object " + classInfoString,
+ "Unexpected classname for " + tagName(tag));
+ is(node instanceof window[classInfoString], true,
+ tagName(tag) + " not an instance of " + classInfos[tag]);
+
+ if (classInfoString != 'HTMLUnknownElement') {
+ is(node instanceof HTMLUnknownElement, false,
+ tagName(tag) + " is an instance of HTMLUnknownElement");
+ } else {
+ is(node instanceof HTMLUnknownElement, true,
+ tagName(tag) + " is an instance of HTMLUnknownElement");
+ }
+
+ // Check that each node QIs to all the things we expect it to QI to
+ for (var iface of interfaces[tag].concat(interfacesNonClassinfo[tag])) {
+ is(iface in SpecialPowers.Ci, true,
+ iface + " not in Components.interfaces");
+ is(node instanceof SpecialPowers.Ci[iface], true,
+ tagName(tag) + " does not QI to " + iface);
+ }
+}
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug390975.html b/dom/html/test/test_bug390975.html
new file mode 100644
index 000000000..9034d4e32
--- /dev/null
+++ b/dom/html/test/test_bug390975.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=390975
+-->
+<head>
+ <title>Test for Bug 390975</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=390975">Mozilla Bug 390975</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <table id="table1">
+ <form id="form1">
+ <input>
+ <input>
+ <tr><td>
+ <input>
+ <input>
+ <input>
+ </td></tr>
+ </form>
+ </table>
+
+ <table id="table2">
+ <form id="form2">
+ <input>
+ <input>
+ <tr id="row2"><td>
+ <input>
+ <input>
+ <input>
+ </td></tr>
+ </form>
+ </table>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 390975 **/
+var form = $("form1");
+is(form.elements.length, 5, "Unexpected elements length");
+
+$("table1").parentNode.removeChild($("table1"));
+is(form.elements.length, 3, "Should have lost control outside table");
+
+form.parentNode.removeChild(form);
+is(form.elements.length, 0, "Should have lost control outside form");
+
+form = $("form2");
+is(form.elements.length, 5, "Unexpected elements length");
+
+$("row2").parentNode.removeChild($("row2"));
+is(form.elements.length, 2, "Should have lost controls inside table row");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug391777.html b/dom/html/test/test_bug391777.html
new file mode 100644
index 000000000..aa01a45de
--- /dev/null
+++ b/dom/html/test/test_bug391777.html
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=391777
+-->
+<head>
+ <title>Test for Bug 391777</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=391777">Mozilla Bug 391777</a>
+<p id="display"></p>
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 391777 **/
+var arg = {};
+arg.testVal = "foo";
+var result = window.showModalDialog("javascript:window.returnValue = window.dialogArguments.testVal; window.close(); 'This window should close on its own.';", arg);
+ok(true, "We should get here without user interaction");
+is(result, "foo", "Unexpected result from showModalDialog");
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug391994.html b/dom/html/test/test_bug391994.html
new file mode 100644
index 000000000..f26ac560c
--- /dev/null
+++ b/dom/html/test/test_bug391994.html
@@ -0,0 +1,184 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=391994
+-->
+<head>
+ <title>Test for Bug 391994</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=391994">Mozilla Bug 391994</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 391994 **/
+var testNumber = 0;
+
+function assertSelected(aOption, aExpectDefaultSelected, aExpectSelected) {
+ ++testNumber;
+ is(aOption.defaultSelected, aExpectDefaultSelected,
+ "Asserting default-selected state for option " + testNumber);
+ is(aOption.selected, aExpectSelected,
+ "Asserting selected state for option " + testNumber);
+}
+
+function assertSame(aSel1, aSel2Str, aTestNumber) {
+ var div = document.createElement("div");
+ div.innerHTML = aSel2Str;
+ sel2 = div.firstChild;
+ is(aSel1.options.length, sel2.options.length,
+ "Length should be same in select test " + aTestNumber);
+ is(aSel1.selectedIndex, sel2.selectedIndex,
+ "Selected index should be same in select test " + aTestNumber);
+ for (var i = 0; i < aSel1.options.length; ++i) {
+ is(aSel1.options[i].selected, sel2.options[i].selected,
+ "Options[" + i + "].selected should be the same in select test " +
+ aTestNumber);
+ is(aSel1.options[i].defaultSelected, sel2.options[i].defaultSelected,
+ "Options[" + i +
+ "].defaultSelected should be the same in select test " +
+ aTestNumber);
+ }
+}
+
+// Creation methods
+var opt = document.createElement("option");
+assertSelected(opt, false, false);
+
+opt = new Option();
+assertSelected(opt, false, false);
+
+// Setting of defaultSelected
+opt = new Option();
+opt.setAttribute("selected", "selected");
+assertSelected(opt, true, true);
+
+opt = new Option();
+opt.defaultSelected = true;
+assertSelected(opt, true, true);
+is(opt.hasAttribute("selected"), true, "Attribute should be set");
+is(opt.getAttribute("selected"), "",
+ "Attribute should be set to empty string");
+
+// Setting of selected
+opt = new Option();
+opt.selected = false;
+assertSelected(opt, false, false);
+
+opt = new Option();
+opt.selected = true;
+assertSelected(opt, false, true);
+
+// Interaction of selected and defaultSelected
+opt = new Option();
+opt.selected;
+opt.setAttribute("selected", "selected");
+assertSelected(opt, true, true);
+
+opt = new Option();
+opt.selected = false;
+opt.setAttribute("selected", "selected");
+assertSelected(opt, true, false);
+
+opt = new Option();
+opt.setAttribute("selected", "selected");
+opt.selected = true;
+opt.removeAttribute("selected");
+assertSelected(opt, false, true);
+
+// First test of putting things in a <select>: Adding default-selected option
+// should select it.
+var sel = document.createElement("select");
+sel.appendChild(new Option());
+is(sel.selectedIndex, 0, "First option should be selected");
+assertSelected(sel.firstChild, false, true);
+
+sel.appendChild(new Option());
+is(sel.selectedIndex, 0, "First option should still be selected");
+assertSelected(sel.firstChild, false, true);
+assertSelected(sel.firstChild.nextSibling, false, false);
+
+opt = new Option();
+opt.defaultSelected = true;
+sel.appendChild(opt);
+assertSelected(sel.firstChild, false, false);
+assertSelected(sel.firstChild.nextSibling, false, false);
+assertSelected(opt, true, true);
+is(opt, sel.firstChild.nextSibling.nextSibling, "What happened here?");
+is(sel.options[0], sel.firstChild, "Unexpected option 0");
+is(sel.options[1], sel.firstChild.nextSibling, "Unexpected option 1");
+is(sel.options[2], opt, "Unexpected option 2");
+is(sel.selectedIndex, 2, "Unexpected selectedIndex in select test 1");
+
+assertSame(sel, "<select><option><option><option selected></select>", 1);
+
+// Second test of putting things in a <select>: Adding two default-selected
+// options should select the second one.
+sel = document.createElement("select");
+sel.appendChild(new Option());
+sel.appendChild(new Option());
+opt = new Option();
+opt.defaultSelected = true;
+sel.appendChild(opt);
+opt = new Option();
+opt.defaultSelected = true;
+sel.appendChild(opt);
+assertSelected(sel.options[0], false, false);
+assertSelected(sel.options[1], false, false);
+assertSelected(sel.options[2], true, false);
+assertSelected(sel.options[3], true, true);
+is(sel.selectedIndex, 3, "Unexpected selectedIndex in select test 2");
+
+assertSame(sel,
+ "<select><option><option><option selected><option selected></select>", 2);
+
+// Third test of putting things in a <select>: adding a selected option earlier
+// than another selected option should make the new option selected.
+sel = document.createElement("select");
+sel.appendChild(new Option());
+sel.appendChild(new Option());
+opt = new Option();
+opt.defaultSelected = true;
+sel.appendChild(opt);
+opt = new Option();
+opt.defaultSelected = true;
+sel.options[0] = opt;
+assertSelected(sel.options[0], true, true);
+assertSelected(sel.options[1], false, false);
+assertSelected(sel.options[2], true, false);
+is(sel.selectedIndex, 0, "Unexpected selectedIndex in select test 3");
+
+// Fourth test of putting things in a <select>: Just like second test, but with
+// a <select multiple>
+sel = document.createElement("select");
+sel.multiple = true;
+sel.appendChild(new Option());
+sel.appendChild(new Option());
+opt = new Option();
+opt.defaultSelected = true;
+sel.appendChild(opt);
+opt = new Option();
+opt.defaultSelected = true;
+sel.appendChild(opt);
+assertSelected(sel.options[0], false, false);
+assertSelected(sel.options[1], false, false);
+assertSelected(sel.options[2], true, true);
+assertSelected(sel.options[3], true, true);
+is(sel.selectedIndex, 2, "Unexpected selectedIndex in select test 4");
+
+assertSame(sel,
+ "<select multiple><option><option>" +
+ "<option selected><option selected></select>",
+ 4);
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug392567.html b/dom/html/test/test_bug392567.html
new file mode 100644
index 000000000..f58c69e9c
--- /dev/null
+++ b/dom/html/test/test_bug392567.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=392567
+-->
+<head>
+ <title>Test for Bug 392567</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=392567">Mozilla Bug 392567</a>
+<p id="display"><iframe name="testFrame" id="testFrame" style="visibility: hidden;"></iframe></p>
+<div id="content" style="display: none">
+ <form name="testForm" target="testFrame">
+ <input type="text" name="key" />
+ </form>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 392567 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function runTests()
+{
+ if (window.location.search.match(/\?key=value/)) {
+ return;
+ }
+
+ var dataUrl = "http://mochi.test:8888/tests/dom/html/test/bug392567.jar";
+ var jarUrl = "jar:" + dataUrl + "!/index.html";
+ var httpUrl = location.href.replace(/\.html.*/, "_404");
+ var previousDir = location.href.replace(/test\/[^\/]*$/, "");
+ var documentURL = location.href.replace(/\.html.*/, "\.html");
+
+ var form = document.forms.testForm;
+ var frame = frames.testFrame;
+ document.getElementById("testFrame").onload = processTestResult;
+
+ // List of tests to run, each test consists of form action URL and expected result URL
+ var tests = [
+ [jarUrl, jarUrl + "?$PARAMS"],
+ [jarUrl + "?jarTest1=jarTest2", jarUrl + "?$PARAMS"],
+ [jarUrl + "?jarTest3=jarTest4#jarTest5", jarUrl + "?$PARAMS#jarTest5"],
+ ["data:text/html,<html></html>", "data:text/html,<html></html>?$PARAMS"],
+ ["data:text/html,<html>How%20about%20this?</html>", "data:text/html,<html>How%20about%20this?$PARAMS"],
+ [httpUrl, httpUrl + "?$PARAMS"],
+ [httpUrl + "?httpTest1=httpTest2", httpUrl + "?$PARAMS"],
+ [httpUrl + "?httpTest3=httpTest4#httpTest5", httpUrl + "?$PARAMS#httpTest5"],
+ ["", documentURL + "?$PARAMS"],
+ [" ", documentURL + "?$PARAMS"],
+ ["../", previousDir + "?$PARAMS"],
+ ];
+
+ var currentTest = -1;
+
+ runNextTest();
+
+ function runNextTest() {
+ currentTest++;
+ if (currentTest >= tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ form.setAttribute("action", tests[currentTest][0]);
+ form.key.value = "value" + currentTest;
+ form.submit();
+ }
+
+ function processTestResult() {
+ var expected = tests[currentTest][1].replace(/\$PARAMS/, "key=value" + currentTest);
+ is(frame.location.href, expected, "Submitting to " + tests[currentTest][0]);
+
+ setTimeout(runNextTest, 0);
+ }
+}
+
+addLoadEvent(function() {
+ SpecialPowers.pushPrefEnv({"set": [["network.jar.block-remote-files", false]]}, runTests);
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug394700.html b/dom/html/test/test_bug394700.html
new file mode 100644
index 000000000..a2dd92129
--- /dev/null
+++ b/dom/html/test/test_bug394700.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=394700
+-->
+<head>
+ <title>Test for Bug 394700</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=394700">Mozilla Bug 394700</a>
+<p id="display"></p>
+<div id="content">
+ <select><option id="A">A</option><option id="B">B</option></select>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 394700 **/
+
+function remove(q1) { q1.parentNode.removeChild(q1); }
+
+function testSelectedIndex()
+{
+ document.addEventListener("DOMNodeRemoved", foo, false);
+ remove(document.getElementById("B"));
+ document.removeEventListener("DOMNodeRemoved", foo, false);
+
+ function foo()
+ {
+ document.removeEventListener("DOMNodeRemoved", foo, false);
+ remove(document.getElementById("A"));
+ }
+ var selectElement = document.getElementsByTagName("select")[0];
+ ok(selectElement.selectedIndex == -1, "Wrong selected index!");
+ ok(selectElement.length == 0, "Select shouldn't have any options!")
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(testSelectedIndex);
+addLoadEvent(SimpleTest.finish);
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug395107.html b/dom/html/test/test_bug395107.html
new file mode 100644
index 000000000..22e5e110d
--- /dev/null
+++ b/dom/html/test/test_bug395107.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=395107
+-->
+<head>
+ <title>Test for Bug 395107</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=395107">Mozilla Bug 395107</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 395107 **/
+var testNumber = 0;
+
+function assertSelected(aOption, aExpectDefaultSelected, aExpectSelected) {
+ ++testNumber;
+ is(aOption.defaultSelected, aExpectDefaultSelected,
+ "Asserting default-selected state for option " + testNumber);
+ is(aOption.selected, aExpectSelected,
+ "Asserting selected state for option " + testNumber);
+}
+
+function assertSame(aSel1, aSel2Str, aTestNumber) {
+ var div = document.createElement("div");
+ div.innerHTML = aSel2Str;
+ sel2 = div.firstChild;
+ is(aSel1.options.length, sel2.options.length,
+ "Length should be same in select test " + aTestNumber);
+ is(aSel1.selectedIndex, sel2.selectedIndex,
+ "Selected index should be same in select test " + aTestNumber);
+ for (var i = 0; i < aSel1.options.length; ++i) {
+ is(aSel1.options[i].selected, sel2.options[i].selected,
+ "Options[" + i + "].selected should be the same in select test " +
+ aTestNumber);
+ is(aSel1.options[i].defaultSelected, sel2.options[i].defaultSelected,
+ "Options[" + i +
+ "].defaultSelected should be the same in select test " +
+ aTestNumber);
+ }
+}
+
+// In a single-select, setting an option selected should deselect an
+// existing selected option.
+var sel = document.createElement("select");
+sel.appendChild(new Option());
+is(sel.selectedIndex, 0, "First option should be selected");
+assertSelected(sel.firstChild, false, true);
+sel.appendChild(new Option());
+is(sel.selectedIndex, 0, "First option should still be selected");
+assertSelected(sel.firstChild, false, true);
+assertSelected(sel.firstChild.nextSibling, false, false);
+
+opt = new Option();
+sel.appendChild(opt);
+opt.defaultSelected = true;
+assertSelected(sel.firstChild, false, false);
+assertSelected(sel.firstChild.nextSibling, false, false);
+assertSelected(opt, true, true);
+is(opt, sel.firstChild.nextSibling.nextSibling, "What happened here?");
+is(sel.options[0], sel.firstChild, "Unexpected option 0");
+is(sel.options[1], sel.firstChild.nextSibling, "Unexpected option 1");
+is(sel.options[2], opt, "Unexpected option 2");
+is(sel.selectedIndex, 2, "Unexpected selectedIndex in select test 1");
+
+assertSame(sel, "<select><option><option><option selected></select>", 1);
+
+// Same, but with the option that gets set selected earlier in the select
+sel = document.createElement("select");
+sel.appendChild(new Option());
+sel.appendChild(new Option());
+opt = new Option();
+opt.defaultSelected = true;
+sel.appendChild(opt);
+opt = new Option();
+sel.options[0] = opt;
+opt.defaultSelected = true;
+assertSelected(sel.options[0], true, true);
+assertSelected(sel.options[1], false, false);
+assertSelected(sel.options[2], true, false);
+is(sel.selectedIndex, 0, "Unexpected selectedIndex in select test 2");
+
+// And now try unselecting options
+sel = document.createElement("select");
+sel.appendChild(new Option());
+opt = new Option();
+opt.defaultSelected = true;
+sel.appendChild(opt);
+sel.appendChild(new Option());
+opt.defaultSelected = false;
+
+assertSelected(sel.options[0], false, true);
+assertSelected(sel.options[1], false, false);
+assertSelected(sel.options[2], false, false);
+is(sel.selectedIndex, 0, "Unexpected selectedIndex in select test 2");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug401160.xhtml b/dom/html/test/test_bug401160.xhtml
new file mode 100644
index 000000000..b99341fe3
--- /dev/null
+++ b/dom/html/test/test_bug401160.xhtml
@@ -0,0 +1,27 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=401160
+-->
+<head>
+ <title>Test for Bug 401160</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=401160">Mozilla Bug 401160</a>
+<label id="label" contenteditable="true"><legend></legend><div></div></label>
+
+<pre id="test">
+<script type="text/javascript">
+
+function do_test() {
+ document.getElementById('label').focus();
+ ok(true, "This is crash test - the test succeeded if we reach this line")
+}
+
+do_test();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug402680.html b/dom/html/test/test_bug402680.html
new file mode 100644
index 000000000..191d2173d
--- /dev/null
+++ b/dom/html/test/test_bug402680.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=402680
+-->
+<head>
+ <title>Test for Bug 402680</title>
+ <script>
+ var activeElementIsNull = (document.activeElement == null);
+ </script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=402680">Mozilla Bug 402680</a>
+<p id="display"></p>
+<div id="content">
+ <input type="text">
+ <textarea></textarea>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 402680 **/
+
+ok(activeElementIsNull,
+ "Before document has body, active element should be null");
+
+function testActiveElement() {
+ ok(document.body == document.activeElement,
+ "After page load body element should be the active element!");
+ var input = document.getElementsByTagName("input")[0];
+ input.focus();
+ ok(document.activeElement == input,
+ "Input element isn't the active element!");
+ var textarea = document.getElementsByTagName("textarea")[0];
+ textarea.focus();
+ ok(document.activeElement == textarea,
+ "Textarea element isn't the active element!");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(testActiveElement);
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug403868.html b/dom/html/test/test_bug403868.html
new file mode 100644
index 000000000..efcb5bdca
--- /dev/null
+++ b/dom/html/test/test_bug403868.html
@@ -0,0 +1,87 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=403868
+-->
+<head>
+ <title>Test for Bug 403868</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=403868">Mozilla Bug 403868</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 403868 **/
+function createSpan(id, insertionPoint) {
+ var s = document.createElement("span");
+ s.id = id;
+ $("content").insertBefore(s, insertionPoint);
+ return s;
+}
+
+var s1a = createSpan("test1", null);
+is(document.getElementById("test1"), s1a,
+ "Only one span with id=test1 in the tree; should work!");
+
+var s2a = createSpan("test1", null);
+is(document.getElementById("test1"), s1a,
+ "Appending span with id=test1 doesn't change which one comes first");
+
+var s3a = createSpan("test1", s2a);
+is(document.getElementById("test1"), s1a,
+ "Inserting span with id=test1 not at the beginning; doesn't matter");
+
+var s4a = createSpan("test1", s1a);
+is(document.getElementById("test1"), s4a,
+ "Inserting span with id=test1 at the beginning changes which one is first");
+
+s4a.parentNode.removeChild(s4a);
+is(document.getElementById("test1"), s1a,
+ "First-created span with id=test1 is first again");
+
+s1a.parentNode.removeChild(s1a);
+is(document.getElementById("test1"), s3a,
+ "Third-created span with id=test1 is first now");
+
+// Start the id hashtable
+for (var i = 0; i < 256; ++i) {
+ document.getElementById("no-such-id-in-the-document" + i);
+}
+
+var s1b = createSpan("test2", null);
+is(document.getElementById("test2"), s1b,
+ "Only one span with id=test2 in the tree; should work!");
+
+var s2b = createSpan("test2", null);
+is(document.getElementById("test2"), s1b,
+ "Appending span with id=test2 doesn't change which one comes first");
+
+var s3b = createSpan("test2", s2b);
+is(document.getElementById("test2"), s1b,
+ "Inserting span with id=test2 not at the beginning; doesn't matter");
+
+var s4b = createSpan("test2", s1b);
+is(document.getElementById("test2"), s4b,
+ "Inserting span with id=test2 at the beginning changes which one is first");
+
+s4b.parentNode.removeChild(s4b);
+is(document.getElementById("test2"), s1b,
+ "First-created span with id=test2 is first again");
+
+s1b.parentNode.removeChild(s1b);
+is(document.getElementById("test2"), s3b,
+ "Third-created span with id=test2 is first now");
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug403868.xhtml b/dom/html/test/test_bug403868.xhtml
new file mode 100644
index 000000000..62fce0669
--- /dev/null
+++ b/dom/html/test/test_bug403868.xhtml
@@ -0,0 +1,86 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=403868
+-->
+<head>
+ <title>Test for Bug 403868</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=403868">Mozilla Bug 403868</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+
+/** Test for Bug 403868 **/
+function createSpan(id, insertionPoint) {
+ var s = document.createElementNS("http://www.w3.org/1999/xhtml", "span");
+ s.id = id;
+ $("content").insertBefore(s, insertionPoint);
+ return s;
+}
+
+var s1a = createSpan("test1", null);
+is(document.getElementById("test1"), s1a,
+ "Only one span with id=test1 in the tree; should work!");
+
+var s2a = createSpan("test1", null);
+is(document.getElementById("test1"), s1a,
+ "Appending span with id=test1 doesn't change which one comes first");
+
+var s3a = createSpan("test1", s2a);
+is(document.getElementById("test1"), s1a,
+ "Inserting span with id=test1 not at the beginning; doesn't matter");
+
+var s4a = createSpan("test1", s1a);
+is(document.getElementById("test1"), s4a,
+ "Inserting span with id=test1 at the beginning changes which one is first");
+
+s4a.parentNode.removeChild(s4a);
+is(document.getElementById("test1"), s1a,
+ "First-created span with id=test1 is first again");
+
+s1a.parentNode.removeChild(s1a);
+is(document.getElementById("test1"), s3a,
+ "Third-created span with id=test1 is first now");
+
+// Start the id hashtable
+for (var i = 0; i < 256; ++i) {
+ document.getElementById("no-such-id-in-the-document" + i);
+}
+
+var s1b = createSpan("test2", null);
+is(document.getElementById("test2"), s1b,
+ "Only one span with id=test2 in the tree; should work!");
+
+var s2b = createSpan("test2", null);
+is(document.getElementById("test2"), s1b,
+ "Appending span with id=test2 doesn't change which one comes first");
+
+var s3b = createSpan("test2", s2b);
+is(document.getElementById("test2"), s1b,
+ "Inserting span with id=test2 not at the beginning; doesn't matter");
+
+var s4b = createSpan("test2", s1b);
+is(document.getElementById("test2"), s4b,
+ "Inserting span with id=test2 at the beginning changes which one is first");
+
+s4b.parentNode.removeChild(s4b);
+is(document.getElementById("test2"), s1b,
+ "First-created span with id=test2 is first again");
+
+s1b.parentNode.removeChild(s1b);
+is(document.getElementById("test2"), s3b,
+ "Third-created span with id=test2 is first now");
+
+]]>
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug405242.html b/dom/html/test/test_bug405242.html
new file mode 100644
index 000000000..9ca3c1156
--- /dev/null
+++ b/dom/html/test/test_bug405242.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=405242
+-->
+<head>
+ <title>Test for Bug 405252</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=405242">Mozilla Bug 405242</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+/** Test for Bug 405242 **/
+var sel = document.createElement("select");
+sel.appendChild(new Option());
+sel.appendChild(new Option());
+sel.appendChild(new Option());
+opt = new Option();
+opt.value = 10;
+sel.appendChild(opt);
+sel.options.remove(0);
+sel.options.remove(1000);
+sel.options.remove(-1);
+is(sel.length, 1, "Unexpected option collection length");
+is(sel[0].value, "10", "Unexpected remained option");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug406596.html b/dom/html/test/test_bug406596.html
new file mode 100644
index 000000000..adc638052
--- /dev/null
+++ b/dom/html/test/test_bug406596.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=406596
+-->
+<head>
+ <title>Test for Bug 406596</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=406596">Mozilla Bug 406596</a>
+<div id="content">
+ <div id="edit" contenteditable="true">This text is editable, you can change its content <a href="#" id="a" tabindex="0">ABCDEFGHIJKLMNOPQRSTUV</a> <input type="submit" value="abcd" id="b"></input> <img src="foo.png" id="c"></div>
+ <div tabindex="0">This text is not editable but is focusable</div>
+ <div tabindex="0">This text is not editable but is focusable</div>
+ <a href="#" id="d" contenteditable="true">ABCDEFGHIJKLMNOPQRSTUV</a>
+ <div tabindex="0">This text is not editable but is focusable</div>
+ <div tabindex="0">This text is not editable but is focusable</div>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 406596 **/
+
+function testTabbing(click, focus, selectionOffset) {
+ var wu = SpecialPowers.getDOMWindowUtils(window);
+
+ var elem = document.getElementById(click);
+ var rect = elem.getBoundingClientRect();
+ var selection = window.getSelection();
+
+ var x = (rect.left + rect.right) / 4;
+ var y = (rect.top + rect.bottom) / 2;
+ wu.sendMouseEvent("mousedown", x, y, 0, 1, 0);
+ wu.sendMouseEvent("mousemove", x + selectionOffset, y, 0, 1, 0);
+ wu.sendMouseEvent("mouseup", x + selectionOffset, y, 0, 1, 0);
+ if (selectionOffset) {
+ is(selection.rangeCount, 1, "there should be one range in the selection");
+ var range = selection.getRangeAt(0);
+ }
+ var focusedElement = document.activeElement;
+ is(focusedElement, document.getElementById(focus),
+ "clicking should move focus to the contentEditable node");
+ synthesizeKey("VK_TAB", {});
+ synthesizeKey("VK_TAB", {});
+ synthesizeKey("VK_TAB", { shiftKey: true });
+ synthesizeKey("VK_TAB", { shiftKey: true });
+ is(document.activeElement, focusedElement,
+ "tab/shift-tab should move focus back to the contentEditable node");
+ if (selectionOffset) {
+ is(selection.rangeCount, 1,
+ "there should still be one range in the selection");
+ var newRange = selection.getRangeAt(0);
+ is(newRange.compareBoundaryPoints(Range.START_TO_START, range), 0,
+ "the selection should be the same as before the tabbing");
+ is(newRange.compareBoundaryPoints(Range.END_TO_END, range), 0,
+ "the selection should be the same as before the tabbing");
+ }
+}
+
+function test() {
+ window.getSelection().removeAllRanges();
+ testTabbing("edit", "edit", 0);
+ testTabbing("a", "edit", 0);
+ testTabbing("d", "d", 0);
+ testTabbing("edit", "edit", 10);
+ testTabbing("a", "edit", 10);
+ testTabbing("d", "d", 10);
+
+ SimpleTest.finish();
+}
+
+window.onload = function() {
+ SimpleTest.waitForExplicitFinish();
+ setTimeout(test, 0);
+};
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug417760.html b/dom/html/test/test_bug417760.html
new file mode 100644
index 000000000..7a16914a0
--- /dev/null
+++ b/dom/html/test/test_bug417760.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=417760
+-->
+<head>
+ <title>cannot focus() img with tabindex="-1"</title>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <style type="text/css">
+ img {
+ border: 5px solid white;
+ }
+ img:focus {
+ border: 5px solid black;
+ }
+ </style>
+
+
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+
+ <script type="text/javascript">
+ function checkFocus(aExpected, aTabIndex)
+ {
+ elemCurr = document.activeElement.getAttribute("id");
+ is(elemCurr, aExpected, "Element with tabIndex " + aTabIndex
+ + " did not receive focus!");
+ }
+
+ function doTest()
+ {
+ // First, test img with tabindex = 0
+ document.getElementById("img-tabindex-0").focus();
+ checkFocus("img-tabindex-0", 0);
+
+ // now test the img with tabindex = -1
+ document.getElementById("img-tabindex-minus-1").focus();
+ checkFocus("img-tabindex-minus-1", -1);
+
+ // now test the img without tabindex, should NOT receive focus!
+ document.getElementById("img-no-tabindex").focus();
+ checkFocus("img-tabindex-minus-1", null);
+
+ SimpleTest.finish();
+ }
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(doTest);
+ </script>
+</head>
+
+<body>
+
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=417760">Mozilla Bug 417760</a>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test">
+ </pre>
+ <br>img tabindex="0":
+ <img id="img-tabindex-0"
+ src="file_bug417760.png"
+ alt="MoCo logo" tabindex="0"/>
+ <br>img tabindex="-1":
+ <img id="img-tabindex-minus-1"
+ src="file_bug417760.png"
+ alt="MoCo logo" tabindex="-1"/>
+ <br>img without tabindex:
+ <img id="img-no-tabindex"
+ src="file_bug417760.png"
+ alt="MoCo logo"/>
+</body>
+</html>
diff --git a/dom/html/test/test_bug421640.html b/dom/html/test/test_bug421640.html
new file mode 100644
index 000000000..59bac6a92
--- /dev/null
+++ b/dom/html/test/test_bug421640.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=421640
+-->
+<head>
+ <title>Test for Bug 421640</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=421640">Mozilla Bug 421640</a>
+<div id="content">
+ <div id="edit" contenteditable="true">This text is editable</div>
+ <div><button id="button">Test</button></div>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 421640 **/
+
+function test(click, focus, nextFocus) {
+ var wu = SpecialPowers.getDOMWindowUtils(window);
+
+ var selection = window.getSelection();
+ var edit = document.getElementById("edit");
+ var text = edit.firstChild;
+
+ selection.removeAllRanges();
+
+ var rect = edit.getBoundingClientRect();
+ wu.sendMouseEvent("mousedown", rect.left + 1, rect.top + 1, 0, 1, 0);
+ wu.sendMouseEvent("mousemove", rect.right - 1, rect.top + 1, 0, 1, 0);
+ wu.sendMouseEvent("mouseup", rect.right - 1, rect.top + 1, 0, 1, 0);
+
+ is(selection.anchorNode, text, "");
+
+ rect = document.getElementById("button").getBoundingClientRect();
+ wu.sendMouseEvent("mousedown", rect.left + 10, rect.top + 1, 0, 1, 0);
+ wu.sendMouseEvent("mouseup", rect.left + 10, rect.top + 1, 0, 1, 0);
+
+ is(selection.anchorNode, text, "");
+
+ SimpleTest.finish();
+}
+
+window.onload = function() {
+ SimpleTest.waitForExplicitFinish();
+ setTimeout(test, 0);
+};
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug424698.html b/dom/html/test/test_bug424698.html
new file mode 100644
index 000000000..9bd6ea5ff
--- /dev/null
+++ b/dom/html/test/test_bug424698.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=424698
+-->
+<head>
+ <title>Test for Bug 424698</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=424698">Mozilla Bug 424698</a>
+<p id="display">
+<input id="i1">
+<input id="target">
+<textarea id="i2"></textarea>
+<textarea id="target2"></textarea>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 424698 **/
+var i = $("i1");
+is(i.value, "", "Value should be empty string");
+i.defaultValue = "test";
+is(i.value, "test", "Setting defaultValue should work");
+i.defaultValue = "test2";
+is(i.value, "test2", "Setting defaultValue multiple times should work");
+
+// Now let's hide and reshow things
+i.style.display = "none";
+is(i.offsetWidth, 0, "Input didn't hide?");
+i.style.display = "";
+isnot(i.offsetWidth, 0, "Input didn't show?");
+is(i.value, "test2", "Hiding/showing should not affect value");
+i.defaultValue = "test3";
+is(i.value, "test3", "Setting defaultValue after hide/show should work");
+
+// Make sure typing works ok
+i = $("target");
+i.focus(); // Otherwise editor gets confused when we send the key events
+is(i.value, "", "Value should be empty string in second control");
+sendString("2test2");
+is(i.value, "2test2", 'We just typed the string "2test2"');
+i.defaultValue = "2test3";
+is(i.value, "2test2", "Setting defaultValue after typing should not work");
+i.style.display = "none";
+is(i.offsetWidth, 0, "Second input didn't hide?");
+i.style.display = "";
+isnot(i.offsetWidth, 0, "Second input didn't show?");
+is(i.value, "2test2", "Hiding/showing second input should not affect value");
+i.defaultValue = "2test4";
+is(i.value, "2test2", "Setting defaultValue after hide/show should not work if we typed");
+
+i = $("i2");
+is(i.value, "", "Textarea value should be empty string");
+i.defaultValue = "test";
+is(i.value, "test", "Setting textarea defaultValue should work");
+i.defaultValue = "test2";
+is(i.value, "test2", "Setting textarea defaultValue multiple times should work");
+
+// Now let's hide and reshow things
+i.style.display = "none";
+is(i.offsetWidth, 0, "Textarea didn't hide?");
+i.style.display = "";
+isnot(i.offsetWidth, 0, "Textarea didn't show?");
+is(i.value, "test2", "Hiding/showing textarea should not affect value");
+i.defaultValue = "test3";
+is(i.value, "test3", "Setting textarea defaultValue after hide/show should work");
+
+// Make sure typing works ok
+i = $("target2");
+i.focus(); // Otherwise editor gets confused when we send the key events
+is(i.value, "", "Textarea value should be empty string in second control");
+sendString("2test2");
+is(i.value, "2test2", 'We just typed the string "2test2"');
+i.defaultValue = "2test3";
+is(i.value, "2test2", "Setting textarea defaultValue after typing should not work");
+i.style.display = "none";
+is(i.offsetWidth, 0, "Second textarea didn't hide?");
+i.style.display = "";
+isnot(i.offsetWidth, 0, "Second textarea didn't show?");
+is(i.value, "2test2", "Hiding/showing second textarea should not affect value");
+i.defaultValue = "2test4";
+is(i.value, "2test2", "Setting textarea defaultValue after hide/show should not work if we typed");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug428135.xhtml b/dom/html/test/test_bug428135.xhtml
new file mode 100644
index 000000000..27ff7aeef
--- /dev/null
+++ b/dom/html/test/test_bug428135.xhtml
@@ -0,0 +1,156 @@
+<?xml version="1.0"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=428135
+-->
+<head>
+ <title>Test for Bug 428135</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=428135">Mozilla Bug 428135</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+<![CDATA[
+
+/** Test for Bug 428135 **/
+
+var expectedCurrentTargets = new Array();
+
+function d(el, ename) {
+ var e = document.createEvent("Events");
+ e.initEvent(ename, true, true);
+ el.dispatchEvent(e);
+}
+
+function testListener(e) {
+ e.preventDefault();
+ var expected = expectedCurrentTargets.shift();
+ ok(expected == e.currentTarget,
+ "Unexpected current target [" + e.currentTarget + "], event=" + e.type +
+ ", phase=" + e.eventPhase + ", target should have been " + expected);
+}
+
+function getAndAddListeners(elname) {
+ var el = document;
+ if (elname) {
+ el = document.getElementById(elname);
+ }
+ el.addEventListener("submit", testListener, true);
+ el.addEventListener("submit", testListener, false);
+ el.addEventListener("reset", testListener, true);
+ el.addEventListener("reset", testListener, false);
+ el.addEventListener("fooEvent", testListener, true);
+ el.addEventListener("fooEvent", testListener, false);
+ return el;
+}
+
+function testSubmitResetEvents() {
+ getAndAddListeners(null);
+ var outerForm = getAndAddListeners("outerForm");
+ var outerSubmit = getAndAddListeners("outerSubmit");
+ var outerReset = getAndAddListeners("outerReset");
+ var outerSubmitDispatcher = getAndAddListeners("outerSubmitDispatcher");
+ var outerResetDispatcher = getAndAddListeners("outerResetDispatcher");
+ var outerChild = getAndAddListeners("outerChild");
+ var innerForm = getAndAddListeners("innerForm");
+ var innerSubmit = getAndAddListeners("innerSubmit");
+ var innerReset = getAndAddListeners("innerReset");
+ var innerSubmitDispatcher = getAndAddListeners("innerSubmitDispatcher");
+ var innerResetDispatcher = getAndAddListeners("innerResetDispatcher");
+
+ expectedCurrentTargets = new Array(document, outerForm, outerForm, document);
+ outerSubmit.click();
+ ok(expectedCurrentTargets.length == 0,
+ "(1) expectedCurrentTargets isn't empty!");
+
+ expectedCurrentTargets = new Array(document, outerForm, outerForm, document);
+ outerReset.click();
+ ok(expectedCurrentTargets.length == 0,
+ "(2) expectedCurrentTargets isn't empty!");
+
+ // Because of bug 428135, submit shouldn't propagate
+ // back to outerForm and document!
+ expectedCurrentTargets =
+ new Array(document, outerForm, outerSubmitDispatcher, outerSubmitDispatcher);
+ outerSubmitDispatcher.click();
+ ok(expectedCurrentTargets.length == 0,
+ "(3) expectedCurrentTargets isn't empty!");
+
+ // Because of bug 428135, reset shouldn't propagate
+ // back to outerForm and document!
+ expectedCurrentTargets =
+ new Array(document, outerForm, outerResetDispatcher, outerResetDispatcher);
+ outerResetDispatcher.click();
+ ok(expectedCurrentTargets.length == 0,
+ "(4) expectedCurrentTargets isn't empty!");
+
+ // Because of bug 428135, submit shouldn't propagate
+ // back to outerForm and document!
+ expectedCurrentTargets =
+ new Array(document, outerForm, outerChild, innerForm, innerForm, outerChild);
+ innerSubmit.click();
+ ok(expectedCurrentTargets.length == 0,
+ "(5) expectedCurrentTargets isn't empty!");
+
+ // Because of bug 428135, reset shouldn't propagate
+ // back to outerForm and document!
+ expectedCurrentTargets =
+ new Array(document, outerForm, outerChild, innerForm, innerForm, outerChild);
+ innerReset.click();
+ ok(expectedCurrentTargets.length == 0,
+ "(6) expectedCurrentTargets isn't empty!");
+
+ // Because of bug 428135, submit shouldn't propagate
+ // back to inner/outerForm or document!
+ expectedCurrentTargets =
+ new Array(document, outerForm, outerChild, innerForm, innerSubmitDispatcher,
+ innerSubmitDispatcher);
+ innerSubmitDispatcher.click();
+ ok(expectedCurrentTargets.length == 0,
+ "(7) expectedCurrentTargets isn't empty!");
+
+ // Because of bug 428135, reset shouldn't propagate
+ // back to inner/outerForm or document!
+ expectedCurrentTargets =
+ new Array(document, outerForm, outerChild, innerForm, innerResetDispatcher,
+ innerResetDispatcher);
+ innerResetDispatcher.click();
+ ok(expectedCurrentTargets.length == 0,
+ "(8) expectedCurrentTargets isn't empty!");
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(testSubmitResetEvents);
+addLoadEvent(SimpleTest.finish);
+
+
+]]>
+</script>
+</pre>
+<form id="outerForm">
+ <input type="submit" value="outer" id="outerSubmit"/>
+ <input type="reset" value="reset outer" id="outerReset"/>
+ <input type="button" value="dispatch submit" onclick="d(this, 'submit')"
+ id="outerSubmitDispatcher"/>
+ <input type="button" value="dispatch reset" onclick="d(this, 'reset')"
+ id="outerResetDispatcher"/>
+ <div id="outerChild">
+ <form id="innerForm">
+ <input type="submit" value="inner" id="innerSubmit"/>
+ <input type="reset" value="reset inner" id="innerReset"/>
+ <input type="button" value="dispatch submit" onclick="d(this, 'submit')"
+ id="innerSubmitDispatcher"/>
+ <input type="button" value="dispatch reset" onclick="d(this, 'reset')"
+ id="innerResetDispatcher"/>
+ </form>
+ </div>
+</form>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug430351.html b/dom/html/test/test_bug430351.html
new file mode 100644
index 000000000..585620e7d
--- /dev/null
+++ b/dom/html/test/test_bug430351.html
@@ -0,0 +1,523 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=430351
+-->
+<head>
+ <title>Test for Bug 430351</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=430351">Mozilla Bug 430351</a>
+<p id="display"></p>
+<div id="content">
+ <div id="parent"></div>
+ <div id="editableParent" contenteditable="true"></div>
+ <iframe id="frame"></iframe>
+ <map name="map"><area></map>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 430351 **/
+
+var focusableElements = [
+ "<a tabindex=\"-1\"></a>",
+ "<a tabindex=\"0\"></a>",
+ "<a tabindex=\"0\" disabled></a>",
+ "<a tabindex=\"1\"></a>",
+ "<a contenteditable=\"true\"></a>",
+
+ "<a href=\"#\"></a>",
+ "<a href=\"#\" tabindex=\"-1\"></a>",
+ "<a href=\"#\" tabindex=\"0\"></a>",
+ "<a href=\"#\" tabindex=\"0\" disabled></a>",
+ "<a href=\"#\" tabindex=\"1\"></a>",
+ "<a href=\"#\" contenteditable=\"true\"></a>",
+ "<a href=\"#\" disabled></a>",
+
+ "<button></button>",
+ "<button tabindex=\"-1\"></button>",
+ "<button tabindex=\"0\"></button>",
+ "<button tabindex=\"1\"></button>",
+ "<button contenteditable=\"true\"></button>",
+
+ "<button type=\"reset\"></button>",
+ "<button type=\"reset\" tabindex=\"-1\"></button>",
+ "<button type=\"reset\" tabindex=\"0\"></button>",
+ "<button type=\"reset\" tabindex=\"1\"></button>",
+ "<button type=\"reset\" contenteditable=\"true\"></button>",
+
+ "<button type=\"submit\"></button>",
+ "<button type=\"submit\" tabindex=\"-1\"></button>",
+ "<button type=\"submit\" tabindex=\"0\"></button>",
+ "<button type=\"submit\" tabindex=\"1\"></button>",
+ "<button type=\"submit\" contenteditable=\"true\"></button>",
+
+ "<div tabindex=\"-1\"></div>",
+ "<div tabindex=\"0\"></div>",
+ "<div tabindex=\"1\"></div>",
+ "<div contenteditable=\"true\"></div>",
+ "<div tabindex=\"0\" disabled></div>",
+
+ "<embed>",
+ "<embed tabindex=\"-1\">",
+ "<embed tabindex=\"0\">",
+ "<embed tabindex=\"0\" disabled>",
+ "<embed tabindex=\"1\">",
+ "<embed disabled>",
+ "<embed contenteditable=\"true\">",
+
+ "<iframe contenteditable=\"true\"></iframe>",
+
+ "<iframe src=\"about:blank\"></iframe>",
+ "<iframe src=\"about:blank\" disabled></iframe>",
+ "<iframe src=\"about:blank\" tabindex=\"-1\"></iframe>",
+ "<iframe src=\"about:blank\" tabindex=\"0\"></iframe>",
+ "<iframe src=\"about:blank\" tabindex=\"0\" disabled></iframe>",
+ "<iframe src=\"about:blank\" tabindex=\"1\"></iframe>",
+ "<iframe src=\"about:blank\" contenteditable=\"true\"></iframe>",
+
+ "<iframe></iframe>",
+ "<iframe tabindex=\"-1\"></iframe>",
+ "<iframe tabindex=\"0\"></iframe>",
+ "<iframe tabindex=\"0\" disabled></iframe>",
+ "<iframe tabindex=\"1\"></iframe>",
+ "<iframe disabled></iframe>",
+
+ "<img tabindex=\"-1\">",
+ "<img tabindex=\"0\">",
+ "<img tabindex=\"0\" disabled>",
+ "<img tabindex=\"1\">",
+
+ "<input>",
+ "<input tabindex=\"-1\">",
+ "<input tabindex=\"0\">",
+ "<input tabindex=\"1\">",
+ "<input contenteditable=\"true\">",
+
+ "<input type=\"button\">",
+ "<input type=\"button\" tabindex=\"-1\">",
+ "<input type=\"button\" tabindex=\"0\">",
+ "<input type=\"button\" tabindex=\"1\">",
+ "<input type=\"button\" contenteditable=\"true\">",
+
+ "<input type=\"checkbox\">",
+ "<input type=\"checkbox\" tabindex=\"-1\">",
+ "<input type=\"checkbox\" tabindex=\"0\">",
+ "<input type=\"checkbox\" tabindex=\"1\">",
+ "<input type=\"checkbox\" contenteditable=\"true\">",
+
+ "<input type=\"image\">",
+ "<input type=\"image\" tabindex=\"-1\">",
+ "<input type=\"image\" tabindex=\"0\">",
+ "<input type=\"image\" tabindex=\"1\">",
+ "<input type=\"image\" contenteditable=\"true\">",
+
+ "<input type=\"password\">",
+ "<input type=\"password\" tabindex=\"-1\">",
+ "<input type=\"password\" tabindex=\"0\">",
+ "<input type=\"password\" tabindex=\"1\">",
+ "<input type=\"password\" contenteditable=\"true\">",
+
+ "<input type=\"radio\">",
+ "<input type=\"radio\" tabindex=\"-1\">",
+ "<input type=\"radio\" tabindex=\"0\">",
+ "<input type=\"radio\" tabindex=\"1\">",
+ "<input type=\"radio\" contenteditable=\"true\">",
+ "<input type=\"radio\" checked>",
+ "<form><input type=\"radio\" name=\"foo\"></form>",
+
+ "<input type=\"reset\">",
+ "<input type=\"reset\" tabindex=\"-1\">",
+ "<input type=\"reset\" tabindex=\"0\">",
+ "<input type=\"reset\" tabindex=\"1\">",
+ "<input type=\"reset\" contenteditable=\"true\">",
+
+ "<input type=\"submit\">",
+ "<input type=\"submit\" tabindex=\"-1\">",
+ "<input type=\"submit\" tabindex=\"0\">",
+ "<input type=\"submit\" tabindex=\"1\">",
+ "<input type=\"submit\" contenteditable=\"true\">",
+
+ "<input type=\"text\">",
+ "<input type=\"text\" tabindex=\"-1\">",
+ "<input type=\"text\" tabindex=\"0\">",
+ "<input type=\"text\" tabindex=\"1\">",
+ "<input type=\"text\" contenteditable=\"true\">",
+
+ "<input type=\"number\">",
+ "<input type=\"number\" tabindex=\"-1\">",
+ "<input type=\"number\" tabindex=\"0\">",
+ "<input type=\"number\" tabindex=\"1\">",
+ "<input type=\"number\" contenteditable=\"true\">",
+
+ "<object tabindex=\"-1\"></object>",
+ "<object tabindex=\"0\"></object>",
+ "<object tabindex=\"1\"></object>",
+ "<object contenteditable=\"true\"></object>",
+
+ "<object classid=\"java:a\"></object>",
+ "<object classid=\"java:a\" tabindex=\"-1\"></object>",
+ "<object classid=\"java:a\" tabindex=\"0\"></object>",
+ "<object classid=\"java:a\" tabindex=\"0\" disabled></object>",
+ "<object classid=\"java:a\" tabindex=\"1\"></object>",
+ "<object classid=\"java:a\" disabled></object>",
+ "<object classid=\"java:a\" contenteditable=\"true\"></object>",
+
+ "<select></select>",
+ "<select tabindex=\"-1\"></select>",
+ "<select tabindex=\"0\"></select>",
+ "<select tabindex=\"1\"></select>",
+ "<select contenteditable=\"true\"></select>",
+
+ "<option tabindex='-1'></option>",
+ "<option tabindex='0'></option>",
+ "<option tabindex='1'></option>",
+ "<option contenteditable></option>",
+
+ "<optgroup tabindex='-1'></optgroup>",
+ "<optgroup tabindex='0'></optgroup>",
+ "<optgroup tabindex='1'></optgroup>",
+ "<optgroup contenteditable></optgroup>"
+];
+
+var nonFocusableElements = [
+ "<a></a>",
+ "<a disabled></a>",
+
+ "<button tabindex=\"0\" disabled></button>",
+ "<button disabled></button>",
+
+ "<button type=\"reset\" tabindex=\"0\" disabled></button>",
+ "<button type=\"reset\" disabled></button>",
+
+ "<button type=\"submit\" tabindex=\"0\" disabled></button>",
+ "<button type=\"submit\" disabled></button>",
+
+ "<div></div>",
+ "<div disabled></div>",
+
+ "<img>",
+ "<img disabled>",
+ "<img contenteditable=\"true\">",
+
+ "<img usemap=\"#map\">",
+ "<img usemap=\"#map\" tabindex=\"-1\">",
+ "<img usemap=\"#map\" tabindex=\"0\">",
+ "<img usemap=\"#map\" tabindex=\"0\" disabled>",
+ "<img usemap=\"#map\" tabindex=\"1\">",
+ "<img usemap=\"#map\" disabled>",
+ "<img usemap=\"#map\" contenteditable=\"true\">",
+
+ "<input tabindex=\"0\" disabled>",
+ "<input disabled>",
+
+ "<input type=\"button\" tabindex=\"0\" disabled>",
+ "<input type=\"button\" disabled>",
+
+ "<input type=\"checkbox\" tabindex=\"0\" disabled>",
+ "<input type=\"checkbox\" disabled>",
+
+ "<input type=\"file\" tabindex=\"0\" disabled>",
+ "<input type=\"file\" disabled>",
+
+ "<input type=\"hidden\">",
+ "<input type=\"hidden\" tabindex=\"-1\">",
+ "<input type=\"hidden\" tabindex=\"0\">",
+ "<input type=\"hidden\" tabindex=\"0\" disabled>",
+ "<input type=\"hidden\" tabindex=\"1\">",
+ "<input type=\"hidden\" disabled>",
+ "<input type=\"hidden\" contenteditable=\"true\">",
+
+ "<input type=\"image\" tabindex=\"0\" disabled>",
+ "<input type=\"image\" disabled>",
+
+ "<input type=\"password\" tabindex=\"0\" disabled>",
+ "<input type=\"password\" disabled>",
+
+ "<input type=\"radio\" tabindex=\"0\" disabled>",
+ "<input type=\"radio\" disabled>",
+
+ "<input type=\"reset\" tabindex=\"0\" disabled>",
+ "<input type=\"reset\" disabled>",
+
+ "<input type=\"submit\" tabindex=\"0\" disabled>",
+ "<input type=\"submit\" disabled>",
+
+ "<input type=\"text\" tabindex=\"0\" disabled>",
+ "<input type=\"text\" disabled>",
+
+ "<object></object>",
+
+ "<select tabindex=\"0\" disabled></select>",
+ "<select disabled></select>",
+
+ "<option></option>",
+ "<option tabindex='1' disabled></option>",
+
+ "<optgroup></optgroup>",
+ "<optgroup tabindex='1' disabled></optgroup>"
+];
+
+var focusableInContentEditable = [
+ "<button></button>",
+ "<button tabindex=\"-1\"></button>",
+ "<button tabindex=\"0\"></button>",
+ "<button tabindex=\"1\"></button>",
+ "<button contenteditable=\"true\"></button>",
+
+ "<button type=\"reset\"></button>",
+ "<button type=\"reset\" tabindex=\"-1\"></button>",
+ "<button type=\"reset\" tabindex=\"0\"></button>",
+ "<button type=\"reset\" tabindex=\"1\"></button>",
+ "<button type=\"reset\" contenteditable=\"true\"></button>",
+
+ "<button type=\"submit\"></button>",
+ "<button type=\"submit\" tabindex=\"-1\"></button>",
+ "<button type=\"submit\" tabindex=\"0\"></button>",
+ "<button type=\"submit\" tabindex=\"1\"></button>",
+ "<button type=\"submit\" contenteditable=\"true\"></button>",
+
+ "<div tabindex=\"-1\"></div>",
+ "<div tabindex=\"0\"></div>",
+ "<div tabindex=\"1\"></div>",
+ "<div tabindex=\"0\" disabled></div>",
+
+ "<embed>",
+ "<embed tabindex=\"-1\">",
+ "<embed tabindex=\"0\">",
+ "<embed tabindex=\"0\" disabled>",
+ "<embed tabindex=\"1\">",
+ "<embed disabled>",
+ "<embed contenteditable=\"true\">",
+
+ "<iframe src=\"about:blank\"></iframe>",
+ "<iframe></iframe>",
+ "<iframe src=\"about:blank\" disabled></iframe>",
+ "<iframe disabled></iframe>",
+ "<iframe src=\"about:blank\" tabindex=\"-1\"></iframe>",
+ "<iframe tabindex=\"-1\"></iframe>",
+ "<iframe src=\"about:blank\" tabindex=\"0\"></iframe>",
+ "<iframe tabindex=\"0\"></iframe>",
+ "<iframe src=\"about:blank\" tabindex=\"0\" disabled></iframe>",
+ "<iframe tabindex=\"0\" disabled></iframe>",
+ "<iframe src=\"about:blank\" tabindex=\"1\"></iframe>",
+ "<iframe tabindex=\"1\"></iframe>",
+ "<iframe src=\"about:blank\" contenteditable=\"true\"></iframe>",
+ "<iframe contenteditable=\"true\"></iframe>",
+
+ "<img tabindex=\"-1\">",
+ "<img tabindex=\"0\">",
+ "<img tabindex=\"0\" disabled>",
+ "<img tabindex=\"1\">",
+
+ "<input>",
+ "<input tabindex=\"-1\">",
+ "<input tabindex=\"0\">",
+ "<input tabindex=\"1\">",
+ "<input contenteditable=\"true\">",
+
+ "<input type=\"button\">",
+ "<input type=\"button\" tabindex=\"-1\">",
+ "<input type=\"button\" tabindex=\"0\">",
+ "<input type=\"button\" tabindex=\"1\">",
+ "<input type=\"button\" contenteditable=\"true\">",
+
+ "<input type=\"file\">",
+ "<input type=\"file\" tabindex=\"-1\">",
+ "<input type=\"file\" tabindex=\"0\">",
+ "<input type=\"file\" tabindex=\"1\">",
+ "<input type=\"file\" contenteditable=\"true\">",
+
+ "<input type=\"checkbox\">",
+ "<input type=\"checkbox\" tabindex=\"-1\">",
+ "<input type=\"checkbox\" tabindex=\"0\">",
+ "<input type=\"checkbox\" tabindex=\"1\">",
+ "<input type=\"checkbox\" contenteditable=\"true\">",
+
+ "<input type=\"image\">",
+ "<input type=\"image\" tabindex=\"-1\">",
+ "<input type=\"image\" tabindex=\"0\">",
+ "<input type=\"image\" tabindex=\"1\">",
+ "<input type=\"image\" contenteditable=\"true\">",
+
+ "<input type=\"password\">",
+ "<input type=\"password\" tabindex=\"-1\">",
+ "<input type=\"password\" tabindex=\"0\">",
+ "<input type=\"password\" tabindex=\"1\">",
+ "<input type=\"password\" contenteditable=\"true\">",
+
+ "<input type=\"radio\">",
+ "<input type=\"radio\" tabindex=\"-1\">",
+ "<input type=\"radio\" tabindex=\"0\">",
+ "<input type=\"radio\" tabindex=\"1\">",
+ "<input type=\"radio\" contenteditable=\"true\">",
+ "<input type=\"radio\" checked>",
+ "<form><input type=\"radio\" name=\"foo\"></form>",
+
+ "<input type=\"reset\">",
+ "<input type=\"reset\" tabindex=\"-1\">",
+ "<input type=\"reset\" tabindex=\"0\">",
+ "<input type=\"reset\" tabindex=\"1\">",
+ "<input type=\"reset\" contenteditable=\"true\">",
+
+ "<input type=\"submit\">",
+ "<input type=\"submit\" tabindex=\"-1\">",
+ "<input type=\"submit\" tabindex=\"0\">",
+ "<input type=\"submit\" tabindex=\"1\">",
+ "<input type=\"submit\" contenteditable=\"true\">",
+
+ "<input type=\"text\">",
+ "<input type=\"text\" tabindex=\"-1\">",
+ "<input type=\"text\" tabindex=\"0\">",
+ "<input type=\"text\" tabindex=\"1\">",
+ "<input type=\"text\" contenteditable=\"true\">",
+
+ "<input type=\"number\">",
+ "<input type=\"number\" tabindex=\"-1\">",
+ "<input type=\"number\" tabindex=\"0\">",
+ "<input type=\"number\" tabindex=\"1\">",
+ "<input type=\"number\" contenteditable=\"true\">",
+
+ "<object tabindex=\"-1\"></object>",
+ "<object tabindex=\"0\"></object>",
+ "<object tabindex=\"1\"></object>",
+
+ // Disabled doesn't work for <object>.
+ "<object tabindex=\"0\" disabled></object>",
+ "<object disabled></object>",
+
+ "<select></select>",
+ "<select tabindex=\"-1\"></select>",
+ "<select tabindex=\"0\"></select>",
+ "<select tabindex=\"1\"></select>",
+ "<select contenteditable=\"true\"></select>",
+
+ "<option tabindex='-1'></option>",
+ "<option tabindex='0'></option>",
+ "<option tabindex='1'></option>",
+
+ "<optgroup tabindex='-1'></optgroup>",
+ "<optgroup tabindex='0'></optgroup>",
+ "<optgroup tabindex='1'></optgroup>"
+];
+
+var focusableInDesignMode = [
+ "<embed>",
+ "<embed tabindex=\"-1\">",
+ "<embed tabindex=\"0\">",
+ "<embed tabindex=\"0\" disabled>",
+ "<embed tabindex=\"1\">",
+ "<embed disabled>",
+ "<embed contenteditable=\"true\">",
+
+ "<img tabindex=\"-1\">",
+ "<img tabindex=\"0\">",
+ "<img tabindex=\"0\" disabled>",
+ "<img tabindex=\"1\">",
+];
+
+// Can't currently test these, need a plugin.
+var focusableElementsTODO = [
+ "<object classid=\"java:a\"></object>",
+ "<object classid=\"java:a\" tabindex=\"-1\"></object>",
+ "<object classid=\"java:a\" tabindex=\"0\"></object>",
+ "<object classid=\"java:a\" tabindex=\"0\" disabled></object>",
+ "<object classid=\"java:a\" tabindex=\"1\"></object>",
+ "<object classid=\"java:a\" disabled></object>",
+ "<object classid=\"java:a\" contenteditable=\"true\"></object>",
+];
+
+var serializer = new XMLSerializer();
+
+function testElements(parent, tags, shouldBeFocusable)
+{
+ var focusable, errorSuffix = "";
+ if (parent.ownerDocument.designMode == "on") {
+ focusable = focusableInDesignMode;
+ errorSuffix = " in a document with designMode=on";
+ }
+ else if (parent.contentEditable == "true") {
+ focusable = focusableInContentEditable;
+ }
+
+ for (var tag of tags) {
+ parent.ownerDocument.body.focus();
+
+ if (focusableElementsTODO.indexOf(tag) > -1) {
+ todo_is(parent.ownerDocument.activeElement, parent.firstChild,
+ tag + " should be focusable" + errorSuffix);
+ continue;
+ }
+
+ parent.innerHTML = tag;
+
+ // Focus the deepest descendant.
+ var descendant = parent;
+ while ((descendant = descendant.firstChild))
+ element = descendant;
+
+ if (element.nodeName == "IFRAME" && element.hasAttribute("src"))
+ var foo = element.contentDocument;
+
+ element.focus();
+
+ var errorPrefix = serializer.serializeToString(element) + " in " +
+ serializer.serializeToString(parent);
+
+ try {
+ // Make sure activeElement doesn't point to a
+ // native anonymous element.
+ parent.ownerDocument.activeElement.localName;
+ } catch (ex) {
+ ok(false, ex + errorPrefix + errorSuffix);
+ }
+ if (focusable ? focusable.indexOf(tag) > -1 : shouldBeFocusable) {
+ is(parent.ownerDocument.activeElement, element,
+ errorPrefix + " should be focusable" + errorSuffix);
+ }
+ else {
+ isnot(parent.ownerDocument.activeElement, element,
+ errorPrefix + " should not be focusable" + errorSuffix);
+ }
+
+ parent.innerHTML = "";
+ }
+}
+
+function test()
+{
+ var parent = document.getElementById("parent");
+ var editableParent = document.getElementById("editableParent");
+
+ testElements(parent, focusableElements, true);
+ testElements(parent, nonFocusableElements, false);
+
+ testElements(editableParent, focusableElements, true);
+ testElements(editableParent, nonFocusableElements, false);
+
+ var frame = document.getElementById("frame");
+ frame.contentDocument.body.innerHTML = document.getElementById("content").innerHTML;
+ frame.contentDocument.designMode = "on";
+ parent = frame.contentDocument.getElementById("parent");
+ editableParent = frame.contentDocument.getElementById("editableParent");
+
+ testElements(parent, focusableElements, false);
+ testElements(parent, nonFocusableElements, false);
+
+ testElements(editableParent, focusableElements, false);
+ testElements(editableParent, nonFocusableElements, false);
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(test);
+addLoadEvent(SimpleTest.finish);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug430392.html b/dom/html/test/test_bug430392.html
new file mode 100644
index 000000000..f483e454d
--- /dev/null
+++ b/dom/html/test/test_bug430392.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=430392
+-->
+<head>
+ <title>Test for Bug 430392</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=430392">Mozilla Bug 430392</a>
+<p id="display"></p>
+<div id="content">
+ <div contenteditable="true" id="edit"> <span contenteditable="false">A</span> ; <span contenteditable="false">B</span> ; <span contenteditable="false">C</span> </div>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 430392 **/
+
+function test() {
+ var edit = document.getElementById("edit");
+ var html = edit.innerHTML;
+ document.getElementById("edit").focus();
+
+ synthesizeKey("VK_RIGHT", {});
+ synthesizeKey("VK_RIGHT", {});
+ synthesizeKey("VK_RETURN", {});
+ synthesizeKey("VK_RETURN", {});
+ synthesizeKey("VK_BACK_SPACE", {});
+ synthesizeKey("VK_BACK_SPACE", {});
+
+ is(edit.innerHTML, html,
+ "adding and then deleting returns should not change text");
+
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(test);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug435128.html b/dom/html/test/test_bug435128.html
new file mode 100644
index 000000000..9d2c85b03
--- /dev/null
+++ b/dom/html/test/test_bug435128.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=435128
+-->
+<head>
+ <title>Test for Bug 435128</title>
+ <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=435128">Mozilla Bug 435128</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<iframe id="content" src="data:text/html;charset=utf-8,%3Chtml%3E%3Chead%3E%3C/head%3E%3Cbody%3E%0A%3Ciframe%20id%3D%22a%22%3E%3C/iframe%3E%0A%3Cscript%3E%0Afunction%20doe%28%29%20%7B%0Avar%20x%20%3D%20window.frames%5B0%5D.document%3B%0A%0Avar%20y%3Ddocument.getElementById%28%27a%27%29%3B%0Ay.parentNode.removeChild%28y%29%3B%0A%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0Atry%20%7Bx.write%28%27t%27%29%3B%7D%20catch%28e%29%20%7B%7D%0A%7D%0AsetTimeout%28%27doe%28%29%27%2C20%29%3B%0A%3C/script%3E%0A%3C/body%3E%3C/html%3E" style="width: 1000px; height: 200px;"></iframe>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 435128 **/
+
+SimpleTest.waitForExplicitFinish();
+
+setTimeout(finish, 60000);
+
+function doe2() {
+ document.getElementById('content').src = document.getElementById('content').src;
+}
+setInterval(doe2, 400);
+
+function finish()
+{
+ ok(true, "This is a mochikit version of a crash test. To complete is to pass.");
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug441930.html b/dom/html/test/test_bug441930.html
new file mode 100644
index 000000000..2a0b18130
--- /dev/null
+++ b/dom/html/test/test_bug441930.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=441930
+-->
+<head>
+ <title>Test for Bug 441930</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=441930">Mozilla Bug 441930</a>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 441930: see bug441930_iframe.html **/
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+<p id="display">
+ <iframe src="bug441930_iframe.html"></iframe>
+</p>
+<div id="content" style="display: none">
+</div>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug442801.html b/dom/html/test/test_bug442801.html
new file mode 100644
index 000000000..b04b23ac8
--- /dev/null
+++ b/dom/html/test/test_bug442801.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=442801
+-->
+<head>
+ <title>Test for Bug 442801</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=442801">Mozilla Bug 442801</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+<div contenteditable="true">
+<p id="ce_true" contenteditable="true">contenteditable true</p>
+</div>
+
+<div contenteditable="true">
+<p id="ce_false" contenteditable="false">contenteditable false</p>
+</div>
+
+<div contenteditable="true">
+<p id="ce_empty" contenteditable="">contenteditable empty</p>
+</div>
+
+<div contenteditable="true">
+<p id="ce_inherit" contenteditable="inherit">contenteditable inherit</p>
+</div>
+
+<div contenteditable="true">
+<p id="ce_none" >contenteditable none</p>
+</div>
+
+
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 442801 **/
+
+is(window.getComputedStyle($("ce_true"), null).getPropertyValue("-moz-user-modify"),
+ "read-write",
+ "parent contenteditable is true, contenteditable is true; user-modify should be read-write");
+is(window.getComputedStyle($("ce_false"), null).getPropertyValue("-moz-user-modify"),
+ "read-only",
+ "parent contenteditable is true, contenteditable is false; user-modify should be read-only");
+is(window.getComputedStyle($("ce_empty"), null).getPropertyValue("-moz-user-modify"),
+ "read-write",
+ "parent contenteditable is true, contenteditable is empty; user-modify should be read-write");
+is(window.getComputedStyle($("ce_inherit"), null).getPropertyValue("-moz-user-modify"),
+ "read-write",
+ "parent contenteditable is true, contenteditable is inherit; user-modify should be read-write");
+is(window.getComputedStyle($("ce_none"), null).getPropertyValue("-moz-user-modify"),
+ "read-write",
+ "parent contenteditable is true, contenteditable is none; user-modify should be read-write");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug445004.html b/dom/html/test/test_bug445004.html
new file mode 100644
index 000000000..ec98f56c8
--- /dev/null
+++ b/dom/html/test/test_bug445004.html
@@ -0,0 +1,138 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=445004
+-->
+<head>
+ <title>Test for Bug 445004</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=445004">Mozilla Bug 445004</a>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 445004 **/
+is(window.location.hostname, "mochi.test", "Unexpected hostname");
+is(window.location.port, "8888", "Unexpected port; fix testcase");
+
+SimpleTest.waitForExplicitFinish();
+
+var loads = 1;
+
+function loadStarted() {
+ ++loads;
+}
+function loadEnded() {
+ --loads;
+ if (loads == 0) {
+ doTest();
+ }
+}
+
+window.onload = loadEnded;
+
+function getMessage(evt) {
+ ok(evt.data == "start" || evt.data == "end", "Must have start or end");
+ if (evt.data == "start")
+ loadStarted();
+ else
+ loadEnded();
+}
+
+window.addEventListener("message", getMessage, false);
+
+function checkURI(uri, name, type) {
+ var host = uri.match(/^http:\/\/([a-z.0-9]*)/)[1];
+ var file = uri.match(/([^\/]*).png$/)[1];
+ is(host, file, "Unexpected base URI for test " + name +
+ " when testing " + type);
+}
+
+function checkFrame(num) {
+ // Just snarf our data
+ var outer = SpecialPowers.wrap(window.frames[num]);
+ name = outer.name;
+
+ is(outer.document.baseURI,
+ "http://example.org/tests/dom/html/test/bug445004-outer.html",
+ "Unexpected base URI for " + name);
+
+ var iswrite = name.match(/write/);
+
+ var inner = outer.frames[0];
+ if (iswrite) {
+ is(inner.document.baseURI,
+ "http://example.org/tests/dom/html/test/bug445004-outer.html",
+ "Unexpected inner base URI for " + name);
+ } else {
+ is(inner.document.baseURI,
+ "http://test1.example.org/tests/dom/html/test/bug445004-inner.html",
+ "Unexpected inner base URI for " + name);
+ }
+
+ var isrel = name.match(/rel/);
+ var offsite = name.match(/offsite/);
+
+ if (!iswrite) {
+ if ((isrel && !offsite) || (!isrel && offsite)) {
+ is(inner.location.hostname, outer.location.hostname,
+ "Unexpected hostnames for " + name);
+ } else {
+ isnot(inner.location.hostname, outer.location.hostname,
+ "Unexpected hostnames for " + name);
+ }
+ }
+
+ checkURI(inner.frames[0].location.href, name, "direct location");
+ checkURI(inner.frames[1].document.getElementsByTagName("img")[0].src,
+ name, "direct write");
+ if (!iswrite) {
+ is(inner.frames[1].location.hostname, inner.location.hostname,
+ "Incorrect hostname for " + name + " direct write")
+ }
+ checkURI(inner.frames[2].location.href, name, "indirect location");
+ checkURI(inner.frames[3].document.getElementsByTagName("img")[0].src,
+ name, "indirect write");
+ if (!iswrite) {
+ is(inner.frames[3].location.hostname, outer.location.hostname,
+ "Incorrect hostname for " + name + " indirect write")
+ }
+ checkURI(inner.document.getElementsByTagName("img")[0].src,
+ name, "direct image load");
+}
+
+
+function doTest() {
+ for (var num = 0; num < 5; ++num) {
+ checkFrame(num);
+ }
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+<p id="display">
+ <iframe
+ src="http://example.org/tests/dom/html/test/bug445004-outer-rel.html"
+ name="bug445004-outer-rel.html"></iframe>
+ <iframe
+ src="http://test1.example.org/tests/dom/html/test/bug445004-outer-rel.html"
+ name="bug445004-outer-rel.html offsite"></iframe>
+ <iframe
+ src="http://example.org/tests/dom/html/test/bug445004-outer-abs.html"
+ name="bug445004-outer-abs.html"></iframe>
+ <iframe
+ src="http://test1.example.org/tests/dom/html/test/bug445004-outer-abs.html"
+ name="bug445004-outer-abs.html offsite"></iframe>
+ <iframe
+ src="http://example.org/tests/dom/html/test/bug445004-outer-write.html"
+ name="bug445004-outer-write.html"></iframe>
+</p>
+</body>
+</html>
diff --git a/dom/html/test/test_bug446483.html b/dom/html/test/test_bug446483.html
new file mode 100644
index 000000000..def6553d5
--- /dev/null
+++ b/dom/html/test/test_bug446483.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=446483
+-->
+<head>
+ <title>Test for Bug 446483</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=446483">Mozilla Bug 446483</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 446483 **/
+
+function gc() {
+ SpecialPowers.gc();
+}
+
+function runTest() {
+ document.getElementById('display').innerHTML =
+ '<iframe src="bug446483-iframe.html"><\/iframe>\n' +
+ '<iframe src="bug446483-iframe.html"><\/iframe>\n';
+
+ setInterval(gc, 1000);
+
+ setTimeout(function() {
+ document.getElementById('display').innerHTML = '';
+ ok(true, '');
+ SimpleTest.finish();
+ }, 4000);
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+addLoadEvent(runTest);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug448166.html b/dom/html/test/test_bug448166.html
new file mode 100644
index 000000000..ec4b3d1a4
--- /dev/null
+++ b/dom/html/test/test_bug448166.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=448166
+-->
+<head>
+ <title>Test for Bug 448166</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=448166">Mozilla Bug 448166</a>
+<p id="display">
+ <a id="test" href="http://www.moz&#xdc00;illa.org">should not be Mozilla</a>
+ <a id="control" href="http://www.mozilla.org">should not be Mozilla</a>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 448166 **/
+isnot($("test").href, "http://www.mozilla.org/",
+ "Should notice unpaired surrogate");
+is($("test").href, "http://www.xn--mozilla-2e14b.org/",
+ "Should replace unpaired surrogate with replacement char");
+is($("control").href, "http://www.mozilla.org/",
+ "Just making sure .href works");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug448564.html b/dom/html/test/test_bug448564.html
new file mode 100644
index 000000000..27d5a272f
--- /dev/null
+++ b/dom/html/test/test_bug448564.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=448564
+-->
+<head>
+ <title>Test for Bug 448564</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=448564">Mozilla Bug 448564</a>
+<p id="display">
+ <iframe src="bug448564-iframe-1.html"></iframe>
+ <iframe src="bug448564-iframe-2.html"></iframe>
+ <iframe src="bug448564-iframe-3.html"></iframe>
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 448564 **/
+
+/**
+ * The three iframes are going to be loaded with some dirty constructed forms.
+ * Each of them will be submitted before the load event and a SJS will replace
+ * the frame content with the query string.
+ * Then, on the load event, our test file will check the content of each iframes
+ * and check if the query string were correctly formatted (implying that all
+ * iframes were correctly submitted.
+ */
+
+function checkQueryString(frame) {
+ var queryString = frame.document.body.textContent;
+ is(queryString.split("&").sort().join("&"),
+ "a=aval&b=bval&c=cval&d=dval",
+ "Not all form fields were properly submitted.");
+}
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(function() {
+ checkQueryString(frames[0]);
+ checkQueryString(frames[1]);
+ checkQueryString(frames[2]);
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug456229.html b/dom/html/test/test_bug456229.html
new file mode 100644
index 000000000..bc12523c7
--- /dev/null
+++ b/dom/html/test/test_bug456229.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=456229
+-->
+<head>
+ <title>Test for Bug 456229</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=456229">Mozilla Bug 456229</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <input id='i' type="search">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 456229 **/
+
+// More checks are done in test_bug551670.html.
+
+var i = document.getElementById('i');
+is(i.type, 'search', "Search state should be recognized");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug458037.xhtml b/dom/html/test/test_bug458037.xhtml
new file mode 100644
index 000000000..965db499c
--- /dev/null
+++ b/dom/html/test/test_bug458037.xhtml
@@ -0,0 +1,112 @@
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=458037
+-->
+<head>
+ <title>Test for Bug 458037</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=458037">Mozilla Bug 458037</a>
+<p id="display"></p>
+<div id="content" >
+<div id="a"></div>
+<div id="b" contenteditable="true"></div>
+<div id="c" contenteditable="false"></div>
+<div id="d" contenteditable="inherit"></div>
+<div contenteditable="true">
+ <div id="e"></div>
+</div>
+<div contenteditable="false">
+ <div id="f"></div>
+</div>
+<div contenteditable="true">
+ <div id="g" contenteditable="false"></div>
+</div>
+<div contenteditable="false">
+ <div id="h" contenteditable="true"></div>
+</div>
+<div contenteditable="true">
+ <div id="i" contenteditable="inherit"></div>
+</div>
+<div contenteditable="false">
+ <div id="j" contenteditable="inherit"></div>
+</div>
+<div contenteditable="true">
+ <xul:box>
+ <div id="k"></div>
+ </xul:box>
+</div>
+<div contenteditable="false">
+ <xul:box>
+ <div id="l"></div>
+ </xul:box>
+</div>
+<div contenteditable="true">
+ <xul:box>
+ <div id="m" contenteditable="inherit"></div>
+ </xul:box>
+</div>
+<div contenteditable="false">
+ <xul:box>
+ <div id="n" contenteditable="inherit"></div>
+ </xul:box>
+</div>
+<div id="x"></div>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 458037 **/
+
+function test(id, expected) {
+ is(document.getElementById(id).isContentEditable, expected,
+ "Element " + id + " should " + (expected ? "" : "not ") + "be editable");
+}
+
+document.addEventListener("DOMContentLoaded", function() {
+ test("a", false);
+ test("b", true);
+ test("c", false);
+ test("d", false);
+ test("e", true);
+ test("f", false);
+ test("g", false);
+ test("h", true);
+ test("i", true);
+ test("j", false);
+ test("k", true);
+ test("l", false);
+ test("m", true);
+ test("n", false);
+
+ var d = document.getElementById("x");
+ test("x", false);
+ d.setAttribute("contenteditable", "true");
+ test("x", true);
+ d.setAttribute("contenteditable", "false");
+ test("x", false);
+ d.setAttribute("contenteditable", "inherit");
+ test("x", false);
+ d.removeAttribute("contenteditable");
+ test("x", false);
+ d.contentEditable = "true";
+ test("x", true);
+ d.contentEditable = "false";
+ test("x", false);
+ d.contentEditable = "inherit";
+ test("x", false);
+
+ // Make sure that isContentEditable is read-only
+ var origValue = d.isContentEditable;
+ d.isContentEditable = !origValue;
+ is(d.isContentEditable, origValue, "isContentEditable should be read only");
+}, false);
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug460568.html b/dom/html/test/test_bug460568.html
new file mode 100644
index 000000000..14bcbbc78
--- /dev/null
+++ b/dom/html/test/test_bug460568.html
@@ -0,0 +1,147 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=460568
+-->
+<head>
+ <title>Test for Bug 460568</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=460568">Mozilla Bug 460568</a>
+<p id="display"><a href="" id="anchor">a[href]</a></p>
+<div id="editor">
+ <a href="" id="anchorInEditor">a[href] in editor</a>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 460568 **/
+
+function runTest()
+{
+ var editor = document.getElementById("editor");
+ var anchor = document.getElementById("anchor");
+ var anchorInEditor = document.getElementById("anchorInEditor");
+
+ var focused;
+ anchorInEditor.onfocus = function() { focused = true; };
+
+ function isReallyEditable()
+ {
+ editor.focus();
+ var range = document.createRange();
+ range.selectNodeContents(editor);
+ var prevStr = range.toString();
+
+ var docShell = SpecialPowers.wrap(window)
+ .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsIWebNavigation)
+ .QueryInterface(SpecialPowers.Ci.nsIDocShell);
+ var controller =
+ docShell.QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsISelectionDisplay)
+ .QueryInterface(SpecialPowers.Ci.nsISelectionController);
+ var sel = controller.getSelection(controller.SELECTION_NORMAL);
+ sel.collapse(anchorInEditor, 0);
+ synthesizeKey('a', {});
+ range.selectNodeContents(editor);
+ return prevStr != range.toString();
+ }
+
+ focused = false;
+ anchor.focus();
+ editor.setAttribute("contenteditable", "true");
+ anchorInEditor.focus();
+ is(focused, false, "focus moved to element in contenteditable=true");
+ is(isReallyEditable(), true, "cannot edit by a key event");
+
+ // for bug 502273
+ focused = false;
+ anchor.focus();
+ editor.setAttribute("dummy", "dummy");
+ editor.removeAttribute("dummy");
+ anchorInEditor.focus();
+ is(focused, false, "focus moved to element in contenteditable=true (after dummy attribute was removed)");
+ is(isReallyEditable(), true, "cannot edit by a key event");
+
+ focused = false;
+ anchor.focus();
+ editor.setAttribute("contenteditable", "false");
+ anchorInEditor.focus();
+ is(focused, true, "focus didn't move to element in contenteditable=false");
+ is(isReallyEditable(), false, "can edit by a key event");
+
+ // for bug 502273
+ focused = false;
+ anchor.focus();
+ editor.setAttribute("dummy", "dummy");
+ editor.removeAttribute("dummy");
+ anchorInEditor.focus();
+ is(focused, true, "focus moved to element in contenteditable=true (after dummy attribute was removed)");
+ is(isReallyEditable(), false, "cannot edit by a key event");
+
+ focused = false;
+ anchor.focus();
+ editor.setAttribute("contenteditable", "true");
+ anchorInEditor.focus();
+ is(focused, false, "focus moved to element in contenteditable=true");
+ is(isReallyEditable(), true, "cannot edit by a key event");
+
+ // for bug 502273
+ focused = false;
+ anchor.focus();
+ editor.setAttribute("dummy", "dummy");
+ editor.removeAttribute("dummy");
+ anchorInEditor.focus();
+ is(focused, false, "focus moved to element in contenteditable=true (after dummy attribute was removed)");
+ is(isReallyEditable(), true, "cannot edit by a key event");
+
+ focused = false;
+ anchor.focus();
+ editor.removeAttribute("contenteditable");
+ anchorInEditor.focus();
+ is(focused, true, "focus didn't move to element in contenteditable removed element");
+ is(isReallyEditable(), false, "can edit by a key event");
+
+ focused = false;
+ anchor.focus();
+ editor.contentEditable = true;
+ anchorInEditor.focus();
+ is(focused, false, "focus moved to element in contenteditable=true by property");
+ is(isReallyEditable(), true, "cannot edit by a key event");
+
+ focused = false;
+ anchor.focus();
+ editor.contentEditable = false;
+ anchorInEditor.focus();
+ is(focused, true, "focus didn't move to element in contenteditable=false by property");
+ is(isReallyEditable(), false, "can edit by a key event");
+
+ focused = false;
+ anchor.focus();
+ editor.setAttribute("contenteditable", "true");
+ anchorInEditor.focus();
+ is(focused, false, "focus moved to element in contenteditable=true");
+ is(isReallyEditable(), true, "cannot edit by a key event");
+
+ // for bug 502273
+ focused = false;
+ anchor.focus();
+ editor.setAttribute("dummy", "dummy");
+ editor.removeAttribute("dummy");
+ anchorInEditor.focus();
+ is(focused, false, "focus moved to element in contenteditable=true (after dummy attribute was removed)");
+ is(isReallyEditable(), true, "cannot edit by a key event");
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+addLoadEvent(SimpleTest.finish);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug463104.html b/dom/html/test/test_bug463104.html
new file mode 100644
index 000000000..f424cd183
--- /dev/null
+++ b/dom/html/test/test_bug463104.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Noninteger coordinates test</title>
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<div id="a" style="position: fixed; left: 5.5px; top: 5.5px; width: 100px; height: 100px; background: blue"></div>
+<p style="margin-top: 110px">
+<script>
+var a = document.getElementById("a");
+isnot(a, document.elementFromPoint(5, 5), "a shouldn't be found");
+isnot(a, document.elementFromPoint(5.25, 5.25), "a shouldn't be found");
+is(a, document.elementFromPoint(5.5, 5.5), "a should be found");
+is(a, document.elementFromPoint(5.75, 5.75), "a should be found");
+is(a, document.elementFromPoint(6, 6), "a should be found");
+is(a, document.elementFromPoint(105, 105), "a should be found");
+is(a, document.elementFromPoint(105.25, 105.25), "a should be found");
+isnot(a, document.elementFromPoint(105.5, 105.5), "a shouldn't be found");
+isnot(a, document.elementFromPoint(105.75, 105.75), "a shouldn't be found");
+isnot(a, document.elementFromPoint(106, 106), "a shouldn't be found");
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug478251.html b/dom/html/test/test_bug478251.html
new file mode 100644
index 000000000..537ccf12e
--- /dev/null
+++ b/dom/html/test/test_bug478251.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=478251
+-->
+<head>
+ <title>Test for Bug 478251</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=478251">Mozilla Bug 478251</a>
+<p id="display"><iframe id="t"></iframe></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 478251 **/
+var doc = $("t").contentDocument;
+doc.open();
+doc.write();
+doc.close();
+is(doc.documentElement.textContent, "", "Writing || failed");
+
+doc.open();
+doc.write(null);
+doc.close();
+is(doc.documentElement.textContent, "null", "Writing |null| failed");
+
+doc.open();
+doc.write(null, null);
+doc.close();
+is(doc.documentElement.textContent, "nullnull", "Writing |null, null| failed");
+
+doc.open();
+doc.write(undefined);
+doc.close();
+is(doc.documentElement.textContent, "undefined", "Writing |undefined| failed");
+
+doc.open();
+doc.write(undefined, undefined);
+doc.close();
+is(doc.documentElement.textContent, "undefinedundefined", "Writing |undefined, undefined| failed");
+
+doc.open();
+doc.writeln();
+doc.close();
+ok(doc.documentElement.textContent == "\n" || doc.documentElement.textContent == "", "Writing |\\n| failed");
+
+doc.open();
+doc.writeln(null);
+doc.close();
+is(doc.documentElement.textContent, "null\n", "Writing |null\\n| failed");
+
+doc.open();
+doc.writeln(null, null);
+doc.close();
+is(doc.documentElement.textContent, "nullnull\n", "Writing |null, null\\n| failed");
+
+doc.open();
+doc.writeln(undefined);
+doc.close();
+is(doc.documentElement.textContent, "undefined\n", "Writing |undefined\\n| failed");
+
+doc.open();
+doc.writeln(undefined, undefined);
+doc.close();
+is(doc.documentElement.textContent, "undefinedundefined\n", "Writing |undefined, undefined\\n| failed");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug481335.xhtml b/dom/html/test/test_bug481335.xhtml
new file mode 100644
index 000000000..f8a51df69
--- /dev/null
+++ b/dom/html/test/test_bug481335.xhtml
@@ -0,0 +1,120 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=481335
+-->
+<head>
+ <title>Test for Bug 481335</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style type="text/css">
+ a { color:blue; }
+ a:visited { color:red; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481335">Mozilla Bug 481335</a>
+<p id="display">
+ <a id="t">A link</a>
+ <iframe id="i"></iframe>
+</p>
+<p id="newparent" xml:base="http://www.example.com/"></p>
+<div id="content" style="display: none"></div>
+<pre id="test">
+<script type="application/javascript;version=1.7">
+<![CDATA[
+
+/** Test for Bug 481335 **/
+SimpleTest.waitForExplicitFinish();
+var rand = Date.now() + "-" + Math.random();
+
+is($("t").href, "",
+ "Unexpected href before set");
+is($("t").href, "",
+ "Unexpected cached href before set");
+
+$("t").setAttribute("href", rand);
+is($("t").href,
+ window.location.href.replace(/test_bug481335.xhtml([\?].*)?/, rand),
+ "Unexpected href after set");
+is($("t").href,
+ window.location.href.replace(/test_bug481335.xhtml([\?].*)?/, rand),
+ "Unexpected cached href after set");
+const unvisitedColor = "rgb(0, 0, 255)";
+const visitedColor = "rgb(255, 0, 0)";
+
+let tests = testIterator();
+function continueTest() {
+ tests.next();
+}
+
+function checkLinkColor(aElmId, aExpectedColor, aMessage) {
+ // Because link coloring is asynchronous, we wait until we get the right
+ // result, or we will time out (resulting in a failure).
+ function getColor() {
+ var utils = SpecialPowers.getDOMWindowUtils(window);
+ return utils.getVisitedDependentComputedStyle($(aElmId), "", "color");
+ }
+ while (getColor() != aExpectedColor) {
+ setTimeout(continueTest, 0);
+ return false;
+ }
+ is(getColor(), aExpectedColor, aMessage);
+ return true;
+}
+
+function testIterator() {
+ // After first load
+ $("newparent").appendChild($("t"));
+ is($("t").href, "http://www.example.com/" + rand,
+ "Unexpected href after move");
+ is($("t").href, "http://www.example.com/" + rand,
+ "Unexpected cached href after move");
+ while (!checkLinkColor("t", unvisitedColor, "Should be unvisited now"))
+ yield undefined;
+
+ $("i").src = $("t").href;
+ yield undefined;
+
+ // After second load
+ while (!checkLinkColor("t", visitedColor, "Should be visited now"))
+ yield undefined;
+ $("t").pathname = rand;
+ while (!checkLinkColor("t", visitedColor,
+ "Should still be visited after setting pathname to its existing value")) {
+ yield undefined;
+ }
+ /* TODO uncomment this test with the landing of bug 534526. See
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=461199#c167
+ $("t").pathname += "x";
+ while (!checkLinkColor("t", unvisitedColor,
+ "Should not be visited after changing pathname")) {
+ yield undefined;
+ }
+ $("t").pathname = $("t").pathname;
+ while (!checkLinkColor("t", unvisitedColor,
+ "Should not be visited after setting unvisited pathname to existing value")) {
+ yield undefined;
+ }
+ */
+
+ $("i").src = $("t").href;
+ yield undefined;
+
+ // After third load
+ while (!checkLinkColor("t", visitedColor,
+ "Should be visited now after third load")) {
+ yield undefined;
+ }
+ SimpleTest.finish();
+ yield undefined;
+}
+
+addLoadEvent(function() {
+ $("i").onload = continueTest;
+ $("i").src = $("t").href;
+});
+]]>
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug481440.html b/dom/html/test/test_bug481440.html
new file mode 100644
index 000000000..b6b454232
--- /dev/null
+++ b/dom/html/test/test_bug481440.html
@@ -0,0 +1,30 @@
+<!--Test must be in quirks mode for document.all to work-->
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=481440
+-->
+<head>
+ <title>Test for Bug 481440</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481440">Mozilla Bug 481440</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <input name="x" id="y">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 481440 **/
+// Do a bunch of getElementById calls to catch hashtables auto-going live
+for (var i = 0; i < 500; ++i) {
+ document.getElementById(i);
+}
+is(document.all["x"], document.getElementById("y"),
+ "Unexpected node");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug481647.html b/dom/html/test/test_bug481647.html
new file mode 100644
index 000000000..24928bbf7
--- /dev/null
+++ b/dom/html/test/test_bug481647.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=481647
+-->
+<head>
+ <title>Test for Bug 481647</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=481647">Mozilla Bug 481647</a>
+<p id="display">
+ <iframe src="javascript:'aaa'"></iframe>
+ <iframe src="javascript:document.write('aaa'); document.close();"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 481647 **/
+SimpleTest.waitForExplicitFinish()
+
+function testFrame(num) {
+ is(window.frames[num].document.baseURI, document.baseURI,
+ "Unexpected base URI in frame " + num);
+}
+
+addLoadEvent(function() {
+ for (var i = 0; i < 2; ++i) {
+ testFrame(i);
+ }
+
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug482659.html b/dom/html/test/test_bug482659.html
new file mode 100644
index 000000000..2329ae999
--- /dev/null
+++ b/dom/html/test/test_bug482659.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=482659
+-->
+<head>
+ <title>Test for Bug 482659</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=482659">Mozilla Bug 482659</a>
+<p id="display">
+ <iframe></iframe>
+ <iframe src="about:blank"></iframe>
+ <iframe></iframe>
+ <iframe src="about:blank"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 482659 **/
+SimpleTest.waitForExplicitFinish()
+
+function testFrame(num) {
+ is(window.frames[num].document.baseURI, document.baseURI,
+ "Unexpected base URI in frame " + num);
+ is(window.frames[num].document.documentURI, "about:blank",
+ "Unexpected document URI in frame " + num);
+}
+
+function appendScript(doc) {
+ var s = doc.createElement("script");
+ s.textContent = "document.write('executed'); document.close()";
+ doc.body.appendChild(s);
+}
+
+function verifyScriptRan(num) {
+ is(window.frames[num].document.documentElement.textContent, "executed",
+ "write didn't happen in frame " + num);
+}
+
+addLoadEvent(function() {
+/* document.write part of test disabled due to bug 483818
+ appendScript(window.frames[2].document);
+ appendScript(window.frames[3].document);
+
+ verifyScriptRan(2);
+ verifyScriptRan(3);
+*/
+ for (var i = 0; i < 4; ++i) {
+ testFrame(i);
+ }
+
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug486741.html b/dom/html/test/test_bug486741.html
new file mode 100644
index 000000000..69b1e2265
--- /dev/null
+++ b/dom/html/test/test_bug486741.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=486741
+-->
+<head>
+ <title>Test for Bug 486741</title>
+ <script type="application/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=486741">Mozilla Bug 486741</a>
+<p id="display"><iframe id="f"></iframe></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 486741 **/
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ var d = $("f").contentDocument;
+ var root = d.documentElement;
+ is(root.tagName, "HTML", "Unexpected root");
+
+ d.open();
+ isnot(d.documentElement, root, "Shouldn't have the old root element");
+
+ d.write("Test");
+ d.close();
+
+ isnot(d.documentElement, root, "Still shouldn't have the old root element");
+ is(d.documentElement.tagName, "HTML", "Unexpected new root after write");
+
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug489532.html b/dom/html/test/test_bug489532.html
new file mode 100644
index 000000000..ac28c3548
--- /dev/null
+++ b/dom/html/test/test_bug489532.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=489532
+-->
+<head>
+ <title>Test for Bug 489532</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=489532">Mozilla Bug 489532</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script>
+/** Test for Bug 489532 **/
+try {
+ document.createElement("<div>");
+ ok(false, "Should throw.")
+} catch (e) {
+ is(e.name, "InvalidCharacterError",
+ "Expected InvalidCharacterError.");
+ ok(e instanceof DOMException, "Expected DOMException.");
+ is(e.code, DOMException.INVALID_CHARACTER_ERR,
+ "Expected INVALID_CHARACTER_ERR.");
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug497242.xhtml b/dom/html/test/test_bug497242.xhtml
new file mode 100644
index 000000000..ba3965ee2
--- /dev/null
+++ b/dom/html/test/test_bug497242.xhtml
@@ -0,0 +1,41 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=497242
+-->
+<head>
+ <title>Test for Bug 497242</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=497242">Mozilla Bug 497242</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <form name="foo"/>
+ <form name="foo"/>
+ <form name="bar"/>
+ <form name="bar" xmlns=""/>
+</div>
+<pre id="test">
+<script type="application/javascript">
+<![CDATA[
+
+/** Test for Bug 497242 **/
+is(document.getElementsByName("foo").length, 2,
+ "Should find both forms with name 'foo'");
+is(document.getElementsByName("foo")[0],
+ document.getElementsByTagName("form")[0],
+ "Unexpected first foo");
+is(document.getElementsByName("foo")[1],
+ document.getElementsByTagName("form")[1],
+ "Unexpected second foo");
+is(document.getElementsByName("bar").length, 1,
+ "Should find only the HTML form with name 'bar'");
+is(document.getElementsByName("bar")[0],
+ document.getElementsByTagName("form")[2],
+ "Unexpected bar");
+]]>
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug499092.html b/dom/html/test/test_bug499092.html
new file mode 100644
index 000000000..d09dcb830
--- /dev/null
+++ b/dom/html/test/test_bug499092.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=499092
+-->
+<head>
+ <title>Test for Bug 499092</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=499092">Mozilla Bug 499092</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 499092 **/
+SimpleTest.waitForExplicitFinish();
+var content = document.getElementById("content");
+
+function testHtml() {
+ is(this.contentDocument.title, "HTML OK");
+ SimpleTest.finish();
+}
+
+function testXml() {
+ is(this.contentDocument.title, "XML OK");
+ var iframeHtml = document.createElement("iframe");
+ iframeHtml.onload = testHtml;
+ iframeHtml.src = "bug499092.html";
+ content.appendChild(iframeHtml);
+}
+
+var iframeXml = document.createElement("iframe");
+iframeXml.onload = testXml;
+iframeXml.src = "bug499092.xml";
+content.appendChild(iframeXml);
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug500885.html b/dom/html/test/test_bug500885.html
new file mode 100644
index 000000000..3e7b24883
--- /dev/null
+++ b/dom/html/test/test_bug500885.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=500885
+-->
+<head>
+ <title>Test for Bug 500885</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=500885">Mozilla Bug 500885</a>
+<div>
+ <input id="file" type="file" />
+</div>
+<script type="text/javascript">
+
+var MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+MockFilePicker.returnValue = MockFilePicker.returnOK;
+
+function test() {
+ // SpecialPowers.DOMWindowUtils doesn't appear to fire mouseEvents correctly
+ var wu = SpecialPowers.getDOMWindowUtils(window);
+
+ try {
+ var domActivateEvents;
+ var fileInput = document.getElementById("file");
+ var rect = fileInput.getBoundingClientRect();
+
+ fileInput.addEventListener ("DOMActivate", function (e) {
+ ok("detail" in e, "DOMActivate should have .detail");
+ is(e.detail, 1, ".detail should be 1");
+ domActivateEvents++;
+ }, false);
+
+ domActivateEvents = 0;
+ wu.sendMouseEvent("mousedown", rect.left + 5, rect.top + 5, 0, 1, 0);
+ wu.sendMouseEvent("mouseup", rect.left + 5, rect.top + 5, 0, 1, 0);
+ is(domActivateEvents, 1, "click on button should fire 1 DOMActivate event");
+
+ domActivateEvents = 0;
+ wu.sendMouseEvent("mousedown", rect.right - 5, rect.top + 5, 0, 1, 0);
+ wu.sendMouseEvent("mouseup", rect.right - 5, rect.top + 5, 0, 1, 0);
+ is(domActivateEvents, 1, "click on text field should fire 1 DOMActivate event");
+
+ } finally {
+ SimpleTest.executeSoon(function() {
+ MockFilePicker.cleanup();
+ SimpleTest.finish();
+ });
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(test);
+
+</script>
+</body>
+
+</html>
diff --git a/dom/html/test/test_bug512367.html b/dom/html/test/test_bug512367.html
new file mode 100644
index 000000000..be10345a9
--- /dev/null
+++ b/dom/html/test/test_bug512367.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=512367
+-->
+<head>
+ <title>Test for Bug 512367</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=512367">Mozilla Bug 512367</a>
+<p id="display">
+ <iframe src="bug369370-popup.png" id="i" style="width:200px; height:200px"></iframe>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+var frame = document.getElementById("i");
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ var viewer =
+ SpecialPowers.wrap(frame.contentWindow)
+ .QueryInterface(SpecialPowers.Ci.nsIInterfaceRequestor)
+ .getInterface(SpecialPowers.Ci.nsIWebNavigation)
+ .QueryInterface(SpecialPowers.Ci.nsIDocShell)
+ .contentViewer;
+
+ viewer.fullZoom = 1.5;
+
+ setTimeout(function() {
+ synthesizeMouse(frame, 30, 30, {});
+
+ is(viewer.fullZoom, 1.5, "Zoom in the image frame should not have been reset");
+
+ SimpleTest.finish();
+ }, 0);
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug514856.html b/dom/html/test/test_bug514856.html
new file mode 100644
index 000000000..50617bbba
--- /dev/null
+++ b/dom/html/test/test_bug514856.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=514856
+-->
+<head>
+ <title>Test for Bug 514856</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=514856">Mozilla Bug 514856</a>
+<p id="display"></p>
+<div id="content">
+ <iframe id="testFrame" src="bug514856_iframe.html"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 514856 **/
+
+function beginTest() {
+ var ifr = document.getElementById("testFrame");
+ var win = ifr.contentWindow;
+
+ // After the click, the load event should be fired.
+ ifr.addEventListener('load', function() {
+ testDone();
+ }, false);
+
+ // synthesizeMouse adds getBoundingClientRect left and top to the offsets but
+ // in that particular case, we don't want that.
+ var rect = ifr.getBoundingClientRect();
+ var left = rect.left;
+ var top = rect.top;
+
+ synthesizeMouse(ifr, 10 - left, 10 - top, { type: "mousemove" }, win);
+ synthesizeMouse(ifr, 12 - left, 12 - top, { type: "mousemove" }, win);
+ synthesizeMouse(ifr, 14 - left, 14 - top, { type: "mousemove" }, win);
+ synthesizeMouse(ifr, 16 - left, 16 - top, { }, win);
+}
+
+function testDone() {
+ var ifr = document.getElementById("testFrame");
+ var url = new String(ifr.contentWindow.location);
+
+ is(url.indexOf("?10,10"), -1, "Shouldn't have ?10,10 in the URL!");
+ is(url.indexOf("?12,12"), -1, "Shouldn't have ?12,12 in the URL!");
+ is(url.indexOf("?14,14"), -1, "Shouldn't have ?14,14 in the URL!");
+ isnot(url.indexOf("?16,16"), -1, "Should have ?16,16 in the URL!");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(beginTest);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug518122.html b/dom/html/test/test_bug518122.html
new file mode 100644
index 000000000..66e9a95a3
--- /dev/null
+++ b/dom/html/test/test_bug518122.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=518122
+-->
+<head>
+ <title>Test for Bug 518122</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=518122">Mozilla Bug 518122</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 518122 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTests);
+
+var simple_tests = [ ["foo", "foo"],
+ ["", ""],
+ [null, ""],
+ [undefined , "undefined"],
+ ["\n", "\n"],
+ ["\r", "\n"],
+ ["\rfoo", "\nfoo"],
+ ["foo\r", "foo\n"],
+ ["foo\rbar", "foo\nbar"],
+ ["foo\rbar\r", "foo\nbar\n"],
+ ["\r\n", "\n"],
+ ["\r\nfoo", "\nfoo"],
+ ["foo\r\n", "foo\n"],
+ ["foo\r\nbar", "foo\nbar"],
+ ["foo\r\nbar\r\n", "foo\nbar\n"] ];
+
+var value_append_tests = [ ["foo", "bar", "foobar"],
+ ["foo", "foo", "foofoo"],
+ ["foobar", "bar", "foobarbar"],
+ ["foobar", "foo", "foobarfoo"],
+ ["foo\n", "foo", "foo\nfoo"],
+ ["foo\r", "foo", "foo\nfoo"],
+ ["foo\r\n", "foo", "foo\nfoo"],
+ ["\n", "\n", "\n\n"],
+ ["\r", "\r", "\n\n"],
+ ["\r\n", "\r\n", "\n\n"],
+ ["\r", "\r\n", "\n\n"],
+ ["\r\n", "\r", "\n\n"],
+ [null, null, "null"],
+ [null, undefined, "undefined"],
+ ["", "", ""]
+ ];
+
+
+var simple_tests_for_input = [ ["foo", "foo"],
+ ["", ""],
+ [null, ""],
+ [undefined , "undefined"],
+ ["\n", ""],
+ ["\r", ""],
+ ["\rfoo", "foo"],
+ ["foo\r", "foo"],
+ ["foo\rbar", "foobar"],
+ ["foo\rbar\r", "foobar"],
+ ["\r\n", ""],
+ ["\r\nfoo", "foo"],
+ ["foo\r\n", "foo"],
+ ["foo\r\nbar", "foobar"],
+ ["foo\r\nbar\r\n", "foobar"] ];
+
+var value_append_tests_for_input = [ ["foo", "bar", "foobar"],
+ ["foo", "foo", "foofoo"],
+ ["foobar", "bar", "foobarbar"],
+ ["foobar", "foo", "foobarfoo"],
+ ["foo\n", "foo", "foofoo"],
+ ["foo\r", "foo", "foofoo"],
+ ["foo\r\n", "foo", "foofoo"],
+ ["\n", "\n", ""],
+ ["\r", "\r", ""],
+ ["\r\n", "\r\n", ""],
+ ["\r", "\r\n", ""],
+ ["\r\n", "\r", ""],
+ [null, null, "null"],
+ [null, undefined, "undefined"],
+ ["", "", ""]
+ ];
+function runTestsFor(el, simpleTests, appendTests) {
+ for(var i = 0; i < simpleTests.length; ++i) {
+ el.value = simpleTests[i][0];
+ is(el.value, simpleTests[i][1], "Wrong value (wrap=" + el.getAttribute('wrap') + ", simple_test=" + i + ")");
+ }
+ for (var j = 0; j < appendTests.length; ++j) {
+ el.value = appendTests[j][0];
+ el.value += appendTests[j][1];
+ is(el.value, appendTests[j][2], "Wrong value (wrap=" + el.getAttribute('wrap') + ", value_append_test=" + j + ")");
+ }
+}
+
+function runTests() {
+ var textareas = document.getElementsByTagName("textarea");
+ for (var i = 0; i < textareas.length; ++i) {
+ runTestsFor(textareas[i], simple_tests, value_append_tests);
+ }
+ var input = document.getElementsByTagName("input")[0];
+ runTestsFor(input, simple_tests_for_input, value_append_tests_for_input);
+ // initialize the editor
+ input.focus();
+ input.blur();
+ runTestsFor(input, simple_tests_for_input, value_append_tests_for_input);
+ SimpleTest.finish();
+}
+
+
+</script>
+</pre>
+<textarea cols="30" rows="7" wrap="none"></textarea>
+<textarea cols="30" rows="7" wrap="off"></textarea><br>
+<textarea cols="30" rows="7" wrap="soft"></textarea>
+<textarea cols="30" rows="7" wrap="hard"></textarea>
+<input type="text">
+</body>
+</html>
diff --git a/dom/html/test/test_bug519987.html b/dom/html/test/test_bug519987.html
new file mode 100644
index 000000000..a10d5e0b8
--- /dev/null
+++ b/dom/html/test/test_bug519987.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=519987
+-->
+<head>
+ <title>Test for Bug 519987</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=519987">Mozilla Bug 519987</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 519987 **/
+var xmlns = 'http://www.w3.org/1999/xhtml';
+is((new Image()).namespaceURI, xmlns, "Unexpected namespace for new Image()");
+is((new Audio()).namespaceURI, xmlns, "Unexpected namespace for new Audio()");
+var titles = document.getElementsByTagName("title");
+var t = titles[0];
+t.parentNode.removeChild(t);
+document.title = "abcdefg";
+is(titles[0].namespaceURI, xmlns, "Unexpected namespace for new <title>");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug523771.html b/dom/html/test/test_bug523771.html
new file mode 100644
index 000000000..80527ff93
--- /dev/null
+++ b/dom/html/test/test_bug523771.html
@@ -0,0 +1,106 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=523771
+-->
+<head>
+ <title>Test for Bug 523771</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=523771">Mozilla Bug 523771</a>
+<p id="display"></p>
+<iframe name="target_iframe" id="target_iframe"></iframe>
+<form action="form_submit_server.sjs" target="target_iframe" id="form"
+method="POST" enctype="multipart/form-data">
+ <input id=singleFile name=singleFile type=file>
+ <input id=multiFile name=multiFile type=file multiple>
+</form>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+singleFileInput = document.getElementById('singleFile');
+multiFileInput = document.getElementById('multiFile');
+var input1File = { name: "523771_file1", type: "", body: "file1 contents"};
+var input2Files =
+ [{ name: "523771_file2", type: "", body: "second file contents" },
+ { name: "523771_file3.txt", type: "text/plain", body: "123456" },
+ { name: "523771_file4.html", type: "text/html", body: "<html>content</html>" }
+ ];
+
+SimpleTest.waitForExplicitFinish();
+
+function setFileInputs () {
+ var f = createFileWithData(input1File.name, input1File.body, input1File.type);
+ SpecialPowers.wrap(singleFileInput).mozSetFileArray([f]);
+
+ var input2FileNames = [];
+ for (file of input2Files) {
+ f = createFileWithData(file.name, file.body, file.type);
+ input2FileNames.push(f);
+ }
+ SpecialPowers.wrap(multiFileInput).mozSetFileArray(input2FileNames);
+}
+
+function createFileWithData(fileName, fileData, fileType) {
+ return new File([fileData], fileName, { type: fileType });
+}
+
+function cleanupFiles() {
+ singleFileInput.value = "";
+ multiFileInput.value = "";
+}
+
+is(singleFileInput.files.length, 0, "single-file .files.length"); // bug 524421
+is(multiFileInput.files.length, 0, "multi-file .files.length"); // bug 524421
+
+setFileInputs();
+
+is(singleFileInput.multiple, false, "single-file input .multiple");
+is(multiFileInput.multiple, true, "multi-file input .multiple");
+is(singleFileInput.value, input1File.name, "single-file input .value");
+is(multiFileInput.value, input2Files[0].name, "multi-file input .value");
+is(singleFileInput.files[0].name, input1File.name, "single-file input .files[n].name");
+is(singleFileInput.files[0].size, input1File.body.length, "single-file input .files[n].size");
+is(singleFileInput.files[0].type, input1File.type, "single-file input .files[n].type");
+for(i = 0; i < input2Files.length; ++i) {
+ is(multiFileInput.files[i].name, input2Files[i].name, "multi-file input .files[n].name");
+ is(multiFileInput.files[i].size, input2Files[i].body.length, "multi-file input .files[n].size");
+ is(multiFileInput.files[i].type, input2Files[i].type, "multi-file input .files[n].type");
+}
+
+document.getElementById('form').submit();
+iframe = document.getElementById('target_iframe');
+iframe.onload = function() {
+ response = JSON.parse(iframe.contentDocument.documentElement.textContent);
+ is(response[0].headers["Content-Disposition"],
+ "form-data; name=\"singleFile\"; filename=\"" + input1File.name +
+ "\"",
+ "singleFile Content-Disposition");
+ is(response[0].headers["Content-Type"], input1File.type || "application/octet-stream",
+ "singleFile Content-Type");
+ is(response[0].body, input1File.body, "singleFile body");
+
+ for(i = 0; i < input2Files.length; ++i) {
+ is(response[i + 1].headers["Content-Disposition"],
+ "form-data; name=\"multiFile\"; filename=\"" + input2Files[i].name +
+ "\"",
+ "multiFile Content-Disposition");
+ is(response[i + 1].headers["Content-Type"], input2Files[i].type || "application/octet-stream",
+ "multiFile Content-Type");
+ is(response[i + 1].body, input2Files[i].body, "multiFile body");
+ }
+
+ cleanupFiles();
+
+ is(singleFileInput.files.length, 0, "single-file .files.length"); // bug 524421
+ is(multiFileInput.files.length, 0, "multi-file .files.length"); // bug 524421
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug529819.html b/dom/html/test/test_bug529819.html
new file mode 100644
index 000000000..e744587a6
--- /dev/null
+++ b/dom/html/test/test_bug529819.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=529819
+-->
+<head>
+ <title>Test for Bug 529819</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529819">Mozilla Bug 529819</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<form id="form">
+ <input name="foo" id="foo">
+ <input name="bar" type="radio">
+ <input name="bar" id="bar" type="radio">
+</form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 529819 **/
+is($("form").elements["foo"] instanceof HTMLInputElement, true, "Should have an element here");
+is($("form").elements["bar"] instanceof HTMLInputElement, false, "Should have a list here");
+is($("form").elements["bar"].length, 2, "Should have a list with two elements here");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug529859.html b/dom/html/test/test_bug529859.html
new file mode 100644
index 000000000..282a5c060
--- /dev/null
+++ b/dom/html/test/test_bug529859.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=529859
+-->
+<head>
+ <title>Test for Bug 529859</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=529859">Mozilla Bug 529859</a>
+<div id="content">
+ <iframe name="target_iframe" id="target_iframe"></iframe>
+ <form action="form_submit_server.sjs" target="target_iframe" id="form"
+ method="POST" enctype="multipart/form-data">
+ <input id="emptyFileInput" name="emptyFileInput" type="file">
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 529859 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ $("target_iframe").onload = function() {
+ var response = JSON.parse(this.contentDocument.documentElement.textContent);
+ is(response.length, 1, "Unexpected number of inputs");
+ is(response[0].headers["Content-Disposition"],
+ "form-data; name=\"emptyFileInput\"; filename=\"\"",
+ "Incorrect content-disposition");
+ is(response[0].headers["Content-Type"], "application/octet-stream",
+ "Unexpected content-type");
+ SimpleTest.finish();
+ }
+ $("form").submit();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug535043.html b/dom/html/test/test_bug535043.html
new file mode 100644
index 000000000..0123c4c2f
--- /dev/null
+++ b/dom/html/test/test_bug535043.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=535043
+-->
+<head>
+ <title>Test for Bug 535043</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=535043">Mozilla Bug 535043</a>
+<p id="display"></p>
+<div id="content">
+ <textarea></textarea>
+ <textarea maxlength="-1"></textarea>
+ <textarea maxlength="0"></textarea>
+ <textarea maxlength="2"></textarea>
+</div>
+<pre id="test">
+<script type="text/javascript">
+
+/** Test for Bug 535043 **/
+function checkTextArea(textArea) {
+ textArea.value = '';
+ textArea.focus();
+ for (var j = 0; j < 3; j++) {
+ synthesizeKey('x', {});
+ }
+ var htmlMaxLength = textArea.getAttribute('maxlength');
+ var domMaxLength = textArea.maxLength;
+ if (htmlMaxLength == null) {
+ is(domMaxLength, -1,
+ 'maxlength is unset but maxLength DOM attribute is not -1');
+ } else if (htmlMaxLength < 0) {
+ // Per the HTML5 spec, out-of-range values are supposed to translate to -1,
+ // not 0, but they don't?
+ is(domMaxLength, -1,
+ 'maxlength is out of range but maxLength DOM attribute is not -1');
+ } else {
+ is(domMaxLength, parseInt(htmlMaxLength),
+ 'maxlength in DOM does not match provided value');
+ }
+ if (textArea.maxLength == -1) {
+ is(textArea.value.length, 3,
+ 'textarea with maxLength -1 should have no length limit');
+ } else {
+ is(textArea.value.length, textArea.maxLength, 'textarea has maxLength ' +
+ textArea.maxLength + ' but length ' + textArea.value.length );
+ }
+}
+
+SimpleTest.waitForFocus(function() {
+ var textAreas = document.getElementsByTagName('textarea');
+ for (var i = 0; i < textAreas.length; i++) {
+ checkTextArea(textAreas[i]);
+ }
+
+ textArea = textAreas[0];
+ testNums = [-42, -1, 0, 2];
+ for (var i = 0; i < testNums.length; i++) {
+ textArea.removeAttribute('maxlength');
+
+ var caught = false;
+ try {
+ textArea.maxLength = testNums[i];
+ } catch (e) {
+ caught = true;
+ }
+ if (testNums[i] < 0) {
+ ok(caught, 'Setting negative maxLength should throw exception');
+ } else {
+ ok(!caught, 'Setting nonnegative maxLength should not throw exception');
+ }
+ checkTextArea(textArea);
+
+ textArea.setAttribute('maxlength', testNums[i]);
+ checkTextArea(textArea);
+ }
+
+ SimpleTest.finish();
+});
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug536891.html b/dom/html/test/test_bug536891.html
new file mode 100644
index 000000000..8fbfe0bc2
--- /dev/null
+++ b/dom/html/test/test_bug536891.html
@@ -0,0 +1,67 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=536891
+-->
+<head>
+ <title>Test for Bug 536891</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=536891">Mozilla Bug 536891</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<textarea id="t" maxlength="-2" minlength="-2"></textarea>
+<input id="i" type="text" maxlength="-2" minlength="-2">
+<input id="p" type="password" maxlength="-2" minlength="-2">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 536891 **/
+
+function checkNegativeMinMaxLength(element)
+{
+ for(let type of ["min", "max"]) {
+ /* value is set to -2 initially in the document, see above */
+ is(element[type + "Length"], -1, "negative " + type + "Length should be considered invalid and represented as -1");
+
+ // changing the property to an negative value should throw (see bug 536895).
+ for(let value of [-15, -2147483648]) { // PR_INT32_MIN
+ let threw = false;
+ try {
+ element[type + "Length"] = value;
+ } catch(e) {
+ threw = true;
+ }
+ is(threw, true, "setting " + type + "Length property to " + value + " should throw");
+ }
+ element[type + "Length"] = "non-numerical value";
+ is(element[type + "Length"], 0, "setting " + type + "Length property to a non-numerical value should set it to zero");
+
+
+ element.setAttribute(type + 'Length', -15);
+ is(element[type + "Length"], -1, "negative " + type + "Length is not processed correctly when set dynamically");
+ is(element.getAttribute(type + 'Length'), "-15", type + "Length attribute doesn't return the correct value");
+
+ element.setAttribute(type + 'Length', 0);
+ is(element[type + "Length"], 0, "zero " + type + "Length is not processed correctly");
+ element.setAttribute(type + 'Length', 2147483647); // PR_INT32_MAX
+ is(element[type + "Length"], 2147483647, "negative " + type + "Length is not processed correctly");
+ element.setAttribute(type + 'Length', -2147483648); // PR_INT32_MIN
+ is(element[type + "Length"], -1, "negative " + type + "Length is not processed correctly");
+ element.setAttribute(type + 'Length', 'non-numerical-value');
+ is(element[type + "Length"], -1, "non-numerical value should be considered invalid and represented as -1");
+ }
+}
+
+/* TODO: correct behavior may be checked for email, telephone, url and search input types */
+checkNegativeMinMaxLength(document.getElementById('t'));
+checkNegativeMinMaxLength(document.getElementById('i'));
+checkNegativeMinMaxLength(document.getElementById('p'));
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug536895.html b/dom/html/test/test_bug536895.html
new file mode 100644
index 000000000..7ff5bedb1
--- /dev/null
+++ b/dom/html/test/test_bug536895.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=536895
+-->
+<head>
+ <title>Test for Bug 536895</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=536895">Mozilla Bug 536895</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<textarea id="t"></textarea>
+<input id="i" type="text">
+<input id="p" type="password">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 536895 **/
+
+function checkNegativeMaxLengthException(element)
+{
+ caught = false;
+ try {
+ element.setAttribute('maxLength', -10);
+ } catch(e) {
+ caught = true;
+ }
+ ok(!caught, "Setting maxLength attribute to a negative value shouldn't throw an exception");
+
+ caught = false;
+ try {
+ element.maxLength = -20;
+ } catch(e) {
+ is(e.name, "IndexSizeError", "Should be an IndexSizeError exception");
+ caught = true;
+ }
+ ok(caught, "Setting negative maxLength from the DOM should throw an exception");
+
+ is(element.getAttribute('maxLength'), "-10", "When the exception is raised, the maxLength attribute shouldn't change");
+}
+
+/* TODO: correct behavior may be checked for email, telephone, url and search input types */
+checkNegativeMaxLengthException(document.getElementById('t'));
+checkNegativeMaxLengthException(document.getElementById('i'));
+checkNegativeMaxLengthException(document.getElementById('p'));
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug546995.html b/dom/html/test/test_bug546995.html
new file mode 100644
index 000000000..0135da601
--- /dev/null
+++ b/dom/html/test/test_bug546995.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=546995
+-->
+<head>
+ <title>Test for Bug 546995</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=546995">Mozilla Bug 546995</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <select id='s'></select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 546995 **/
+
+/* This test in only testing IDL reflection, another one is testing the behavior */
+
+function checkAutofocusIDLAttribute(element)
+{
+ ok('autofocus' in element, "Element has the autofocus IDL attribute");
+ ok(!element.autofocus, "autofocus default value is false");
+ element.setAttribute('autofocus', 'autofocus');
+ ok(element.autofocus, "autofocus should be enabled");
+ element.removeAttribute('autofocus');
+ ok(!element.autofocus, "autofocus should be disabled");
+}
+
+// TODO: keygen should be added when correctly implemented, see bug 101019.
+checkAutofocusIDLAttribute(document.getElementById('s'));
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug547850.html b/dom/html/test/test_bug547850.html
new file mode 100644
index 000000000..977366518
--- /dev/null
+++ b/dom/html/test/test_bug547850.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=547850
+-->
+<head>
+ <title>Test for Bug 547850</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=547850">Mozilla Bug 547850</a>
+<script>
+document.write("<div id=content><f\u00c5></f\u00c5><r\u00e5></r\u00e5>");
+document.write("<span g\u00c5=a1 t\u00e5=a2></span></div>");
+</script>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+var ch = $('content').childNodes;
+is(ch[0].localName, "f\u00c5", "upper case localName");
+is(ch[1].localName, "r\u00e5", "lower case localName");
+is(ch[0].nodeName, "F\u00c5", "upper case nodeName");
+is(ch[1].nodeName, "R\u00e5", "lower case nodeName");
+is(ch[0].tagName, "F\u00c5", "upper case tagName");
+is(ch[1].tagName, "R\u00e5", "lower case tagName");
+is(ch[2].getAttribute("g\u00c5"), "a1", "upper case attr name");
+is(ch[2].getAttribute("t\u00e5"), "a2", "lower case attr name");
+is(ch[2].getAttribute("G\u00c5"), "a1", "upper case attr name");
+is(ch[2].getAttribute("T\u00e5"), "a2", "lower case attr name");
+is(ch[2].getAttribute("g\u00e5"), null, "wrong lower case attr name");
+is(ch[2].getAttribute("t\u00c5"), null, "wrong upper case attr name");
+is($('content').getElementsByTagName("f\u00c5")[0], ch[0], "gEBTN upper case");
+is($('content').getElementsByTagName("f\u00c5").length, 1, "gEBTN upper case length");
+is($('content').getElementsByTagName("r\u00e5")[0], ch[1], "gEBTN lower case");
+is($('content').getElementsByTagName("r\u00e5").length, 1, "gEBTN lower case length");
+is($('content').getElementsByTagName("F\u00c5")[0], ch[0], "gEBTN upper case");
+is($('content').getElementsByTagName("F\u00c5").length, 1, "gEBTN upper case length");
+is($('content').getElementsByTagName("R\u00e5")[0], ch[1], "gEBTN lower case");
+is($('content').getElementsByTagName("R\u00e5").length, 1, "gEBTN lower case length");
+is($('content').getElementsByTagName("f\u00e5").length, 0, "gEBTN wrong upper case");
+is($('content').getElementsByTagName("r\u00c5").length, 0, "gEBTN wrong lower case");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug551846.html b/dom/html/test/test_bug551846.html
new file mode 100644
index 000000000..e528e5a16
--- /dev/null
+++ b/dom/html/test/test_bug551846.html
@@ -0,0 +1,164 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=551846
+-->
+<head>
+ <title>Test for Bug 551846</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=551846">Mozilla Bug 551846</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <select id='s'>
+ <option>Tulip</option>
+ <option>Lily</option>
+ <option>Gagea</option>
+ <option>Snowflake</option>
+ <option>Ismene</option>
+ </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 551846 **/
+
+function checkSizeReflection(element, defaultValue)
+{
+ is(element.size, defaultValue, "Default size should be " + defaultValue);
+
+ element.setAttribute('size', -15);
+ is(element.size, defaultValue,
+ "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+ is(element.getAttribute('size'), "-15",
+ "The content attribute should containt the previously set value");
+
+ element.setAttribute('size', 0);
+ is(element.size, 0,
+ "0 should be considered as a valid value");
+ is(element.getAttribute('size'), "0",
+ "The content attribute should containt the previously set value");
+
+ element.setAttribute('size', 2147483647); /* PR_INT32_MAX */
+ is(element.size, 2147483647,
+ "PR_INT32_MAX should be considered as a valid value");
+ is(element.getAttribute('size'), "2147483647",
+ "The content attribute should containt the previously set value");
+
+ element.setAttribute('size', -2147483648); /* PR_INT32_MIN */
+ is(element.size, defaultValue,
+ "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+ is(element.getAttribute('size'), "-2147483648",
+ "The content attribute should containt the previously set value");
+
+ element.setAttribute('size', 'non-numerical-value');
+ is(element.size, defaultValue,
+ "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+ is(element.getAttribute('size'), 'non-numerical-value',
+ "The content attribute should containt the previously set value");
+
+ element.setAttribute('size', 4294967294); /* PR_INT32_MAX * 2 */
+ is(element.size, defaultValue,
+ "Value greater than PR_INT32_MAX should be considered as invalid");
+ is(element.getAttribute('size'), "4294967294",
+ "The content attribute should containt the previously set value");
+
+ element.setAttribute('size', -4294967296); /* PR_INT32_MIN * 2 */
+ is(element.size, defaultValue,
+ "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+ is(element.getAttribute('size'), "-4294967296",
+ "The content attribute should containt the previously set value");
+
+ element.size = defaultValue + 1;
+ element.removeAttribute('size');
+ is(element.size, defaultValue,
+ "When the attribute is removed, the size should be the default size");
+
+ element.setAttribute('size', 'foobar');
+ is(element.size, defaultValue,
+ "The reflecting IDL attribute should return the default value when content attribute value is invalid");
+ element.removeAttribute('size');
+ is(element.size, defaultValue,
+ "When the attribute is removed, the size should be the default size");
+}
+
+function checkSetSizeException(element)
+{
+ var caught = false;
+
+ try {
+ element.size = 1;
+ } catch(e) {
+ caught = true;
+ }
+ ok(!caught, "Setting a positive size shouldn't throw an exception");
+
+ caught = false;
+ try {
+ element.size = 0;
+ } catch(e) {
+ caught = true;
+ }
+ ok(!caught, "Setting a size to 0 from the IDL shouldn't throw an exception");
+
+ element.size = 1;
+
+ caught = false;
+ try {
+ element.size = -1;
+ } catch(e) {
+ caught = true;
+ }
+ ok(!caught, "Setting a negative size from the IDL shouldn't throw an exception");
+
+ is(element.size, 0, "The size should now be equal to the minimum non-negative value");
+
+ caught = false;
+ try {
+ element.setAttribute('size', -10);
+ } catch(e) {
+ caught = true;
+ }
+ ok(!caught, "Setting an invalid size in the content attribute shouldn't throw an exception");
+
+ // reverting to defalut
+ element.removeAttribute('size');
+}
+
+function checkSizeWhenChangeMultiple(element, aDefaultNonMultiple, aDefaultMultiple)
+{
+ s.setAttribute('size', -1)
+ is(s.size, aDefaultNonMultiple, "Size IDL attribute should be 1");
+
+ s.multiple = true;
+ is(s.size, aDefaultMultiple, "Size IDL attribute should be 4");
+
+ is(s.getAttribute('size'), "-1", "Size content attribute should be -1");
+
+ s.setAttribute('size', -2);
+ is(s.size, aDefaultMultiple, "Size IDL attribute should be 4");
+
+ s.multiple = false;
+ is(s.size, aDefaultNonMultiple, "Size IDL attribute should be 1");
+
+ is(s.getAttribute('size'), "-2", "Size content attribute should be -2");
+}
+
+var s = document.getElementById('s');
+
+checkSizeReflection(s, 0);
+checkSetSizeException(s);
+
+s.setAttribute('multiple', 'true');
+checkSizeReflection(s, 0);
+checkSetSizeException(s);
+s.removeAttribute('multiple');
+
+checkSizeWhenChangeMultiple(s, 0, 0);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug555567.html b/dom/html/test/test_bug555567.html
new file mode 100644
index 000000000..04c82147c
--- /dev/null
+++ b/dom/html/test/test_bug555567.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=555567
+-->
+<head>
+ <title>Test for Bug 555567</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=555567">Mozilla Bug 555567</a>
+<div id='content' style="display: none">
+ <form>
+ <fieldset>
+ <legend id="a"></legend>
+ </fieldset>
+ <legend id="b"></legend>
+ </form>
+ <legend id="c"></legend>
+</div>
+<pre id="test">
+<p id="display"></p>
+<script type="application/javascript">
+
+/** Test for Bug 555567 **/
+
+var a = document.getElementById('a');
+var b = document.getElementById('b');
+var c = document.getElementById('c');
+
+isnot(a.form, null,
+ "First legend element should have a not null form IDL attribute");
+is(b.form, null,
+ "Second legend element should have a null form IDL attribute");
+is(c.form, null,
+ "Third legend element should have a null form IDL attribute");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug556645.html b/dom/html/test/test_bug556645.html
new file mode 100644
index 000000000..449f956a6
--- /dev/null
+++ b/dom/html/test/test_bug556645.html
@@ -0,0 +1,50 @@
+<html>
+<head>
+ <title>Test for Bug 556645</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<script>
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+
+function runTest()
+{
+ var obj = document.getElementById("obj");
+ var childDoc = obj.contentDocument;
+ var body = childDoc.body;
+ is(document.activeElement, document.body, "focus in parent before");
+ is(childDoc.activeElement, body, "focus in child before");
+
+ var button = childDoc.getElementsByTagName("button")[0];
+ button.focus();
+ childDoc.defaultView.focus();
+ is(document.activeElement, obj, "focus in parent after focus()");
+ is(childDoc.activeElement, button, "focus in child after focus()");
+
+ button.blur();
+ var pbutton = document.getElementById("pbutton");
+ pbutton.focus();
+
+ synthesizeKey("VK_TAB", { });
+ is(document.activeElement, obj, "focus in parent after tab");
+ is(childDoc.activeElement, childDoc.documentElement, "focus in child after tab");
+
+ synthesizeKey("VK_TAB", { });
+ is(document.activeElement, obj, "focus in parent after tab 2");
+ is(childDoc.activeElement, button, "focus in child after tab 2");
+
+ SimpleTest.finish();
+}
+
+</script>
+
+<button id="pbutton">Parent</button>
+<object id="obj" type="text/html"
+ data="data:text/html,%3Cbody%3E%3Cbutton%3EChild%3C/button%3E%3C/body%3E"
+ width="200" height="200"></object>
+
+</body>
+</html>
diff --git a/dom/html/test/test_bug557087-1.html b/dom/html/test/test_bug557087-1.html
new file mode 100644
index 000000000..32e36e59d
--- /dev/null
+++ b/dom/html/test/test_bug557087-1.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=557087
+-->
+<head>
+ <title>Test for Bug 557087</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 557087 **/
+
+function checkDisabledAttribute(aFieldset)
+{
+ ok('disabled' in aFieldset,
+ "fieldset elements should have the disabled attribute");
+
+ ok(!aFieldset.disabled,
+ "fieldset elements disabled attribute should be disabled");
+ is(aFieldset.getAttribute('disabled'), null,
+ "fieldset elements disabled attribute should be disabled");
+
+ aFieldset.disabled = true;
+ ok(aFieldset.disabled,
+ "fieldset elements disabled attribute should be enabled");
+ isnot(aFieldset.getAttribute('disabled'), null,
+ "fieldset elements disabled attribute should be enabled");
+
+ aFieldset.removeAttribute('disabled');
+ aFieldset.setAttribute('disabled', '');
+ ok(aFieldset.disabled,
+ "fieldset elements disabled attribute should be enabled");
+ isnot(aFieldset.getAttribute('disabled'), null,
+ "fieldset elements disabled attribute should be enabled");
+
+ aFieldset.removeAttribute('disabled');
+ ok(!aFieldset.disabled,
+ "fieldset elements disabled attribute should be disabled");
+ is(aFieldset.getAttribute('disabled'), null,
+ "fieldset elements disabled attribute should be disabled");
+}
+
+function checkDisabledPseudoClass(aFieldset)
+{
+ is(document.querySelector(":disabled"), null,
+ "no elements should have :disabled applied to them");
+
+ aFieldset.disabled = true;
+ is(document.querySelector(":disabled"), aFieldset,
+ ":disabled should apply to fieldset elements");
+
+ aFieldset.disabled = false;
+ is(document.querySelector(":disabled"), null,
+ "no elements should have :disabled applied to them");
+}
+
+function checkEnabledPseudoClass(aFieldset)
+{
+ is(document.querySelector(":enabled"), aFieldset,
+ ":enabled should apply to fieldset elements");
+
+ aFieldset.disabled = true;
+ is(document.querySelector(":enabled"), null,
+ "no elements should have :enabled applied to them");
+
+ aFieldset.disabled = false;
+ is(document.querySelector(":enabled"), aFieldset,
+ ":enabled should apply to fieldset elements");
+}
+
+function checkFocus(aFieldset)
+{
+ aFieldset.disabled = true;
+ aFieldset.setAttribute('tabindex', 1);
+
+ aFieldset.focus();
+
+ isnot(document.activeElement, aFieldset,
+ "fieldset can't be focused when disabled");
+ aFieldset.removeAttribute('tabindex');
+ aFieldset.disabled = false;
+}
+
+function checkClickEvent(aFieldset)
+{
+ var clickHandled = false;
+
+ aFieldset.disabled = true;
+
+ aFieldset.addEventListener("click", function(aEvent) {
+ aEvent.target.removeEventListener("click", arguments.callee, false);
+ clickHandled = true;
+ }, false);
+
+ sendMouseEvent({type:'click'}, aFieldset);
+ SimpleTest.executeSoon(function() {
+ ok(!clickHandled, "When disabled, fieldset should prevent click events");
+ SimpleTest.finish();
+ });
+}
+
+SimpleTest.waitForExplicitFinish();
+
+var fieldset = document.createElement("fieldset");
+var content = document.getElementById('content');
+content.appendChild(fieldset);
+
+checkDisabledAttribute(fieldset);
+checkDisabledPseudoClass(fieldset);
+checkEnabledPseudoClass(fieldset);
+checkFocus(fieldset);
+checkClickEvent(fieldset);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug557087-2.html b/dom/html/test/test_bug557087-2.html
new file mode 100644
index 000000000..923a136c5
--- /dev/null
+++ b/dom/html/test/test_bug557087-2.html
@@ -0,0 +1,359 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=557087
+-->
+<head>
+ <title>Test for Bug 557087</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a>
+<p id="display"></p>
+<div id="content" style="display:none;">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 557087 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var elementsPreventingClick = [ "input", "button", "select", "textarea", "fieldset" ];
+var elementsWithClick = [ "option", "optgroup", "output", "label", "object" ];
+var gHandled = 0;
+
+function clickShouldNotHappenHandler(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldNotHappenHandler, false);
+ ok(false, "click event should be prevented! (test1)");
+ if (++gHandled >= elementsWithClick.length) {
+ test2();
+ }
+}
+
+function clickShouldNotHappenHandler2(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldNotHappenHandler3, false);
+ ok(false, "click event should be prevented! (test2)");
+ if (++gHandled >= elementsWithClick.length) {
+ test3();
+ }
+}
+
+function clickShouldNotHappenHandler5(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldNotHappenHandler5, false);
+ ok(false, "click event should be prevented! (test5)");
+ if (++gHandled >= elementsWithClick.length) {
+ test6();
+ }
+}
+
+function clickShouldNotHappenHandler7(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldNotHappenHandler7, false);
+ ok(false, "click event should be prevented! (test7)");
+ if (++gHandled >= elementsWithClick.length) {
+ test8();
+ }
+}
+
+function clickShouldHappenHandler(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldHappenHandler, false);
+ ok(true, "click event has been correctly received (test1)");
+ if (++gHandled >= elementsWithClick.length) {
+ test2();
+ }
+}
+
+function clickShouldHappenHandler2(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldHappenHandler2, false);
+ ok(true, "click event has been correctly received (test2)");
+ if (++gHandled >= elementsWithClick.length) {
+ test3();
+ }
+}
+
+function clickShouldHappenHandler3(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldHappenHandler3, false);
+ ok(true, "click event has been correctly received (test3)");
+ if (++gHandled >= (elementsWithClick.length +
+ elementsPreventingClick.length)) {
+ test4();
+ }
+}
+
+function clickShouldHappenHandler4(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldHappenHandler4, false);
+ ok(true, "click event has been correctly received (test4)");
+ if (++gHandled >= (elementsWithClick.length +
+ elementsPreventingClick.length)) {
+ test5();
+ }
+}
+
+function clickShouldHappenHandler5(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldHappenHandler5, false);
+ ok(true, "click event has been correctly received (test5)");
+ if (++gHandled >= elementsWithClick.length) {
+ test6();
+ }
+}
+
+function clickShouldHappenHandler6(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldHappenHandler6, false);
+ ok(true, "click event has been correctly received (test6)");
+ if (++gHandled >= (elementsWithClick.length +
+ elementsPreventingClick.length)) {
+ test7();
+ }
+}
+
+function clickShouldHappenHandler7(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldHappenHandler7, false);
+ ok(true, "click event has been correctly received (test5)");
+ if (++gHandled >= elementsWithClick.length) {
+ test8();
+ }
+}
+
+function clickShouldHappenHandler8(aEvent)
+{
+ aEvent.target.removeEventListener("click", clickShouldHappenHandler8, false);
+ ok(true, "click event has been correctly received (test8)");
+ if (++gHandled >= (elementsWithClick.length +
+ elementsPreventingClick.length)) {
+ SimpleTest.finish();
+ }
+}
+
+var fieldset1 = document.createElement("fieldset");
+var fieldset2 = document.createElement("fieldset");
+var legendA = document.createElement("legend");
+var legendB = document.createElement("legend");
+var content = document.getElementById('content');
+fieldset1.disabled = true;
+content.appendChild(fieldset1);
+fieldset1.appendChild(fieldset2);
+
+function clean()
+{
+ var count = fieldset2.children.length;
+ for (var i=0; i<count; ++i) {
+ if (fieldset2.children[i] != legendA &&
+ fieldset2.children[i] != legendB) {
+ fieldset2.removeChild(fieldset2.children[i]);
+ }
+ }
+}
+
+function test1()
+{
+ gHandled = 0;
+
+ // Initialize children without click expected.
+ for (var name of elementsPreventingClick) {
+ var element = document.createElement(name);
+ fieldset2.appendChild(element);
+ element.addEventListener("click", clickShouldNotHappenHandler, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+
+ // Initialize children with click expected.
+ for (var name of elementsWithClick) {
+ var element = document.createElement(name);
+ fieldset2.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+}
+
+function test2()
+{
+ gHandled = 0;
+ fieldset1.disabled = false;
+ fieldset2.disabled = true;
+
+ // Initialize children without click expected.
+ for (var name of elementsPreventingClick) {
+ var element = document.createElement(name);
+ fieldset2.appendChild(element);
+ element.addEventListener("click", clickShouldNotHappenHandler2, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+
+ // Initialize children with click expected.
+ for (var name of elementsWithClick) {
+ var element = document.createElement(name);
+ fieldset2.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler2, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+}
+
+function test3()
+{
+ gHandled = 0;
+ fieldset1.disabled = false;
+ fieldset2.disabled = false;
+
+ // All elements should accept the click.
+ for (var name of elementsPreventingClick) {
+ var element = document.createElement(name);
+ fieldset2.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler3, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+
+ // Initialize children with click expected.
+ for (var name of elementsWithClick) {
+ var element = document.createElement(name);
+ fieldset2.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler3, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+}
+
+function test4()
+{
+ gHandled = 0;
+ fieldset1.disabled = false;
+ fieldset2.disabled = true;
+
+ fieldset2.appendChild(legendA);
+
+ // All elements should accept the click.
+ for (var name of elementsPreventingClick) {
+ var element = document.createElement(name);
+ legendA.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler4, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+
+ // Initialize children with click expected.
+ for (var name of elementsWithClick) {
+ var element = document.createElement(name);
+ legendA.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler4, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+}
+
+function test5()
+{
+ gHandled = 0;
+ fieldset2.insertBefore(legendB, legendA);
+
+ // Initialize children without click expected.
+ for (var name of elementsPreventingClick) {
+ var element = document.createElement(name);
+ legendA.appendChild(element);
+ element.addEventListener("click", clickShouldNotHappenHandler5, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+
+ // Initialize children with click expected.
+ for (var name of elementsWithClick) {
+ var element = document.createElement(name);
+ legendA.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler5, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+}
+
+function test6()
+{
+ gHandled = 0;
+ fieldset2.removeChild(legendB);
+ fieldset1.disabled = true;
+ fieldset2.disabled = false;
+
+ fieldset1.appendChild(legendA);
+ legendA.appendChild(fieldset2);
+
+ // All elements should accept the click.
+ for (var name of elementsPreventingClick) {
+ var element = document.createElement(name);
+ fieldset2.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler6, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+
+ // Initialize children with click expected.
+ for (var name of elementsWithClick) {
+ var element = document.createElement(name);
+ fieldset2.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler6, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+}
+
+function test7()
+{
+ gHandled = 0;
+ fieldset1.disabled = true;
+ fieldset2.disabled = false;
+
+ fieldset1.appendChild(fieldset2);
+ fieldset2.appendChild(legendA);
+
+ // All elements should accept the click.
+ for (var name of elementsPreventingClick) {
+ var element = document.createElement(name);
+ legendA.appendChild(element);
+ element.addEventListener("click", clickShouldNotHappenHandler7, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+
+ // Initialize children with click expected.
+ for (var name of elementsWithClick) {
+ var element = document.createElement(name);
+ legendA.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler7, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+}
+
+function test8()
+{
+ gHandled = 0;
+ fieldset1.disabled = true;
+ fieldset2.disabled = true;
+
+ fieldset1.appendChild(legendA);
+ legendA.appendChild(fieldset2);
+ fieldset2.appendChild(legendB);
+
+ // All elements should accept the click.
+ for (var name of elementsPreventingClick) {
+ var element = document.createElement(name);
+ legendB.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler8, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+
+ // Initialize children with click expected.
+ for (var name of elementsWithClick) {
+ var element = document.createElement(name);
+ legendB.appendChild(element);
+ element.addEventListener("click", clickShouldHappenHandler8, false);
+ sendMouseEvent({type:'click'}, element);
+ }
+}
+
+test1();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug557087-3.html b/dom/html/test/test_bug557087-3.html
new file mode 100644
index 000000000..166007c49
--- /dev/null
+++ b/dom/html/test/test_bug557087-3.html
@@ -0,0 +1,215 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=557087
+-->
+<head>
+ <title>Test for Bug 557087</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 557087 **/
+
+function checkValueMissing(aElement, aExpected)
+{
+ var msg = aExpected ? aElement.tagName + " should suffer from value missing"
+ : aElement.tagName + " should not suffer from value missing"
+ is(aElement.validity.valueMissing, aExpected, msg);
+}
+
+function checkCandidateForConstraintValidation(aElement, aExpected)
+{
+ var msg = aExpected ? aElement.tagName + " should be candidate for constraint validation"
+ : aElement.tagName + " should not be candidate for constraint validation"
+ is(aElement.willValidate, aExpected, msg);
+}
+
+function checkDisabledPseudoClass(aElement, aDisabled)
+{
+ var disabledElements = document.querySelectorAll(":disabled");
+ var found = false;
+
+ for (var e of disabledElements) {
+ if (aElement == e) {
+ found = true;
+ break;
+ }
+ }
+
+ var msg = aDisabled ? aElement.tagName + " should have :disabled applying"
+ : aElement.tagName + " should not have :disabled applying";
+ ok(aDisabled ? found : !found, msg);
+}
+
+function checkEnabledPseudoClass(aElement, aEnabled)
+{
+ var enabledElements = document.querySelectorAll(":enabled");
+ var found = false;
+
+ for (var e of enabledElements) {
+ if (aElement == e) {
+ found = true;
+ break;
+ }
+ }
+
+ var msg = aEnabled ? aElement.tagName + " should have :enabled applying"
+ : aElement.tagName + " should not have :enabled applying";
+ ok(aEnabled ? found : !found, msg);
+}
+
+function checkFocus(aElement, aExpected)
+{
+ aElement.setAttribute('tabindex', 1);
+
+ // We use the focus manager so we can test <label>.
+ var fm = SpecialPowers.Cc["@mozilla.org/focus-manager;1"]
+ .getService(SpecialPowers.Ci.nsIFocusManager);
+ fm.setFocus(aElement, 0);
+
+ if (aExpected) {
+ is(document.activeElement, aElement, "element should be focused");
+ } else {
+ isnot(document.activeElement, aElement, "element should not be focused");
+ }
+
+ aElement.blur();
+ aElement.removeAttribute('tabindex');
+}
+
+var elements = [ "input", "button", "select", "textarea", "fieldset", "option",
+ "optgroup", "label", "output", "object" ];
+
+var testData = {
+/* tag name | affected by disabled | test focus | test pseudo-classes | test willValidate */
+ "INPUT": [ true, true, true, true, true ],
+ "BUTTON": [ true, true, true, false, false ],
+ "SELECT": [ true, true, true, true, false ],
+ "TEXTAREA": [ true, true, true, true, true ],
+ "FIELDSET": [ true, true, true, false, false ],
+ "OPTION": [ false, true, true, false, false ],
+ "OPTGROUP": [ false, true, true, false, false ],
+ "OBJECT": [ false, true, false, false, false ],
+ "LABEL": [ false, true, false, false, false ],
+ "OUTPUT": [ false, true, false, false, false ],
+};
+
+/**
+ * For not candidate elements without disabled attribute and not submittable,
+ * we only have to check that focus and click works even inside a disabled
+ * fieldset.
+ */
+function checkElement(aElement, aDisabled)
+{
+ var data = testData[aElement.tagName];
+ var expected = data[0] ? !aDisabled : true;
+
+ if (data[1]) {
+ checkFocus(aElement, expected);
+ }
+
+ if (data[2]) {
+ checkEnabledPseudoClass(aElement, data[0] ? !aDisabled : true);
+ checkDisabledPseudoClass(aElement, data[0] ? aDisabled : false);
+ }
+
+ if (data[3]) {
+ checkCandidateForConstraintValidation(aElement, expected);
+ }
+
+ if (data[4]) {
+ checkValueMissing(aElement, expected);
+ }
+}
+
+var fieldset1 = document.createElement("fieldset");
+var fieldset2 = document.createElement("fieldset");
+var legendA = document.createElement("legend");
+var legendB = document.createElement("legend");
+var content = document.getElementById('content');
+content.appendChild(fieldset1);
+fieldset1.appendChild(fieldset2);
+fieldset2.disabled = true;
+
+for (var data of elements) {
+ var element = document.createElement(data);
+
+ if (data[4]) {
+ element.required = true;
+ }
+
+ fieldset1.disabled = false;
+ fieldset2.appendChild(element);
+
+ checkElement(element, fieldset2.disabled);
+
+ // Make sure changes are correctly managed.
+ fieldset2.disabled = false;
+ checkElement(element, fieldset2.disabled);
+ fieldset2.disabled = true;
+ checkElement(element, fieldset2.disabled);
+
+ // Make sure if a fieldset which is not the first fieldset is disabled, the
+ // elements inside the second fielset are disabled.
+ fieldset2.disabled = false;
+ fieldset1.disabled = true;
+ checkElement(element, fieldset1.disabled);
+
+ // Make sure the state change of the inner fieldset will not confuse.
+ fieldset2.disabled = true;
+ fieldset2.disabled = false;
+ checkElement(element, fieldset1.disabled);
+
+
+ /* legend tests */
+
+ // elements in the first legend of a disabled fieldset should not be disabled.
+ fieldset2.disabled = true;
+ fieldset1.disabled = false;
+ legendA.appendChild(element);
+ fieldset2.appendChild(legendA);
+ checkElement(element, false);
+
+ // elements in the second legend should be disabled
+ fieldset2.insertBefore(legendB, legendA);
+ checkElement(element, fieldset2.disabled);
+ fieldset2.removeChild(legendB);
+
+ // Elements in the first legend of a fieldset disabled by another fieldset
+ // should be disabled.
+ fieldset1.disabled = true;
+ checkElement(element, fieldset1.disabled);
+
+ // Elements inside a fieldset inside the first legend of a disabled fieldset
+ // should not be diasbled.
+ fieldset2.disabled = false;
+ fieldset1.appendChild(legendA);
+ legendA.appendChild(fieldset2);
+ fieldset2.appendChild(element);
+ checkElement(element, false);
+
+ // Elements inside the first legend of a disabled fieldset inside the first
+ // legend of a disabled fieldset should not be disabled.
+ fieldset2.disabled = false;
+ fieldset2.appendChild(legendB);
+ legendB.appendChild(element);
+ checkElement(element, false);
+ fieldset2.removeChild(legendB);
+ fieldset1.appendChild(fieldset2);
+
+ element.parentNode.removeChild(element);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug557087-4.html b/dom/html/test/test_bug557087-4.html
new file mode 100644
index 000000000..edb732dae
--- /dev/null
+++ b/dom/html/test/test_bug557087-4.html
@@ -0,0 +1,90 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=557087
+-->
+<head>
+ <title>Test for Bug 557087</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a>
+<p id="display"></p>
+<div id="content">
+ <iframe name='f'></iframe>
+ <form target='f' action="data:text/html">
+ <input type='text' id='a'>
+ <input type='checkbox' id='b'>
+ <input type='radio' id='c'>
+ <fieldset disabled>
+ <fieldset>
+ <input type='submit' id='s'>
+ </fieldset>
+ </fieldset>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 557087 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var gExpectedSubmits = 6;
+var gSubmitReceived = 0;
+var gEnd = false;
+
+var fieldsets = document.getElementsByTagName("fieldset");
+var form = document.forms[0];
+
+form.addEventListener("submit", function() {
+ ok(gEnd, gEnd ? "expected submit" : "non expected submit");
+ if (++gSubmitReceived >= gExpectedSubmits) {
+ form.removeEventListener("submit", arguments.callee, false);
+ SimpleTest.finish();
+ }
+}, false);
+
+var inputs = [
+ document.getElementById('a'),
+ document.getElementById('b'),
+ document.getElementById('c'),
+];
+
+function doSubmit()
+{
+ for (e of inputs) {
+ e.focus();
+ synthesizeKey("VK_RETURN", {});
+ }
+}
+
+SimpleTest.waitForFocus(function() {
+ doSubmit();
+
+ fieldsets[1].disabled = true;
+ fieldsets[0].disabled = false;
+ doSubmit();
+
+ fieldsets[0].disabled = false;
+ fieldsets[1].disabled = false;
+
+ gEnd = true;
+ doSubmit();
+
+ // Simple check that we can submit from inside a legend even if the fieldset
+ // is disabled.
+ var legend = document.createElement("legend");
+ fieldsets[0].appendChild(legend);
+ fieldsets[0].disabled = true;
+ legend.appendChild(document.getElementById('s'));
+
+ doSubmit();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug557087-5.html b/dom/html/test/test_bug557087-5.html
new file mode 100644
index 000000000..4b8c021f8
--- /dev/null
+++ b/dom/html/test/test_bug557087-5.html
@@ -0,0 +1,93 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=557087
+-->
+<head>
+ <title>Test for Bug 557087</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a>
+<p id="display"></p>
+<div id="content">
+ <iframe name='t'></iframe>
+ <form target='t' action="data:text/html,">
+ <fieldset disabled>
+ <fieldset>
+ <input name='i' value='i'>
+ <textarea name='t'>t</textarea>
+ <select name='s'><option>s</option></select>
+ </fieldset>
+ </fieldset>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 557087 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+
+var testResults = [
+ "data:text/html,?",
+ "data:text/html,?",
+ "data:text/html,?i=i&t=t&s=s",
+ "data:text/html,?i=i&t=t&s=s",
+];
+var gTestCount = 0;
+
+var form = document.forms[0];
+var iframe = document.getElementsByTagName('iframe')[0];
+var fieldsets = document.getElementsByTagName('fieldset');
+
+function runTest()
+{
+ iframe.addEventListener("load", function() {
+ is(iframe.contentWindow.location.href, testResults[gTestCount],
+ testResults[gTestCount] + " should have been loaded");
+
+ switch (++gTestCount) {
+ case 1:
+ fieldsets[1].disabled = true;
+ fieldsets[0].disabled = false;
+ form.submit();
+ SimpleTest.executeSoon(function() {
+ form.submit()
+ });
+ break;
+ case 2:
+ fieldsets[0].disabled = false;
+ fieldsets[1].disabled = false;
+ SimpleTest.executeSoon(function() {
+ form.submit()
+ });
+ break;
+ case 3:
+ // Elements inside the first legend of a disabled fieldset are submittable.
+ fieldsets[0].disabled = true;
+ fieldsets[1].disabled = true;
+ var legend = document.createElement("legend");
+ fieldsets[0].appendChild(legend);
+ while (fieldsets[1].firstChild) {
+ legend.appendChild(fieldsets[1].firstChild);
+ }
+ SimpleTest.executeSoon(function() {
+ form.submit()
+ });
+ break;
+ default:
+ iframe.removeEventListener("load", arguments.callee, false);
+ SimpleTest.executeSoon(SimpleTest.finish);
+ }
+ }, false);
+
+ form.submit();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug557087-6.html b/dom/html/test/test_bug557087-6.html
new file mode 100644
index 000000000..ea2e3efcc
--- /dev/null
+++ b/dom/html/test/test_bug557087-6.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=557087
+-->
+<head>
+ <title>Test for Bug 557087</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557087">Mozilla Bug 557087</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <fieldset disabled>
+ <input>
+ </fieldset>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 557087 **/
+
+// Testing random stuff following review comments.
+
+var fieldset = document.getElementsByTagName("fieldset")[0];
+
+is(fieldset.elements.length, 1,
+ "there should be one element inside the fieldset");
+is(fieldset.elements[0], document.getElementsByTagName("input")[0],
+ "input should be the element inside the fieldset");
+
+document.body.removeChild(document.getElementById('content'));
+is(fieldset.querySelector("input:disabled"), fieldset.elements[0],
+ "the input should still be disabled");
+
+fieldset.disabled = false;
+is(fieldset.querySelector("input:enabled"), fieldset.elements[0],
+ "the input should be enabled");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug557620.html b/dom/html/test/test_bug557620.html
new file mode 100644
index 000000000..4fe9def3a
--- /dev/null
+++ b/dom/html/test/test_bug557620.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=557620
+-->
+<head>
+ <title>Test for Bug 557620</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=557620">Mozilla Bug 557620</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <input type="tel" id='i'>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 557620 **/
+
+// More checks are done in test_bug551670.html.
+
+var tel = document.getElementById('i');
+is(tel.type, 'tel', "input with type='tel' should return 'tel'");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug558788-1.html b/dom/html/test/test_bug558788-1.html
new file mode 100644
index 000000000..94b7a5f00
--- /dev/null
+++ b/dom/html/test/test_bug558788-1.html
@@ -0,0 +1,211 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=558788
+-->
+<head>
+ <title>Test for Bug 558788</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ input, textarea { background-color: rgb(0,0,0) !important; }
+ :-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; }
+ :-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=558788">Mozilla Bug 558788</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 558788 **/
+
+/**
+ * This test checks the behavior of :valid and :invalid pseudo-classes
+ * when the user is typing/interacting with the element.
+ * Only <input> and <textarea> elements can have there validity changed by an
+ * user input.
+ */
+
+var gContent = document.getElementById('content');
+
+function checkValidApplies(elmt)
+{
+ is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+}
+
+function checkInvalidApplies(elmt, aTodo)
+{
+ if (aTodo) {
+ todo_is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+ return;
+ }
+ is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+}
+
+function checkMissing(elementName)
+{
+ var element = document.createElement(elementName);
+ element.required = true;
+ gContent.appendChild(element);
+ checkInvalidApplies(element);
+
+ element.focus();
+
+ synthesizeKey("a", {});
+ checkValidApplies(element);
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ checkInvalidApplies(element);
+
+ gContent.removeChild(element);
+}
+
+function checkTooLong(elementName)
+{
+ var element = document.createElement(elementName);
+ element.value = "foo";
+ element.maxLength = 2;
+ gContent.appendChild(element);
+ checkInvalidApplies(element, true);
+
+ element.focus();
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ checkValidApplies(element);
+ gContent.removeChild(element);
+}
+
+function checkTextAreaMissing()
+{
+ checkMissing('textarea');
+}
+
+function checkTextAreaTooLong()
+{
+ checkTooLong('textarea');
+}
+
+function checkTextArea()
+{
+ checkTextAreaMissing();
+ checkTextAreaTooLong();
+}
+
+function checkInputMissing()
+{
+ checkMissing('input');
+}
+
+function checkInputTooLong()
+{
+ checkTooLong('input');
+}
+
+function checkInputEmail()
+{
+ var element = document.createElement('input');
+ element.type = 'email';
+ gContent.appendChild(element);
+ checkValidApplies(element);
+
+ element.focus();
+
+ synthesizeKey("a", {});
+ checkInvalidApplies(element);
+
+ sendString("@b.c");
+ checkValidApplies(element);
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ for (var i=0; i<4; ++i) {
+ if (i == 1) {
+ // a@b is a valid value.
+ checkValidApplies(element);
+ } else {
+ checkInvalidApplies(element);
+ }
+ synthesizeKey("VK_BACK_SPACE", {});
+ }
+ checkValidApplies(element);
+
+ gContent.removeChild(element);
+}
+
+function checkInputURL()
+{
+ var element = document.createElement('input');
+ element.type = 'url';
+ gContent.appendChild(element);
+ checkValidApplies(element);
+
+ element.focus();
+
+ synthesizeKey("h", {});
+ checkInvalidApplies(element);
+
+ sendString("ttp://mozilla.org");
+ checkValidApplies(element);
+
+ for (var i=0; i<13; ++i) {
+ synthesizeKey("VK_BACK_SPACE", {});
+ checkValidApplies(element);
+ }
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ for (var i=0; i<4; ++i) {
+ checkInvalidApplies(element);
+ synthesizeKey("VK_BACK_SPACE", {});
+ }
+ checkValidApplies(element);
+
+ gContent.removeChild(element);
+}
+
+function checkInputPattern()
+{
+ var element = document.createElement('input');
+ element.pattern = "[0-9]*"
+ gContent.appendChild(element);
+ checkValidApplies(element);
+
+ element.focus();
+
+ synthesizeKey("0", {});
+ checkValidApplies(element);
+
+ synthesizeKey("a", {});
+ checkInvalidApplies(element);
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ checkValidApplies(element);
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ checkValidApplies(element);
+
+ gContent.removeChild(element);
+}
+
+function checkInput()
+{
+ checkInputMissing();
+ checkInputTooLong();
+ checkInputEmail();
+ checkInputURL();
+ checkInputPattern();
+}
+
+checkTextArea();
+checkInput();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug558788-2.html b/dom/html/test/test_bug558788-2.html
new file mode 100644
index 000000000..dcf5db00d
--- /dev/null
+++ b/dom/html/test/test_bug558788-2.html
@@ -0,0 +1,174 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=558788
+-->
+<head>
+ <title>Test for Bug 558788</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=558788">Mozilla Bug 558788</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 558788 **/
+
+var validElementsDescription = [
+ /* element type value required pattern maxlength minlength */
+ /* <input> */
+ [ "input", null, null, null, null, null, null ],
+ /* <input required value='foo'> */
+ [ "input", null, "foo", true, null, null, null ],
+ /* <input type='email'> */
+ [ "input", "email", null, null, null, null, null ],
+ /* <input type='email' value='foo@mozilla.org'> */
+ [ "input", "email", "foo@mozilla.org", null, null, null, null ],
+ /* <input type='url'> */
+ [ "input", "url", null, null, null, null, null ],
+ /* <input type='url' value='http://mozilla.org'> */
+ [ "input", "url", "http://mozilla.org", null, null, null, null ],
+ /* <input pattern='\\d\\d'> */
+ [ "input", null, null, null, "\\d\\d", null, null ],
+ /* <input pattern='\\d\\d' value='42'> */
+ [ "input", null, "42", null, "\\d\\d", null, null ],
+ /* <input maxlength='3'> - still valid until user interaction */
+ [ "input", null, null, null, null, "3", null ],
+ /* <input maxlength='3'> */
+ [ "input", null, "fooo", null, null, "3", null ],
+ /* <input minlength='3'> - still valid until user interaction */
+ [ "input", null, null, null, null, null, "3" ],
+ /* <input minlength='3'> */
+ [ "input", null, "fo", null, null, null, "3" ],
+ /* <textarea></textarea> */
+ [ "textarea", null, null, null, null, null, null ],
+ /* <textarea required>foo</textarea> */
+ [ "textarea", null, "foo", true, null, null, null ]
+];
+
+var invalidElementsDescription = [
+ /* element type value required pattern maxlength minlength valid-value */
+ /* <input required> */
+ [ "input", null, null, true, null, null, null, "foo" ],
+ /* <input type='email' value='foo'> */
+ [ "input", "email", "foo", null, null, null, null, "foo@mozilla.org" ],
+ /* <input type='url' value='foo'> */
+ [ "input", "url", "foo", null, null, null, null, "http://mozilla.org" ],
+ /* <input pattern='\\d\\d' value='foo'> */
+ [ "input", null, "foo", null, "\\d\\d", null, null, "42" ],
+ /* <input maxlength='3'> - still valid until user interaction */
+ [ "input", null, "foooo", null, null, "3", null, "foo" ],
+ /* <input minlength='3'> - still valid until user interaction */
+ [ "input", null, "foo", null, null, null, "3", "foo" ],
+ /* <textarea required></textarea> */
+ [ "textarea", null, null, true, null, null, null, "foo" ],
+];
+
+var validElements = [];
+var invalidElements = [];
+
+function appendElements(aElementsDesc, aElements)
+{
+ var content = document.getElementById('content');
+ var length = aElementsDesc.length;
+
+ for (var i=0; i<length; ++i) {
+ var e = document.createElement(aElementsDesc[i][0]);
+ if (aElementsDesc[i][1]) {
+ e.type = aElementsDesc[i][1];
+ }
+ if (aElementsDesc[i][2]) {
+ e.value = aElementsDesc[i][2];
+ }
+ if (aElementsDesc[i][3]) {
+ e.required = true;
+ }
+ if (aElementsDesc[i][4]) {
+ e.pattern = aElementsDesc[i][4];
+ }
+ if (aElementsDesc[i][5]) {
+ e.maxLength = aElementsDesc[i][5];
+ }
+ if (aElementsDesc[i][6]) {
+ e.minLength = aElementsDesc[i][6];
+ }
+
+ content.appendChild(e);
+
+ // Adding the element to the appropriate list.
+ aElements.push(e);
+ }
+}
+
+function compareArrayWithSelector(aElements, aSelector)
+{
+ var aSelectorElements = document.querySelectorAll(aSelector);
+
+ is(aSelectorElements.length, aElements.length,
+ aSelector + " selector should return the correct number of elements");
+
+ if (aSelectorElements.length != aElements.length) {
+ return;
+ }
+
+ var length = aElements.length;
+ for (var i=0; i<length; ++i) {
+ is(aSelectorElements[i], aElements[i],
+ aSelector + " should return the correct elements");
+ }
+}
+
+function makeMinMaxLengthElementsActuallyInvalid(aInvalidElements,
+ aInvalidElementsDesc)
+{
+ // min/maxlength elements are not invalid until user edits them
+ var length = aInvalidElementsDesc.length;
+
+ for (var i=0; i<length; ++i) {
+ var e = aInvalidElements[i];
+ if (aInvalidElementsDesc[i][5]) { // maxlength
+ e.focus();
+ synthesizeKey("VK_BACK_SPACE", {});
+ } else if (aInvalidElementsDesc[i][6]) { // minlength
+ e.focus();
+ synthesizeKey("VK_BACK_SPACE", {});
+ }
+ }
+}
+
+function makeInvalidElementsValid(aInvalidElements,
+ aInvalidElementsDesc,
+ aValidElements)
+{
+ var length = aInvalidElementsDesc.length;
+
+ for (var i=0; i<length; ++i) {
+ var e = aInvalidElements.shift();
+ e.value = aInvalidElementsDesc[i][7];
+ aValidElements.push(e);
+ }
+}
+
+appendElements(validElementsDescription, validElements);
+appendElements(invalidElementsDescription, invalidElements);
+
+makeMinMaxLengthElementsActuallyInvalid(invalidElements, invalidElementsDescription);
+
+compareArrayWithSelector(validElements, ":valid");
+compareArrayWithSelector(invalidElements, ":invalid");
+
+makeInvalidElementsValid(invalidElements, invalidElementsDescription,
+ validElements);
+
+compareArrayWithSelector(validElements, ":valid");
+compareArrayWithSelector(invalidElements, ":invalid");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug560112.html b/dom/html/test/test_bug560112.html
new file mode 100644
index 000000000..1b1daadc4
--- /dev/null
+++ b/dom/html/test/test_bug560112.html
@@ -0,0 +1,211 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=560112
+-->
+<head>
+ <title>Test for Bug 560112</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=560112">Mozilla Bug 560112</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 560112 **/
+
+/**
+ * Sets dataset property. Checks data attribute "attr".
+ * Gets dataset property. Checks data attribute "attr".
+ * Overwrites dataset property Checks data attribute "attr".
+ * Deletes dataset property. Checks data attribute "attr".
+ */
+function SetGetOverwriteDel(attr, prop)
+{
+ var el = document.createElement('div');
+
+ // Set property.
+ is(prop in el.dataset, false, 'Property should not be in dataset before setting.');
+ el.dataset[prop] = "zzzzzz";
+ is(prop in el.dataset, true, 'Property should be in dataset after setting.');
+ ok(el.hasAttribute(attr), 'Element should have data attribute for dataset property "' + prop + '".');
+
+ // Get property.
+ is(el.dataset[prop], "zzzzzz", 'Dataset property "' + prop + '" should have value "zzzzzz".');
+ is(el.getAttribute(attr), "zzzzzz", 'Attribute "' + attr + '" should have value "zzzzzz".');
+
+ // Overwrite property.
+ el.dataset[prop] = "yyyyyy";
+ is(el.dataset[prop], "yyyyyy", 'Dataset property "' + prop + '" should have value "yyyyyy".');
+ is(el.getAttribute(attr), "yyyyyy", 'Attribute "' + attr + '" should have value "yyyyyy".');
+
+ // Delete property.
+ delete el.dataset[prop];
+ ok(!el.hasAttribute(attr), 'Element should not have data attribute for dataset property "' + prop + '".');
+ is(prop in el.dataset, false, 'Deleted property should not be in dataset.');
+}
+
+/**
+ * Sets dataset property and expects exception.
+ */
+function SetExpectException(prop)
+{
+ var el = document.createElement('div');
+
+ try {
+ el.dataset[prop] = "xxxxxx";
+ ok(false, 'Exception should have been thrown.');
+ } catch (ex) {
+ ok(true, 'Exception should have been thrown.');
+ }
+}
+
+/**
+ * Adds attributes in "attrList" to element.
+ * Deletes attributes in "delList" from element.
+ * Checks for "numProp" properties in dataset.
+ */
+function DelAttrEnumerate(attrList, delList, numProp)
+{
+ var el = document.createElement('div');
+
+ // Adds attributes in "attrList".
+ for (var i = 0; i < attrList.length; ++i) {
+ el.setAttribute(attrList[i], "aaaaaa");
+ }
+
+ // Remove attributes in "delList".
+ for (var i = 0; i < delList.length; ++i) {
+ el.removeAttribute(delList[i]);
+ }
+
+ var numPropCounted = 0;
+
+ for (var prop in el.dataset) {
+ if (el.dataset[prop] == "aaaaaa") {
+ ++numPropCounted;
+ }
+ }
+
+ is(numPropCounted, numProp, 'Number of enumerable dataset properties is incorrent after attribute removal.');
+}
+
+/**
+ * Adds attributes in "attrList" to element.
+ * Checks for "numProp" properties in dataset.
+ */
+function Enumerate(attrList, numProp)
+{
+ var el = document.createElement('div');
+
+ // Adds attributes in "attrList" to element.
+ for (var i = 0; i < attrList.length; ++i) {
+ el.setAttribute(attrList[i], "aaaaaa");
+ }
+
+ var numPropCounted = 0;
+
+ for (var prop in el.dataset) {
+ if (el.dataset[prop] == "aaaaaa") {
+ ++numPropCounted;
+ }
+ }
+
+ is(numPropCounted, numProp, 'Number of enumerable dataset properties is incorrect.');
+}
+
+/**
+ * Adds dataset property then removes attribute from element and check for presence of
+ * properties using the "in" operator.
+ */
+function AddPropDelAttr(attr, prop)
+{
+ var el = document.createElement('div');
+
+ el.dataset[prop] = 'dddddd';
+ is(prop in el.dataset, true, 'Operator "in" should return true after setting property.');
+ el.removeAttribute(attr);
+ is(prop in el.dataset, false, 'Operator "in" should return false for removed attribute.');
+}
+
+/**
+ * Adds then removes attribute from element and check for presence of properties using the
+ * "in" operator.
+ */
+function AddDelAttr(attr, prop)
+{
+ var el = document.createElement('div');
+
+ el.setAttribute(attr, 'dddddd');
+ is(prop in el.dataset, true, 'Operator "in" should return true after setting attribute.');
+ el.removeAttribute(attr);
+ is(prop in el.dataset, false, 'Operator "in" should return false for removed attribute.');
+}
+
+// Typical use case.
+SetGetOverwriteDel('data-property', 'property');
+SetGetOverwriteDel('data-a-longer-property', 'aLongerProperty');
+
+AddDelAttr('data-property', 'property');
+AddDelAttr('data-a-longer-property', 'aLongerProperty');
+
+AddPropDelAttr('data-property', 'property');
+AddPropDelAttr('data-a-longer-property', 'aLongerProperty');
+
+// Empty property name.
+SetGetOverwriteDel('data-', '');
+
+// Leading dash characters.
+SetGetOverwriteDel('data--', '-');
+SetGetOverwriteDel('data--d', 'D');
+SetGetOverwriteDel('data---d', '-D');
+
+// Trailing dash characters.
+SetGetOverwriteDel('data-d-', 'd-');
+SetGetOverwriteDel('data-d--', 'd--');
+SetGetOverwriteDel('data-d-d-', 'dD-');
+
+// "data-" in attribute name.
+SetGetOverwriteDel('data-data-', 'data-');
+SetGetOverwriteDel('data-data-data-', 'dataData-');
+
+// Longer attribute.
+SetGetOverwriteDel('data-long-long-long-long-long-long-long-long-long-long-long-long-long', 'longLongLongLongLongLongLongLongLongLongLongLongLong');
+
+var longAttr = 'data-long';
+var longProp = 'long';
+for (var i = 0; i < 30000; ++i) {
+ // Create really long attribute and property names.
+ longAttr += '-long';
+ longProp += 'Long';
+}
+
+SetGetOverwriteDel(longAttr, longProp);
+
+// Syntax error in setting dataset property (dash followed by lower case).
+SetExpectException('-a');
+SetExpectException('a-a');
+SetExpectException('a-a-a');
+
+// Invalid character.
+SetExpectException('a a');
+
+// Enumeration over dataset properties.
+Enumerate(['data-a-big-fish'], 1);
+Enumerate(['dat-a-big-fish'], 0);
+Enumerate(['data-'], 1);
+Enumerate(['data-', 'data-more-data'], 2);
+Enumerate(['daaata-', 'data-more-data'], 1);
+
+// Delete data attributes and enumerate properties.
+DelAttrEnumerate(['data-one', 'data-two'], ['data-one'], 1);
+DelAttrEnumerate(['data-one', 'data-two'], ['data-three'], 2);
+DelAttrEnumerate(['data-one', 'data-two'], ['one'], 2);
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug561634.html b/dom/html/test/test_bug561634.html
new file mode 100644
index 000000000..61a1486e7
--- /dev/null
+++ b/dom/html/test/test_bug561634.html
@@ -0,0 +1,126 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=561634
+-->
+<head>
+ <title>Test for Bug 561634</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=561634">Mozilla Bug 561634</a>
+<p id="display"></p>
+<div id="content" style="display: none;">
+ <form>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 561634 **/
+
+function checkEmptyForm()
+{
+ ok(document.forms[0].checkValidity(), "An empty form is valid");
+}
+
+function checkBarredFromConstraintValidation()
+{
+ var f = document.forms[0];
+ var fs = document.createElement('fieldset');
+ var i = document.createElement('input');
+
+ f.appendChild(fs);
+ i.type = 'hidden';
+ f.appendChild(i);
+
+ fs.setCustomValidity("foo");
+ i.setCustomValidity("foo");
+
+ ok(f.checkValidity(),
+ "A form with invalid element barred from constraint validation should be valid");
+
+ f.removeChild(i);
+ f.removeChild(fs);
+}
+
+function checkValid()
+{
+ var f = document.forms[0];
+ var i = document.createElement('input');
+ f.appendChild(i);
+
+ ok(f.checkValidity(), "A form with valid elements is valid");
+
+ f.removeChild(i);
+}
+
+function checkInvalid()
+{
+ var f = document.forms[0];
+ var i = document.createElement('input');
+ f.appendChild(i);
+
+ i.setCustomValidity("foo");
+ ok(!f.checkValidity(), "A form with invalid elements is invalid");
+
+ var i2 = document.createElement('input');
+ f.appendChild(i2);
+ ok(!f.checkValidity(),
+ "A form with at least one invalid element is invalid");
+
+ f.removeChild(i2);
+ f.removeChild(i);
+}
+
+function checkInvalidEvent()
+{
+ var f = document.forms[0];
+ var i = document.createElement('input');
+ f.appendChild(i);
+ var i2 = document.createElement('input');
+ f.appendChild(i2);
+
+ i.setCustomValidity("foo");
+
+ var invalidEventForInvalidElement = false;
+ var invalidEventForValidElement = false;
+
+ i.addEventListener("invalid", function (e) {
+ invalidEventForInvalidElement = true;
+ ok(e.cancelable, "invalid event should be cancelable");
+ ok(!e.bubbles, "invalid event should not bubble");
+ }, false);
+
+ i2.addEventListener("invalid", function (e) {
+ invalidEventForValidElement = true;
+ }, false);
+
+ f.checkValidity();
+
+ setTimeout(function() {
+ ok(invalidEventForInvalidElement,
+ "invalid event should be fired on invalid elements");
+ ok(!invalidEventForValidElement,
+ "invalid event should not be fired on valid elements");
+
+ f.removeChild(i2);
+ f.removeChild(i);
+
+ SimpleTest.finish();
+ }, 0);
+}
+
+SimpleTest.waitForExplicitFinish();
+
+checkEmptyForm();
+checkBarredFromConstraintValidation();
+checkValid();
+checkInvalid();
+checkInvalidEvent(); // will call finish().
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug561636.html b/dom/html/test/test_bug561636.html
new file mode 100644
index 000000000..d259e8c83
--- /dev/null
+++ b/dom/html/test/test_bug561636.html
@@ -0,0 +1,118 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=561636
+-->
+<head>
+ <title>Test for Bug 561636</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=561636">Mozilla Bug 561636</a>
+<p id="display"></p>
+<iframe style='width:50px; height: 50px;' name='t'></iframe>
+<iframe style='width:50px; height: 50px;' name='t2' id='i'></iframe>
+<div id="content">
+ <form target='t' action='data:text/html,'>
+ <input required>
+ <input id='a' type='submit'>
+ </form>
+ <form target='t' action='data:text/html,'>
+ <input type='checkbox' required>
+ <button id='b' type='submit'></button>
+ </form>
+ <form target='t' action='data:text/html,'>
+ <input id='c' required>
+ </form>
+ <form target='t' action='data:text/html,'>
+ <input>
+ <input id='s2' type='submit'>
+ </form>
+ <form target='t2' action='data:text/html,'>
+ <input required>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 561636 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTest);
+
+function runTest()
+{
+ var formSubmitted = [ false, false ];
+ var invalidHandled = false;
+
+ var os = SpecialPowers.Cc['@mozilla.org/observer-service;1']
+ .getService(SpecialPowers.Ci.nsIObserverService);
+ var observers = os.enumerateObservers("invalidformsubmit");
+
+ // The following test should not be done if there is no observer for
+ // "invalidformsubmit" because the form submission will not be canceled in that
+ // case.
+ if (!observers.hasMoreElements()) {
+ SimpleTest.finish();
+ return;
+ }
+
+ // Initialize
+ document.forms[0].addEventListener('submit', function(aEvent) {
+ aEvent.target.removeEventListener('submit', arguments.callee, false);
+ formSubmitted[0] = true;
+ }, false);
+
+ document.forms[1].addEventListener('submit', function(aEvent) {
+ aEvent.target.removeEventListener('submit', arguments.callee, false);
+ formSubmitted[1] = true;
+ }, false);
+
+ document.forms[2].addEventListener('submit', function(aEvent) {
+ aEvent.target.removeEventListener('submit', arguments.callee, false);
+ formSubmitted[2] = true;
+ }, false);
+
+ document.forms[3].addEventListener('submit', function(aEvent) {
+ aEvent.target.removeEventListener('submit', arguments.callee, false);
+ formSubmitted[3] = true;
+
+ ok(!formSubmitted[0], "Form 1 should not have been submitted because invalid");
+ ok(!formSubmitted[1], "Form 2 should not have been submitted because invalid");
+ ok(!formSubmitted[2], "Form 3 should not have been submitted because invalid");
+ ok(formSubmitted[3], "Form 4 should have been submitted because valid");
+
+ // Next test.
+ document.forms[4].submit();
+ }, false);
+
+ document.forms[4].elements[0].addEventListener('invalid', function(aEvent) {
+ aEvent.target.removeEventListener('invalid', arguments.callee, false);
+ invalidHandled = true;
+ }, false);
+
+ document.getElementById('i').addEventListener('load', function(aEvent) {
+ aEvent.target.removeEventListener('load', arguments.callee, false);
+
+ SimpleTest.executeSoon(function () {
+ ok(true, "Form 5 should have been submitted because submit() has been used even if invalid");
+ ok(!invalidHandled, "Invalid event should not have been sent");
+
+ SimpleTest.finish();
+ });
+ }, false);
+
+ document.getElementById('a').click();
+ document.getElementById('b').click();
+ var c = document.getElementById('c');
+ c.focus();
+ synthesizeKey("KEY_Enter", { code: "Enter" });
+ document.getElementById('s2').click();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug561640.html b/dom/html/test/test_bug561640.html
new file mode 100644
index 000000000..670d1b3a1
--- /dev/null
+++ b/dom/html/test/test_bug561640.html
@@ -0,0 +1,72 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=561640
+-->
+<head>
+ <title>Test for Bug 561640</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ input, textarea { background-color: rgb(0,0,0) !important; }
+ :-moz-any(input,textarea):valid { background-color: rgb(0,255,0) !important; }
+ :-moz-any(input,textarea):invalid { background-color: rgb(255,0,0) !important; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=561640">Mozilla Bug 561640</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 561640 **/
+
+var elements = [ 'input', 'textarea' ];
+var content = document.getElementById('content');
+
+function checkValid(elmt)
+{
+ ok(!elmt.validity.tooLong, "element should not be too long");
+ is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
+ "rgb(0, 255, 0)", ":valid pseudo-class should apply");
+}
+
+function checkInvalid(elmt)
+{
+ todo(elmt.validity.tooLong, "element should be too long");
+ todo_is(window.getComputedStyle(elmt, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+}
+
+for (var elmtName of elements) {
+ var elmt = document.createElement(elmtName);
+ content.appendChild(elmt);
+
+ if (elmtName == 'textarea') {
+ elmt.textContent = 'foo';
+ } else {
+ elmt.setAttribute('value', 'foo');
+ }
+ elmt.maxLength = 2;
+ checkValid(elmt);
+
+ elmt.value = 'a';
+ checkValid(elmt);
+
+ if (elmtName == 'textarea') {
+ elmt.textContent = 'f';
+ } else {
+ elmt.setAttribute('value', 'f');
+ }
+ elmt.value = 'bar';
+ checkInvalid(elmt);
+
+ content.removeChild(elmt);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug564001.html b/dom/html/test/test_bug564001.html
new file mode 100644
index 000000000..3815ac8cf
--- /dev/null
+++ b/dom/html/test/test_bug564001.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=564001
+-->
+<head>
+ <title>Test for Bug 564001</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=564001">Mozilla Bug 564001</a>
+<p id="display"><img usemap=#map src=image.png></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script>
+/** Test for Bug 564001 **/
+SimpleTest.waitForExplicitFinish();
+
+var wrongArea = document.createElement("area");
+wrongArea.shape = "default";
+wrongArea.href = "#FAIL";
+var wrongMap = document.createElement("map");
+wrongMap.name = "map";
+wrongMap.appendChild(wrongArea);
+document.body.appendChild(wrongMap);
+
+var rightArea = document.createElement("area");
+rightArea.shape = "default";
+rightArea.href = "#PASS";
+var rightMap = document.createElement("map");
+rightMap.name = "map";
+rightMap.appendChild(rightArea);
+document.body.insertBefore(rightMap, wrongMap);
+
+var images = document.getElementsByTagName("img");
+onhashchange = function() {
+ is(location.hash, "#PASS", "Should get the first map in tree order.");
+ SimpleTest.finish();
+};
+SimpleTest.waitForFocus(() => synthesizeMouse(images[0], 50, 50, {}));
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug566046.html b/dom/html/test/test_bug566046.html
new file mode 100644
index 000000000..f12d12536
--- /dev/null
+++ b/dom/html/test/test_bug566046.html
@@ -0,0 +1,207 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=566046
+-->
+<head>
+ <title>Test for Bug 566046</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <base>
+ <base target='frame2'>
+ <base target=''>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566046">Mozilla Bug 566046</a>
+<p id="display"></p>
+<style>
+ iframe { width: 130px; height: 100px;}
+</style>
+<iframe name='frame1' id='frame1'></iframe>
+<iframe name='frame2' id='frame2'></iframe>
+<iframe name='frame3' id='frame3'></iframe>
+<iframe name='frame4' id='frame4'></iframe>
+<iframe name='frame5' id='frame5'></iframe>
+<iframe name='frame5bis' id='frame5bis'></iframe>
+<iframe name='frame6' id='frame6'></iframe>
+<iframe name='frame7' id='frame7'></iframe>
+<iframe name='frame8' id='frame8'></iframe>
+<iframe name='frame9' id='frame9'></iframe>
+<div id="content">
+ <form target='frame1' action="data:text/html," method="GET">
+ <input name='foo' value='foo'>
+ </form>
+ <form action="data:text/html," method="GET">
+ <input name='bar' value='bar'>
+ </form>
+ <form target="">
+ </form>
+
+ <!-- submit controls with formtarget that are validated with a CLICK -->
+ <form target="tulip" action="data:text/html," method="GET">
+ <input name='tulip' value='tulip'>
+ <input type='submit' id='is' formtarget='frame3'>
+ </form>
+ <form action="data:text/html," method="GET">
+ <input name='foobar' value='foobar'>
+ <input type='image' id='ii' formtarget='frame4'>
+ </form>
+ <form action="data:text/html," method="GET">
+ <input name='tulip2' value='tulip2'>
+ <button type='submit' id='bs' formtarget='frame5'>submit</button>
+ </form>
+ <form action="data:text/html," method="GET">
+ <input name='tulip3' value='tulip3'>
+ <button type='submit' id='bsbis' formtarget='frame5bis'>submit</button>
+ </form>
+
+ <!-- submit controls with formtarget that are validated with ENTER -->
+ <form target="tulip" action="data:text/html," method="GET">
+ <input name='footulip' value='footulip'>
+ <input type='submit' id='is2' formtarget='frame6'>
+ </form>
+ <form action="data:text/html," method="GET">
+ <input name='tulipfoobar' value='tulipfoobar'>
+ <input type='image' id='ii2' formtarget='frame7'>
+ </form>
+ <form action="data:text/html," method="GET">
+ <input name='tulipbar' value='tulipbar'>
+ <button type='submit' id='bs2' formtarget='frame8'>submit</button>
+ </form>
+
+ <!-- check that a which is not a submit control do not use @formtarget -->
+ <form target='frame9' action="data:text/html," method="GET">
+ <input id='enter' name='input' value='enter' formtarget='frame6'>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 566046 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ setTimeout(runTests, 0);
+});
+
+var gTestResults = {
+ frame1: "data:text/html,?foo=foo",
+ frame2: "data:text/html,?bar=bar",
+ frame3: "data:text/html,?tulip=tulip",
+ frame4: "data:text/html,?foobar=foobar&x=0&y=0",
+ frame5: "data:text/html,?tulip2=tulip2",
+ frame5bis: "data:text/html,?tulip3=tulip3",
+ frame6: "data:text/html,?footulip=footulip",
+ frame7: "data:text/html,?tulipfoobar=tulipfoobar&x=0&y=0",
+ frame8: "data:text/html,?tulipbar=tulipbar",
+ frame9: "data:text/html,?input=enter",
+};
+
+var gPendingLoad = 0; // Has to be set after depending on the frames number.
+
+function runTests()
+{
+ // Check the target IDL attribute.
+ for (var i=0; i<document.forms.length; ++i) {
+ var testValue = document.forms[i].getAttribute('target');
+ is(document.forms[i].target, testValue ? testValue : "",
+ "target IDL attribute should reflect the target content attribute");
+ }
+
+ // We add a load event for the frames which will be called when the forms
+ // will be submitted.
+ var frames = [ document.getElementById('frame1'),
+ document.getElementById('frame2'),
+ document.getElementById('frame3'),
+ document.getElementById('frame4'),
+ document.getElementById('frame5'),
+ document.getElementById('frame5bis'),
+ document.getElementById('frame6'),
+ document.getElementById('frame7'),
+ document.getElementById('frame8'),
+ document.getElementById('frame9'),
+ ];
+ gPendingLoad = frames.length;
+
+ for (var i=0; i<frames.length; i++) {
+ frames[i].setAttribute('onload', "frameLoaded(this);");
+ }
+
+ // Submitting only the forms with a valid target.
+ document.forms[0].submit();
+ document.forms[1].submit();
+
+ /**
+ * We are going to focus each element before interacting with either for
+ * simulating the ENTER key (synthesizeKey) or a click (synthesizeMouse) or
+ * using .click(). This because it may be needed (ENTER) and because we want
+ * to have the element visible in the iframe.
+ *
+ * Focusing the first element (id='is') is launching the tests.
+ */
+ document.getElementById('is').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('is'), 5, 5, {});
+ document.getElementById('ii').focus();
+ }, false);
+
+ document.getElementById('ii').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('ii'), 5, 5, {});
+ document.getElementById('bs').focus();
+ }, false);
+
+ document.getElementById('bs').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('bs'), 5, 5, {});
+ document.getElementById('bsbis').focus();
+ }, false);
+
+ document.getElementById('bsbis').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ document.getElementById('bsbis').click();
+ document.getElementById('is2').focus();
+ }, false);
+
+ document.getElementById('is2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('ii2').focus();
+ }, false);
+
+ document.getElementById('ii2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('bs2').focus();
+ }, false);
+
+ document.getElementById('bs2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('enter').focus();
+ }, false);
+
+ document.getElementById('enter').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ }, false);
+
+ document.getElementById('is').focus();
+}
+
+function frameLoaded(aFrame) {
+ // Check if when target is unspecified, it fallback correctly to the base
+ // element target attribute.
+ is(aFrame.contentWindow.location.href, gTestResults[aFrame.name],
+ "the target attribute doesn't have the correct behavior");
+
+ if (--gPendingLoad == 0) {
+ SimpleTest.finish();
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug567938-1.html b/dom/html/test/test_bug567938-1.html
new file mode 100644
index 000000000..b1c49bfb4
--- /dev/null
+++ b/dom/html/test/test_bug567938-1.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=567938
+-->
+<head>
+ <title>Test for Bug 567938</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="runTests();">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567938">Mozilla Bug 567938</a>
+<p id="display"></p>
+<iframe id='iframe' name="submit_frame" style="visibility: hidden;"></iframe>
+<div id="content" style="display: none">
+ <form id='f' method='get' target='submit_frame'>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 567938 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var gTestData = ["submit", "image"];
+var gCurrentTest = 0;
+
+function initializeNextTest()
+{
+ var form = document.forms[0];
+
+ // Cleaning-up.
+ form.textContent = "";
+
+ // Add the new element.
+ var element = document.createElement("input");
+ element.id = 'i';
+ element.type = gTestData[gCurrentTest];
+ element.onclick = function() { form.submit(); return false; };
+ form.action = gTestData[gCurrentTest];
+ form.appendChild(element);
+
+ sendMouseEvent({type: 'click'}, 'i');
+}
+
+function runTests()
+{
+ document.getElementById('iframe').addEventListener('load', function(aEvent) {
+ is(frames['submit_frame'].location.href,
+ "http://mochi.test:8888/tests/dom/html/test/" + gTestData[gCurrentTest],
+ "The form should have been submitted");
+ gCurrentTest++;
+ if (gCurrentTest < gTestData.length) {
+ initializeNextTest();
+ } else {
+ aEvent.target.removeEventListener('load', arguments.callee, false);
+ SimpleTest.finish();
+ }
+ }, false);
+
+ initializeNextTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug567938-2.html b/dom/html/test/test_bug567938-2.html
new file mode 100644
index 000000000..38d4881ed
--- /dev/null
+++ b/dom/html/test/test_bug567938-2.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=567938
+-->
+<head>
+ <title>Test for Bug 567938</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567938">Mozilla Bug 567938</a>
+<p id="display"></p>
+<iframe id='iframe' name="submit_frame" style="visibility: hidden;"></iframe>
+<div id="content" style="display: none">
+ <form id='f' method='get' target='submit_frame'>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 567938 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTests);
+
+var gTestData = ["submit", "image"];
+var gCurrentTest = 0;
+
+function initializeNextTest()
+{
+ var form = document.forms[0];
+
+ // Cleaning-up.
+ form.textContent = "";
+
+ // Add the new element.
+ var element = document.createElement("input");
+ element.id = 'i';
+ element.type = gTestData[gCurrentTest];
+ element.onclick = function() { form.submit(); element.type='text'; };
+ form.action = gTestData[gCurrentTest];
+ form.appendChild(element);
+
+ sendMouseEvent({type: 'click'}, 'i');
+}
+
+function runTests()
+{
+ document.getElementById('iframe').addEventListener('load', function(aEvent) {
+ is(frames['submit_frame'].location.href,
+ "http://mochi.test:8888/tests/dom/html/test/" + gTestData[gCurrentTest],
+ "The form should have been submitted");
+ gCurrentTest++;
+ if (gCurrentTest < gTestData.length) {
+ initializeNextTest();
+ } else {
+ aEvent.target.removeEventListener('load', arguments.callee, false);
+ SimpleTest.finish();
+ }
+ }, false);
+
+ initializeNextTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug567938-3.html b/dom/html/test/test_bug567938-3.html
new file mode 100644
index 000000000..ab78fb984
--- /dev/null
+++ b/dom/html/test/test_bug567938-3.html
@@ -0,0 +1,70 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=567938
+-->
+<head>
+ <title>Test for Bug 567938</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567938">Mozilla Bug 567938</a>
+<p id="display"></p>
+<iframe id='iframe' name="submit_frame" style="visibility: hidden;"></iframe>
+<div id="content" style="display: none">
+ <form id='f' method='get' target='submit_frame'>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 567938 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTests);
+
+var gTestData = ["submit", "image"];
+var gCurrentTest = 0;
+
+function initializeNextTest()
+{
+ var form = document.forms[0];
+
+ // Cleaning-up.
+ form.textContent = "";
+
+ // Add the new element.
+ var element = document.createElement("input");
+ element.id = 'i';
+ element.type = gTestData[gCurrentTest];
+ element.onclick = function() { setTimeout("document.forms[0].submit();",0); return false; };
+ form.appendChild(element);
+ form.action = gTestData[gCurrentTest];
+
+ sendMouseEvent({type: 'click'}, 'i');
+}
+
+function runTests()
+{
+ document.getElementById('iframe').addEventListener('load', function(aEvent) {
+ is(frames['submit_frame'].location.href,
+ "http://mochi.test:8888/tests/dom/html/test/" + gTestData[gCurrentTest],
+ "The form should have been submitted");
+ gCurrentTest++;
+ if (gCurrentTest < gTestData.length) {
+ initializeNextTest();
+ } else {
+ aEvent.target.removeEventListener('load', arguments.callee, false);
+ SimpleTest.finish();
+ }
+ }, false);
+
+ initializeNextTest();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug567938-4.html b/dom/html/test/test_bug567938-4.html
new file mode 100644
index 000000000..749a793ef
--- /dev/null
+++ b/dom/html/test/test_bug567938-4.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=567938
+-->
+<head>
+ <title>Test for Bug 567938</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567938">Mozilla Bug 567938</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <input id='i' type='checkbox' onclick="return false;">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 567938 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTests);
+
+function runTests()
+{
+ document.getElementById('i').checked = false;
+
+ document.getElementById('i').addEventListener('click', function(aEvent) {
+ aEvent.target.removeEventListener('click', arguments.callee, false);
+ SimpleTest.executeSoon(function() {
+ ok(!aEvent.target.checked, "the input should not be checked");
+ SimpleTest.finish();
+ });
+ }, false);
+
+ sendMouseEvent({type: 'click'}, 'i');
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug569955.html b/dom/html/test/test_bug569955.html
new file mode 100644
index 000000000..252a4ee47
--- /dev/null
+++ b/dom/html/test/test_bug569955.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=569955
+-->
+<head>
+ <title>Test for Bug 569955</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=569955">Mozilla Bug 569955</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <input id='i' autofocus>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 569955 **/
+
+function runTests()
+{
+ isnot(document.activeElement, document.getElementById('i'),
+ "not rendered elements can't be autofocused");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ setTimeout(runTests, 0);
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug573969.html b/dom/html/test/test_bug573969.html
new file mode 100644
index 000000000..308e89e51
--- /dev/null
+++ b/dom/html/test/test_bug573969.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=573969
+-->
+<head>
+ <title>Test for Bug 573969</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=573969">Mozilla Bug 573969</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <xmp id='x'></xmp>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 573969 **/
+
+var testData = [
+ '<div>foo</div>',
+ '&lt;div&gt;&lt;/div&gt;',
+];
+
+var x = document.getElementById('x');
+
+for (v of testData) {
+ x.innerHTML = v;
+ is(x.innerHTML, v, "innerHTML value should not be escaped");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug57600.html b/dom/html/test/test_bug57600.html
new file mode 100644
index 000000000..a8b976e22
--- /dev/null
+++ b/dom/html/test/test_bug57600.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=57600
+-->
+<head>
+ <title>Test for Bug 57600</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=57600">Mozilla Bug 57600</a>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 57600 **/
+SimpleTest.waitForExplicitFinish();
+var count = 0;
+function disp(win) {
+ var d = win ? win.document : self.testname.document;
+ var str = 'You should see this';
+ d.open();
+ d.write(str);
+ d.close();
+ is(d.documentElement.textContent, str, "Unexpected text");
+ if (++count == 2) {
+ SimpleTest.finish();
+ }
+}
+</script>
+</pre>
+<p id="display">
+ <iframe src="javascript:'<body onload=&quot;this.onerror = parent.onerror; parent.disp(self)&quot;></body>'">
+ </iframe>
+ <iframe name="testname" src="javascript:'<body onload=&quot;this.onerror = parent.onerror; parent.disp()&quot;></body>'">
+ </iframe>
+</p>
+</body>
+</html>
diff --git a/dom/html/test/test_bug579079.html b/dom/html/test/test_bug579079.html
new file mode 100644
index 000000000..2f098b3cf
--- /dev/null
+++ b/dom/html/test/test_bug579079.html
@@ -0,0 +1,43 @@
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=579079
+-->
+<head>
+ <title>Test for Bug 579079</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=579079">Mozilla Bug 579079</a>
+
+<div id="foo">
+ <img name="img1">
+ <form name="form1"></form>
+ <applet name="applet1"></applet>
+ <embed name="embed1"></embed>
+ <object name="object1"></object>
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+var img = document.img1;
+var form = document.form1;
+var applet = document.applet1;
+var embed = document.embed1;
+var object = document.object1;
+$("foo").innerHTML = $("foo").innerHTML;
+isnot(document.img1, img);
+ok(document.img1 instanceof HTMLImageElement);
+isnot(document.form1, form);
+ok(document.form1 instanceof HTMLFormElement);
+isnot(document.applet1, applet);
+ok(document.applet1 instanceof HTMLAppletElement);
+isnot(document.embed1, embed);
+ok(document.embed1 instanceof HTMLEmbedElement);
+isnot(document.object1, object);
+ok(document.object1 instanceof HTMLObjectElement);
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug582412-1.html b/dom/html/test/test_bug582412-1.html
new file mode 100644
index 000000000..4883a3b76
--- /dev/null
+++ b/dom/html/test/test_bug582412-1.html
@@ -0,0 +1,209 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=566160
+-->
+<head>
+ <title>Test for Bug 566160</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566160">Mozilla Bug 566160</a>
+<p id="display"></p>
+<style>
+ iframe { width: 130px; height: 100px;}
+</style>
+<iframe name='frame1' id='frame1'></iframe>
+<iframe name='frame2' id='frame2'></iframe>
+<iframe name='frame3' id='frame3'></iframe>
+<iframe name='frame3bis' id='frame3bis'></iframe>
+<iframe name='frame4' id='frame4'></iframe>
+<iframe name='frame5' id='frame5'></iframe>
+<iframe name='frame6' id='frame6'></iframe>
+<iframe name='frame7' id='frame7'></iframe>
+<iframe name='frame8' id='frame8'></iframe>
+<iframe name='frame9' id='frame9'></iframe>
+<div id="content">
+ <!-- submit controls with formaction that are validated with a CLICK -->
+ <form target="frame1" action="data:text/html," method="POST">
+ <input name='foo' value='foo'>
+ <input type='submit' id='is' formmethod="GET">
+ </form>
+ <form target="frame2" action="data:text/html," method="POST">
+ <input name='bar' value='bar'>
+ <input type='image' id='ii' formmethod="GET">
+ </form>
+ <form target="frame3" action="data:text/html," method="POST">
+ <input name='tulip' value='tulip'>
+ <button type='submit' id='bs' formmethod="GET">submit</button>
+ </form>
+ <form target="frame3bis" action="data:text/html," method="POST">
+ <input name='tulipbis' value='tulipbis'>
+ <button type='submit' id='bsbis' formmethod="GET">submit</button>
+ </form>
+
+ <!-- submit controls with formaction that are validated with ENTER -->
+ <form target="frame4" action="data:text/html," method="POST">
+ <input name='footulip' value='footulip'>
+ <input type='submit' id='is2' formmethod="GET">
+ </form>
+ <form target="frame5" action="data:text/html," method="POST">
+ <input name='foobar' value='foobar'>
+ <input type='image' id='ii2' formmethod="GET">
+ </form>
+ <form target="frame6" action="data:text/html," method="POST">
+ <input name='tulip2' value='tulip2'>
+ <button type='submit' id='bs2' formmethod="GET">submit</button>
+ </form>
+
+ <!-- check that when submitting a from from an element
+ which is not a submit control, @formaction isn't used -->
+ <form target='frame7' action="data:text/html," method="GET">
+ <input id='enter' name='input' value='enter' formmethod="POST">
+ </form>
+
+ <!-- If formmethod isn't set, it's default value shouldn't be used -->
+ <form target="frame8" action="data:text/html," method="POST">
+ <input name='tulip8' value='tulip8'>
+ <input type='submit' id='i8'>
+ </form>
+
+ <!-- If formmethod is set but has an invalid value, the default value should
+ be used. -->
+ <form target="frame9" action="data:text/html," method="POST">
+ <input name='tulip9' value='tulip9'>
+ <input type='submit' id='i9' formmethod="">
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 566160 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ setTimeout(runTests, 0);
+});
+
+var gTestResults = {
+ frame1: "data:text/html,?foo=foo",
+ frame2: "data:text/html,?bar=bar&x=0&y=0",
+ frame3: "data:text/html,?tulip=tulip",
+ frame3bis: "data:text/html,?tulipbis=tulipbis",
+ frame4: "data:text/html,?footulip=footulip",
+ frame5: "data:text/html,?foobar=foobar&x=0&y=0",
+ frame6: "data:text/html,?tulip2=tulip2",
+ frame7: "data:text/html,?input=enter",
+ frame8: "data:text/html,",
+ frame9: "data:text/html,?tulip9=tulip9",
+};
+
+var gPendingLoad = 0; // Has to be set after depending on the frames number.
+
+function runTests()
+{
+ // We add a load event for the frames which will be called when the forms
+ // will be submitted.
+ var frames = [ document.getElementById('frame1'),
+ document.getElementById('frame2'),
+ document.getElementById('frame3'),
+ document.getElementById('frame3bis'),
+ document.getElementById('frame4'),
+ document.getElementById('frame5'),
+ document.getElementById('frame6'),
+ document.getElementById('frame7'),
+ document.getElementById('frame8'),
+ document.getElementById('frame9'),
+ ];
+ gPendingLoad = frames.length;
+
+ for (var i=0; i<frames.length; i++) {
+ frames[i].setAttribute('onload', "frameLoaded(this);");
+ }
+
+ /**
+ * We are going to focus each element before interacting with either for
+ * simulating the ENTER key (synthesizeKey) or a click (synthesizeMouse) or
+ * using .click(). This because it may be needed (ENTER) and because we want
+ * to have the element visible in the iframe.
+ *
+ * Focusing the first element (id='is') is launching the tests.
+ */
+ document.getElementById('is').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('is'), 5, 5, {});
+ document.getElementById('ii').focus();
+ }, false);
+
+ document.getElementById('ii').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('ii'), 5, 5, {});
+ document.getElementById('bs').focus();
+ }, false);
+
+ document.getElementById('bs').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('bs'), 5, 5, {});
+ document.getElementById('bsbis').focus();
+ }, false);
+
+ document.getElementById('bsbis').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ document.getElementById('bsbis').click();
+ document.getElementById('is2').focus();
+ }, false);
+
+ document.getElementById('is2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('ii2').focus();
+ }, false);
+
+ document.getElementById('ii2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('bs2').focus();
+ }, false);
+
+ document.getElementById('bs2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('enter').focus();
+ }, false);
+
+ document.getElementById('enter').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('i8').focus();
+ }, false);
+
+ document.getElementById('i8').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('i9').focus();
+ }, false);
+
+ document.getElementById('i9').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ }, false);
+
+ document.getElementById('is').focus();
+}
+
+function frameLoaded(aFrame) {
+ // Check if formaction/action has the correct behavior.
+ is(aFrame.contentWindow.location.href, gTestResults[aFrame.name],
+ "the method/formmethod attribute doesn't have the correct behavior");
+
+ if (--gPendingLoad == 0) {
+ SimpleTest.finish();
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug582412-2.html b/dom/html/test/test_bug582412-2.html
new file mode 100644
index 000000000..59175679c
--- /dev/null
+++ b/dom/html/test/test_bug582412-2.html
@@ -0,0 +1,209 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=566160
+-->
+<head>
+ <title>Test for Bug 566160</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=566160">Mozilla Bug 566160</a>
+<p id="display"></p>
+<style>
+ iframe { width: 130px; height: 100px;}
+</style>
+<iframe name='frame1' id='frame1'></iframe>
+<iframe name='frame2' id='frame2'></iframe>
+<iframe name='frame3' id='frame3'></iframe>
+<iframe name='frame3bis' id='frame3bis'></iframe>
+<iframe name='frame4' id='frame4'></iframe>
+<iframe name='frame5' id='frame5'></iframe>
+<iframe name='frame6' id='frame6'></iframe>
+<iframe name='frame7' id='frame7'></iframe>
+<iframe name='frame8' id='frame8'></iframe>
+<iframe name='frame9' id='frame9'></iframe>
+<div id="content">
+ <!-- submit controls with formaction that are validated with a CLICK -->
+ <form target="frame1" action="form_submit_server.sjs" method="POST">
+ <input name='foo' value='foo'>
+ <input type='submit' id='is' formenctype='multipart/form-data'>
+ </form>
+ <form target="frame2" action="form_submit_server.sjs" method="POST">
+ <input name='bar' value='bar'>
+ <input type='image' id='ii' formenctype='multipart/form-data'>
+ </form>
+ <form target="frame3" action="form_submit_server.sjs" method="POST">
+ <input name='tulip' value='tulip'>
+ <button type='submit' id='bs' formenctype="multipart/form-data">submit</button>
+ </form>
+ <form target="frame3bis" action="form_submit_server.sjs" method="POST">
+ <input name='tulipbis' value='tulipbis'>
+ <button type='submit' id='bsbis' formenctype="multipart/form-data">submit</button>
+ </form>
+
+ <!-- submit controls with formaction that are validated with ENTER -->
+ <form target="frame4" action="form_submit_server.sjs" method="POST">
+ <input name='footulip' value='footulip'>
+ <input type='submit' id='is2' formenctype="multipart/form-data">
+ </form>
+ <form target="frame5" action="form_submit_server.sjs" method="POST">
+ <input name='foobar' value='foobar'>
+ <input type='image' id='ii2' formenctype="multipart/form-data">
+ </form>
+ <form target="frame6" action="form_submit_server.sjs" method="POST">
+ <input name='tulip2' value='tulip2'>
+ <button type='submit' id='bs2' formenctype="multipart/form-data">submit</button>
+ </form>
+
+ <!-- check that when submitting a from from an element
+ which is not a submit control, @formaction isn't used -->
+ <form target='frame7' action="form_submit_server.sjs" method="POST">
+ <input id='enter' name='input' value='enter' formenctype="multipart/form-data">
+ </form>
+
+ <!-- If formenctype isn't set, it's default value shouldn't be used -->
+ <form target="frame8" action="form_submit_server.sjs" method="POST" enctype="multipart/form-data">
+ <input name='tulip8' value='tulip8'>
+ <input type='submit' id='i8'>
+ </form>
+
+ <!-- If formenctype is set but has an invalid value, the default value should
+ be used. -->
+ <form target="frame9" action="form_submit_server.sjs" method="POST" enctype="multipart/form-data">
+ <input name='tulip9' value='tulip9'>
+ <input type='submit' id='i9' formenctype="">
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 566160 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ setTimeout(runTests, 0);
+});
+
+var gTestResults = {
+ frame1: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"foo\\\"\"},\"body\":\"foo\"}]',
+ frame2: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"bar\\\"\"},\"body\":\"bar\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"x\\\"\"},\"body\":\"0\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"y\\\"\"},\"body\":\"0\"}]',
+ frame3: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulip\\\"\"},\"body\":\"tulip\"}]',
+ frame3bis: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulipbis\\\"\"},\"body\":\"tulipbis\"}]',
+ frame4: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"footulip\\\"\"},\"body\":\"footulip\"}]',
+ frame5: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"foobar\\\"\"},\"body\":\"foobar\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"x\\\"\"},\"body\":\"0\"},{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"y\\\"\"},\"body\":\"0\"}]',
+ frame6: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulip2\\\"\"},\"body\":\"tulip2\"}]',
+ frame7: '[]',
+ frame8: '[{\"headers\":{\"Content-Disposition\":\"form-data; name=\\\"tulip8\\\"\"},\"body\":\"tulip8\"}]',
+ frame9: '[]',
+};
+
+var gPendingLoad = 0; // Has to be set after depending on the frames number.
+
+function runTests()
+{
+ // We add a load event for the frames which will be called when the forms
+ // will be submitted.
+ var frames = [ document.getElementById('frame1'),
+ document.getElementById('frame2'),
+ document.getElementById('frame3'),
+ document.getElementById('frame3bis'),
+ document.getElementById('frame4'),
+ document.getElementById('frame5'),
+ document.getElementById('frame6'),
+ document.getElementById('frame7'),
+ document.getElementById('frame8'),
+ document.getElementById('frame9'),
+ ];
+ gPendingLoad = frames.length;
+
+ for (var i=0; i<frames.length; i++) {
+ frames[i].setAttribute('onload', "frameLoaded(this);");
+ }
+
+ /**
+ * We are going to focus each element before interacting with either for
+ * simulating the ENTER key (synthesizeKey) or a click (synthesizeMouse) or
+ * using .click(). This because it may be needed (ENTER) and because we want
+ * to have the element visible in the iframe.
+ *
+ * Focusing the first element (id='is') is launching the tests.
+ */
+ document.getElementById('is').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('is'), 5, 5, {});
+ document.getElementById('ii').focus();
+ }, false);
+
+ document.getElementById('ii').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('ii'), 5, 5, {});
+ document.getElementById('bs').focus();
+ }, false);
+
+ document.getElementById('bs').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeMouse(document.getElementById('bs'), 5, 5, {});
+ document.getElementById('bsbis').focus();
+ }, false);
+
+ document.getElementById('bsbis').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ document.getElementById('bsbis').click();
+ document.getElementById('is2').focus();
+ }, false);
+
+ document.getElementById('is2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('ii2').focus();
+ }, false);
+
+ document.getElementById('ii2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('bs2').focus();
+ }, false);
+
+ document.getElementById('bs2').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('enter').focus();
+ }, false);
+
+ document.getElementById('enter').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('i8').focus();
+ }, false);
+
+ document.getElementById('i8').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ document.getElementById('i9').focus();
+ }, false);
+
+ document.getElementById('i9').addEventListener('focus', function(aEvent) {
+ aEvent.target.removeEventListener('focus', arguments.callee, false);
+ synthesizeKey("VK_RETURN", {});
+ }, false);
+
+ document.getElementById('is').focus();
+}
+
+function frameLoaded(aFrame) {
+ // Check if formaction/action has the correct behavior.
+ is(aFrame.contentDocument.documentElement.textContent, gTestResults[aFrame.name],
+ "the enctype/formenctype attribute doesn't have the correct behavior");
+
+ if (--gPendingLoad == 0) {
+ SimpleTest.finish();
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug583514.html b/dom/html/test/test_bug583514.html
new file mode 100644
index 000000000..20e7824e6
--- /dev/null
+++ b/dom/html/test/test_bug583514.html
@@ -0,0 +1,71 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=583514
+-->
+<head>
+ <title>Test for Bug 583514</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583514">Mozilla Bug 583514</a>
+<p id="display"></p>
+<div id="content">
+ <input>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 583514 **/
+
+var gExpectDivClick = false;
+var gExpectInputClick = false;
+
+var div = document.getElementById('content');
+var input = document.getElementsByTagName('input')[0];
+
+div.addEventListener('click', function() {
+ ok(gExpectDivClick, "click event received on div and expected status was: " +
+ gExpectDivClick);
+}, false);
+
+input.addEventListener('click', function() {
+ ok(gExpectInputClick, "click event received on input and expected status was: " +
+ gExpectInputClick);
+}, false);
+
+SimpleTest.waitForExplicitFinish();
+
+SimpleTest.waitForFocus(function() {
+ var body = document.body;
+
+ body.addEventListener('click', function(aEvent) {
+ if (aEvent.target == input) {
+ body.removeEventListener('click', arguments.callee, false);
+ }
+
+ ok(true, "click event received on body");
+
+ SimpleTest.executeSoon(function() {
+ isnot(document.activeElement, input, "input shouldn't have been focused");
+ isnot(document.activeElement, div, "div shouldn't have been focused");
+
+ if (aEvent.target == input) {
+ SimpleTest.finish();
+ } else {
+ gExpectDivClick = true;
+ gExpectInputClick = true;
+ input.click();
+ }
+ });
+ }, false);
+
+ gExpectDivClick = true;
+ div.click();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug583533.html b/dom/html/test/test_bug583533.html
new file mode 100644
index 000000000..1042b6f09
--- /dev/null
+++ b/dom/html/test/test_bug583533.html
@@ -0,0 +1,81 @@
+<!DOCTYPE HTML>
+<html>
+ <!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=583533
+-->
+ <head>
+ <title>Test for Bug 583514</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ </head>
+ <body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=583533">Mozilla Bug 583533</a>
+ <p id="display"></p>
+ <div id="content">
+ <div id="e" accesskey="a">
+ </div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+ /** Test for Bug 583533 **/
+
+ var sbs = SpecialPowers.Cc['@mozilla.org/intl/stringbundle;1'].
+ getService(SpecialPowers.Ci.nsIStringBundleService);
+ var bundle = sbs.createBundle("chrome://global-platform/locale/platformKeys.properties");
+
+ var shiftText = bundle.GetStringFromName("VK_SHIFT");
+ var altText = bundle.GetStringFromName("VK_ALT");
+ var controlText = bundle.GetStringFromName("VK_CONTROL");
+ var metaText = bundle.GetStringFromName("VK_META");
+ var separatorText = bundle.GetStringFromName("MODIFIER_SEPARATOR");
+
+ var modifier = SpecialPowers.getIntPref("ui.key.contentAccess");
+
+ var isShift;
+ var isAlt;
+ var isControl;
+ var isMeta;
+
+ is(modifier < 16 && modifier >= 0, true, "Modifier in range");
+
+ // There are no consts for the mask of this prefs.
+ if (modifier & 8) {
+ isMeta = true;
+ }
+ if (modifier & 1) {
+ isShift = true;
+ }
+ if (modifier & 2) {
+ isControl = true;
+ }
+ if (modifier & 4) {
+ isAlt = true;
+ }
+
+ var label = "";
+
+ if (isControl)
+ label += controlText + separatorText;
+ if (isMeta)
+ label += metaText + separatorText;
+ if (isAlt)
+ label += altText + separatorText;
+ if (isShift)
+ label += shiftText + separatorText;
+
+ label += document.getElementById("e").accessKey;
+
+ is(label, document.getElementById("e").accessKeyLabel, "JS and C++ agree on accessKeyLabel");
+
+ /** Test for Bug 808964 **/
+
+ var div = document.createElement("div");
+ document.body.appendChild(div);
+
+ is(div.accessKeyLabel, "", "accessKeyLabel should be empty string");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug586763.html b/dom/html/test/test_bug586763.html
new file mode 100644
index 000000000..9ecf00ea8
--- /dev/null
+++ b/dom/html/test/test_bug586763.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=586763
+-->
+<title>Test for Bug 586763</title>
+<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=586763">Mozilla Bug 586763</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script>
+/** Test for Bug 586763 **/
+var tests = [
+ ["ol", "start", 1],
+ ["li", "value", 0],
+ ["object", "hspace", 0],
+ ["object", "vspace", 0],
+ ["img", "hspace", 0],
+ ["img", "vspace", 0],
+ ["video", "height", 0],
+ ["video", "width", 0],
+ ["pre", "width", 0],
+ ["textarea", "cols", 20],
+ ["textarea", "rows", 2],
+ ["span", "tabIndex", -1],
+ ["frame", "tabIndex", 0],
+ ["a", "tabIndex", 0],
+ ["area", "tabIndex", 0],
+ ["button", "tabIndex", 0],
+ ["input", "tabIndex", 0],
+ ["object", "tabIndex", -1],
+ ["select", "tabIndex", 0],
+ ["textarea", "tabIndex", 0],
+];
+
+for (var i = 0; i < tests.length; i++) {
+ is(document.createElement(tests[i][0])[tests[i][1]], tests[i][2], "Reflected attribute " + tests[i][0] + "." + tests[i][1] + " should default to " + tests[i][2]);
+}
+</script>
+</pre>
diff --git a/dom/html/test/test_bug586786.html b/dom/html/test/test_bug586786.html
new file mode 100644
index 000000000..17d95c2a5
--- /dev/null
+++ b/dom/html/test/test_bug586786.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=586786
+-->
+<head>
+ <title>Test for Bug 586786</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=586786">Mozilla Bug 586786</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 586786 **/
+
+var elements = ["col", "colgroup", "tbody", "tfoot", "thead", "tr", "td", "th"];
+
+for(var i = 0; i < elements.length; i++)
+{
+ reflectString({
+ element: document.createElement(elements[i]),
+ attribute: "align",
+ otherValues: [ "left", "right", "center", "justify", "char" ]
+ });
+
+ reflectString({
+ element: document.createElement(elements[i]),
+ attribute: "vAlign",
+ otherValues: [ "top", "middle", "bottom", "baseline" ]
+ });
+
+ reflectString({
+ element: document.createElement(elements[i]),
+ attribute: {idl: "ch", content: "char"}
+ });
+}
+
+// table.border, table.width
+reflectString({
+ element: document.createElement("table"),
+ attribute: "border"
+});
+
+reflectString({
+ element: document.createElement("table"),
+ attribute: "width"
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug587469.html b/dom/html/test/test_bug587469.html
new file mode 100644
index 000000000..b0e941296
--- /dev/null
+++ b/dom/html/test/test_bug587469.html
@@ -0,0 +1,41 @@
+<!-- Quirks -->
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=587469
+-->
+<head>
+ <title>Test for Bug 587469</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=587469">Mozilla Bug 587469</a>
+<p id="display">
+<map name=a></map>
+<map name=a><area shape=rect coords=25,25,75,75 href=#fail></map>
+<img usemap=#a src=image.png>
+</p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 587469 **/
+SimpleTest.waitForExplicitFinish();
+function finish() {
+ is(location.hash, "", "Should not have changed the hash.");
+ SimpleTest.finish();
+}
+SimpleTest.waitForFocus(function() {
+ synthesizeMouse(document.getElementsByTagName("img")[0], 50, 50, {});
+ // Hit the event loop twice before doing the test
+ setTimeout(function() {
+ setTimeout(finish, 0);
+ }, 0);
+});
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug589.html b/dom/html/test/test_bug589.html
new file mode 100644
index 000000000..a5d0eabdb
--- /dev/null
+++ b/dom/html/test/test_bug589.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=589
+-->
+<head>
+ <title>Test for Bug 589</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<style type="text/css">
+.letters {list-style-type: upper-alpha;}
+.numbers {list-style-type: decimal;}
+</style>
+
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=589">Mozilla Bug 589</a>
+<p id="display"></p>
+<div id="content" >
+
+<OL id="thelist" class="letters">
+<LI id="liA">This list should feature...
+<LI id="liB">...letters for each item...
+<LI id="li3" class="numbers">...except this one.
+</OL>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 589 **/
+
+is(computedStyle($("liA"),"list-style-type"),"upper-alpha");
+is(computedStyle($("liB"),"list-style-type"),"upper-alpha");
+is(computedStyle($("li3"),"list-style-type"),"decimal");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug590353-1.html b/dom/html/test/test_bug590353-1.html
new file mode 100644
index 000000000..c7aa52ab9
--- /dev/null
+++ b/dom/html/test/test_bug590353-1.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=590353
+-->
+<head>
+ <title>Test for Bug 590353</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=590353">Mozilla Bug 590353</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 590353 **/
+
+var testData = ['checkbox', 'radio'];
+
+for (var data of testData) {
+ var e = document.createElement('input');
+ e.type = data;
+ e.checked = true;
+ e.value = "foo";
+
+ is(e.value, "foo", "foo should be the new " + data + "value");
+ is(e.getAttribute('value'), "foo", "foo should be the new " + data +
+ " value attribute value");
+ ok(e.checked, data + " should still be checked");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug590353-2.html b/dom/html/test/test_bug590353-2.html
new file mode 100644
index 000000000..db44efab1
--- /dev/null
+++ b/dom/html/test/test_bug590353-2.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=590353
+-->
+<head>
+ <title>Test for Bug 590353</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=590353">Mozilla Bug 590353</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 590353 **/
+
+var testData = [
+ [ "text", "foo", "" ],
+ [ "email", "foo@bar.com", "" ],
+ [ "url", "http:///foo.com", "" ],
+ [ "tel", "555 555 555 555", "" ],
+ [ "search", "foo", "" ],
+ [ "password", "secret", "" ],
+ [ "hidden", "foo", "foo" ],
+ [ "button", "foo", "foo" ],
+ [ "reset", "foo", "foo" ],
+ [ "submit", "foo", "foo" ],
+ [ "checkbox", true, false ],
+ [ "radio", true, false ],
+ [ "file", "590353_file", "" ],
+];
+
+function createFileWithData(fileName, fileData) {
+ return new File([new Blob([fileData], { type: "text/plain" })], fileName);
+}
+
+var content = document.getElementById('content');
+var form = document.createElement('form');
+content.appendChild(form);
+
+for (var data of testData) {
+ var e = document.createElement('input');
+ e.type = data[0];
+
+ if (data[0] == 'checkbox' || data[0] == 'radio') {
+ e.checked = data[1];
+ } else if (data[0] == 'file') {
+ var file = createFileWithData(data[1], "file content");
+ SpecialPowers.wrap(e).mozSetFileArray([file]);
+ } else {
+ e.value = data[1];
+ }
+
+ form.appendChild(e);
+}
+
+form.reset();
+
+var size = form.elements.length;
+for (var i=0; i<size; ++i) {
+ var e = form.elements[i];
+
+ if (e.type == 'radio' || e.type == 'checkbox') {
+ is(e.checked, testData[i][2],
+ "the element checked value should be " + testData[i][2]);
+ } else {
+ is(e.value, testData[i][2],
+ "the element value should be " + testData[i][2]);
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug590363.html b/dom/html/test/test_bug590363.html
new file mode 100644
index 000000000..3e72b542c
--- /dev/null
+++ b/dom/html/test/test_bug590363.html
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=590363
+-->
+<head>
+ <title>Test for Bug 590363</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=590363">Mozilla Bug 590363</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 590363 **/
+
+var testData = [
+ /* type to test | is the value reset when changing to file then reverting */
+ [ "button", false ],
+ [ "checkbox", false ],
+ [ "hidden", false ],
+ [ "reset", false ],
+ [ "image", false ],
+ [ "radio", false ],
+ [ "submit", false ],
+ [ "tel", true ],
+ [ "text", true ],
+ [ "url", true ],
+ [ "email", true ],
+ [ "search", true ],
+ [ "password", true ],
+ [ "number", true ],
+ [ "date", true ],
+ [ "time", true ],
+ [ "range", true ],
+ [ "color", true ],
+ [ 'month', true ],
+ [ 'week', true ],
+ [ 'datetime-local', true ]
+ // 'file' is treated separatly.
+];
+
+var nonTrivialSanitizing = [ 'number', 'date', 'time', 'color', 'month', 'week',
+ 'datetime-local' ];
+
+var length = testData.length;
+for (var i=0; i<length; ++i) {
+ for (var j=0; j<length; ++j) {
+ var e = document.createElement('input');
+ e.type = testData[i][0];
+
+ var expectedValue;
+
+ // range will sanitize its value to 50 (the default) if it isn't a valid
+ // number. We need to handle that specially.
+ if (testData[j][0] == 'range' || testData[i][0] == 'range') {
+ if (testData[j][0] == 'date' || testData[j][0] == 'time' ||
+ testData[j][0] == 'month' || testData[j][0] == 'week' ||
+ testData[j][0] == 'datetime-local') {
+ expectedValue = '';
+ } else if (testData[j][0] == 'color') {
+ expectedValue = '#000000';
+ } else {
+ expectedValue = '50';
+ }
+ } else if (testData[i][0] == 'color' || testData[j][0] == 'color') {
+ if (testData[j][0] == 'number' || testData[j][0] == 'date' ||
+ testData[j][0] == 'time' || testData[j][0] == 'month' ||
+ testData[j][0] == 'week' || testData[j][0] == 'datetime-local') {
+ expectedValue = ''
+ } else {
+ expectedValue = '#000000';
+ }
+ } else if (nonTrivialSanitizing.indexOf(testData[i][0]) != -1 &&
+ nonTrivialSanitizing.indexOf(testData[j][0]) != -1) {
+ expectedValue = '';
+ } else if (testData[i][0] == 'number' || testData[j][0] == 'number') {
+ expectedValue = '42';
+ } else if (testData[i][0] == 'date' || testData[j][0] == 'date') {
+ expectedValue = '2012-12-21';
+ } else if (testData[i][0] == 'time' || testData[j][0] == 'time') {
+ expectedValue = '21:21';
+ } else if (testData[i][0] == 'month' || testData[j][0] == 'month') {
+ expectedValue = '2013-03';
+ } else if (testData[i][0] == 'week' || testData[j][0] == 'week') {
+ expectedValue = '2016-W35';
+ } else if (testData[i][0] == 'datetime-local' ||
+ testData[j][0] == 'datetime-local') {
+ expectedValue = '2016-11-07T16:40';
+ } else {
+ expectedValue = "foo";
+ }
+ e.value = expectedValue;
+
+ e.type = testData[j][0];
+ is(e.value, expectedValue, ".value should still return the same value after " +
+ "changing type from " + testData[i][0] + " to " + testData[j][0]);
+ }
+}
+
+// For type='file' .value doesn't behave the same way.
+// We are just going to check that we do not loose the value.
+for (var data of testData) {
+ var e = document.createElement('input');
+ e.type = data[0];
+ e.value = 'foo';
+ e.type = 'file';
+ e.type = data[0];
+
+ if (data[0] == 'range') {
+ is(e.value, '50', ".value should still return the same value after " +
+ "changing type from " + data[0] + " to 'file' then reverting to " + data[0]);
+ } else if (data[0] == 'color') {
+ is(e.value, '#000000', ".value should have been reset to the default color after " +
+ "changing type from " + data[0] + " to 'file' then reverting to " + data[0]);
+ } else if (data[1]) {
+ is(e.value, '', ".value should have been reset to the empty string after " +
+ "changing type from " + data[0] + " to 'file' then reverting to " + data[0]);
+ } else {
+ is(e.value, 'foo', ".value should still return the same value after " +
+ "changing type from " + data[0] + " to 'file' then reverting to " + data[0]);
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug592802.html b/dom/html/test/test_bug592802.html
new file mode 100644
index 000000000..c2c9df9ed
--- /dev/null
+++ b/dom/html/test/test_bug592802.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=592802
+-->
+<head>
+ <title>Test for Bug 592802</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=592802">Mozilla Bug 592802</a>
+<p id="display"></p>
+<div id="content">
+ <input id='a' type='file'>
+ <input id='a2' type='file'>
+</div>
+<button id='b' onclick="document.getElementById('a').click();">Show Filepicker</button>
+<button id='b2' onclick="document.getElementById('a2').click();">Show Filepicker</button>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 592802 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+
+var testData = [
+/* visibility | display | multiple */
+ [ "", "", false ],
+ [ "hidden", "", false ],
+ [ "", "none", false ],
+ [ "", "", true ],
+ [ "hidden", "", true ],
+ [ "", "none", true ],
+];
+
+var testCounter = 0;
+var testNb = testData.length;
+
+function finished()
+{
+ MockFilePicker.cleanup();
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForFocus(function() {
+ // mockFilePicker will simulate a cancel for the first time the file picker will be shown.
+ MockFilePicker.returnValue = MockFilePicker.returnCancel;
+
+ var b2 = document.getElementById('b2');
+ b2.focus(); // Be sure the element is visible.
+ document.getElementById('b2').addEventListener("change", function(aEvent) {
+ aEvent.target.removeEventListener("change", arguments.callee, false);
+ ok(false, "When cancel is received, change should not fire");
+ }, false);
+ b2.click();
+
+ // Now, we can launch tests when file picker isn't canceled.
+ MockFilePicker.useBlobFile();
+ MockFilePicker.returnValue = MockFilePicker.returnOK;
+
+ var b = document.getElementById('b');
+ b.focus(); // Be sure the element is visible.
+
+ document.getElementById('a').addEventListener("change", function(aEvent) {
+ ok(true, "change event correctly sent");
+ ok(aEvent.bubbles, "change event should bubble");
+ ok(!aEvent.cancelable, "change event should not be cancelable");
+ testCounter++;
+
+ if (testCounter >= testNb) {
+ aEvent.target.removeEventListener("change", arguments.callee, false);
+ SimpleTest.executeSoon(finished);
+ } else {
+ var data = testData[testCounter];
+ var a = document.getElementById('a');
+ a.style.visibility = data[0];
+ a.style.display = data[1];
+ a.multiple = data[2];
+
+ SimpleTest.executeSoon(function() {
+ b.click();
+ });
+ }
+ }, false);
+
+ b.click();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug593689.html b/dom/html/test/test_bug593689.html
new file mode 100644
index 000000000..782601f35
--- /dev/null
+++ b/dom/html/test/test_bug593689.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=593689
+-->
+<head>
+ <title>Test for Bug 593689</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=593689">Mozilla Bug 593689</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 593689 **/
+function testWidth(w) {
+ var img = new Image(w);
+ is(img.width, w|0, "Unexpected handling of '" + w + "' width");
+}
+
+testWidth(1);
+testWidth(0);
+testWidth("xxx");
+testWidth(null);
+testWidth(undefined);
+testWidth({});
+testWidth({ valueOf: function() { return 10; } });
+
+function testHeight(h) {
+ var img = new Image(100, h);
+ is(img.height, h|0, "Unexpected handling of '" + h + "' height");
+}
+
+testHeight(1);
+testHeight(0);
+testHeight("xxx");
+testHeight(null);
+testHeight(undefined);
+testHeight({});
+testHeight({ valueOf: function() { return 10; } });
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug595429.html b/dom/html/test/test_bug595429.html
new file mode 100644
index 000000000..74535705e
--- /dev/null
+++ b/dom/html/test/test_bug595429.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=595429
+-->
+<head>
+ <title>Test for Bug 595429</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=595429">Mozilla Bug 595429</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 595429 **/
+
+var fieldset = document.createElement("fieldset");
+
+ok("name" in fieldset, "<fieldset> should have a name IDL attribute");
+
+var testData = [
+ "",
+ " ",
+ "foo",
+ "foo bar",
+];
+
+is(fieldset.getAttribute("name"), null,
+ "By default, name content attribute should be null");
+is(fieldset.name, "",
+ "By default, name IDL attribute should be the empty string");
+
+for (var data of testData) {
+ fieldset.setAttribute("name", data);
+ is(fieldset.getAttribute("name"), data,
+ "name content attribute should be " + data);
+ is(fieldset.name, data, "name IDL attribute should be " + data);
+
+ fieldset.setAttribute("name", "");
+ fieldset.name = data;
+ is(fieldset.getAttribute("name"), data,
+ "name content attribute should be " + data);
+ is(fieldset.name, data, "name IDL attribute should be " + data);
+}
+
+fieldset.removeAttribute("name");
+is(fieldset.getAttribute("name"), null,
+ "name content attribute should be null");
+is(fieldset.name, "", "name IDL attribute should be the empty string");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug595447.html b/dom/html/test/test_bug595447.html
new file mode 100644
index 000000000..015af69d4
--- /dev/null
+++ b/dom/html/test/test_bug595447.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=595447
+-->
+<head>
+ <title>Test for Bug 595447</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=595447">Mozilla Bug 595447</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 595447 **/
+
+var fieldset = document.createElement("fieldset");
+
+ok("type" in fieldset, "fieldset element should have a type IDL attribute");
+is(fieldset.type, "fieldset", "fieldset.type should return 'fieldset'");
+fieldset.type = "foo";
+is(fieldset.type, "fieldset", "fieldset.type is readonly");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug595449.html b/dom/html/test/test_bug595449.html
new file mode 100644
index 000000000..14d5e5ced
--- /dev/null
+++ b/dom/html/test/test_bug595449.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=595449
+-->
+<head>
+ <title>Test for Bug 595449</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=595449">Mozilla Bug 595449</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 595449 **/
+
+var fieldset = document.createElement("fieldset");
+
+ok("elements" in fieldset,
+ "fieldset element should have an 'elements' IDL attribute");
+
+ok(fieldset.elements instanceof HTMLCollection,
+ "fieldset.elements should be an instance of HTMLCollection");
+
+// https://www.w3.org/Bugs/Public/show_bug.cgi?id=23356
+todo(fieldset.elements instanceof HTMLFormControlsCollection,
+ "fieldset.elements should be an instance of HTMLFormControlsCollection");
+
+is(fieldset.elements.length, 0, "Nothing should be in fieldset.elements");
+
+var oldElements = fieldset.elements;
+
+is(fieldset.elements, oldElements,
+ "fieldset.elements should always return the same object");
+
+var tmpElement = document.createElement("input");
+
+fieldset.appendChild(tmpElement);
+
+is(fieldset.elements.length, 1,
+ "fieldset.elements should now contain one element");
+
+is(fieldset.elements[0], tmpElement,
+ "fieldset.elements[0] should be the input element");
+
+tmpElement.name = "foo";
+is(fieldset.elements.foo, tmpElement,
+ "we should be able to access to an element using it's name as a property on .elements");
+
+is(fieldset.elements, oldElements,
+ "fieldset.elements should always return the same object");
+
+fieldset.removeChild(tmpElement);
+
+var testData = [
+ [ "<input>", 1 , [ HTMLInputElement ] ],
+ [ "<button></button>", 1, [ HTMLButtonElement ] ],
+ [ "<button><input></button>", 2, [ HTMLButtonElement, HTMLInputElement ] ],
+ [ "<object>", 1, [ HTMLObjectElement ] ],
+ [ "<output></output>", 1, [ HTMLOutputElement ] ],
+ [ "<select></select>", 1, [ HTMLSelectElement ] ],
+ [ "<select><option>foo</option></select>", 1, [ HTMLSelectElement ] ],
+ [ "<select><option>foo</option><input></select>", 2, [ HTMLSelectElement, HTMLInputElement ] ],
+ [ "<textarea></textarea>", 1, [ HTMLTextAreaElement ] ],
+ [ "<label>foo</label>", 0 ],
+ [ "<progress>", 0 ],
+ [ "<meter>", 0 ],
+ [ "<keygen>", 1, [ HTMLSelectElement ] ],
+ [ "<legend></legend>", 0 ],
+ [ "<legend><input></legend>", 1, [ HTMLInputElement ] ],
+ [ "<legend><input></legend><legend><input></legend>", 2, [ HTMLInputElement, HTMLInputElement ] ],
+ [ "<legend><input></legend><input>", 2, [ HTMLInputElement, HTMLInputElement ] ],
+ [ "<fieldset></fieldset>", 1, [ HTMLFieldSetElement ] ],
+ [ "<fieldset><input></fieldset>", 2, [ HTMLFieldSetElement, HTMLInputElement ] ],
+ [ "<fieldset><fieldset><input></fieldset></fieldset>", 3, [ HTMLFieldSetElement, HTMLFieldSetElement, HTMLInputElement ] ],
+ [ "<button></button><fieldset></fieldset><input><keygen><object><output></output><select></select><textarea></textarea>", 8, [ HTMLButtonElement, HTMLFieldSetElement, HTMLInputElement, HTMLSelectElement, HTMLObjectElement, HTMLOutputElement, HTMLSelectElement, HTMLTextAreaElement ] ],
+];
+
+for (var data of testData) {
+ fieldset.innerHTML = data[0];
+ is(fieldset.elements.length, data[1],
+ "fieldset.elements should contain " + data[1] + " elements");
+
+ for (var i=0; i<data[1]; ++i) {
+ ok(fieldset.elements[i] instanceof data[2][i],
+ "fieldset.elements[" + i + "] should be instance of " + data[2][i])
+ }
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug596350.html b/dom/html/test/test_bug596350.html
new file mode 100644
index 000000000..a92484ef7
--- /dev/null
+++ b/dom/html/test/test_bug596350.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=596350
+-->
+<head>
+ <title>Test for Bug 596350</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596350">Mozilla Bug 596350</a>
+<p id="display"></p>
+<div id="content">
+ <object></object>
+ <object data="iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMsALGPC/xhBQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9YGARc5KB0XV+IAAAAddEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIFRoZSBHSU1Q72QlbgAAAF1JREFUGNO9zL0NglAAxPEfdLTs4BZM4DIO4C7OwQg2JoQ9LE1exdlYvBBeZ7jqch9//q1uH4TLzw4d6+ErXMMcXuHWxId3KOETnnXXV6MJpcq2MLaI97CER3N0vr4MkhoXe0rZigAAAABJRU5ErkJggg=="></object>
+ <object data="data:text/html,foo"></object>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 596350 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(runTests);
+
+var testData = [
+// Object 0
+ [ 0, null, -1 ],
+ [ 0, "1", 1 ],
+ [ 0, "-1", -1 ],
+ [ 0, "0", 0 ],
+ [ 0, "foo", -1 ],
+// Object 1
+ [ 1, null, -1 ],
+ [ 1, "1", 1 ],
+// Object 2
+ [ 2, null, 0 ],
+ [ 2, "1", 1 ],
+ [ 2, "-1", -1 ],
+];
+
+var objects = document.getElementsByTagName("object");
+
+function runTests()
+{
+ for (var data of testData) {
+ var obj = objects[data[0]];
+
+ if (data[1]) {
+ obj.setAttribute("tabindex", data[1]);
+ }
+
+ is(obj.tabIndex, data[2], "tabIndex value should be " + data[2]);
+
+ obj.removeAttribute("tabindex");
+ }
+
+ SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug596511.html b/dom/html/test/test_bug596511.html
new file mode 100644
index 000000000..e539c5b73
--- /dev/null
+++ b/dom/html/test/test_bug596511.html
@@ -0,0 +1,229 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=596511
+-->
+<head>
+ <title>Test for Bug 596511</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ select:valid { background-color: green; }
+ select:invalid { background-color: red; }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=596511">Mozilla Bug 596511</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 596511 **/
+
+function checkNotSufferingFromBeingMissing(element, aTodo)
+{
+ if (aTodo) {
+ ok = todo;
+ is = todo_is;
+ }
+
+ ok(!element.validity.valueMissing,
+ "Element should not suffer from value missing");
+ ok(element.validity.valid, "Element should be valid");
+ ok(element.checkValidity(), "Element should be valid");
+
+ is(element.validationMessage, "",
+ "Validation message should be the empty string");
+
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(0, 128, 0)", ":valid pseudo-class should apply");
+
+ if (aTodo) {
+ ok = SimpleTest.ok;
+ is = SimpleTest.is;
+ }
+}
+
+function checkSufferingFromBeingMissing(element, aTodo)
+{
+ if (aTodo) {
+ ok = todo;
+ is = todo_is;
+ }
+
+ ok(element.validity.valueMissing, "Element should suffer from value missing");
+ ok(!element.validity.valid, "Element should not be valid");
+ ok(!element.checkValidity(), "Element should not be valid");
+
+ is(element.validationMessage, "Please select an item in the list.",
+ "Validation message is wrong");
+
+ is(window.getComputedStyle(element, null).getPropertyValue('background-color'),
+ "rgb(255, 0, 0)", ":invalid pseudo-class should apply");
+
+ if (aTodo) {
+ ok = SimpleTest.ok;
+ is = SimpleTest.is;
+ }
+}
+
+function checkRequiredAttribute(element)
+{
+ ok('required' in element, "select should have a required attribute");
+
+ ok(!element.required, "select required attribute should be disabled");
+ is(element.getAttribute('required'), null,
+ "select required attribute should be disabled");
+
+ element.required = true;
+ ok(element.required, "select required attribute should be enabled");
+ isnot(element.getAttribute('required'), null,
+ "select required attribute should be enabled");
+
+ element.removeAttribute('required');
+ element.setAttribute('required', '');
+ ok(element.required, "select required attribute should be enabled");
+ isnot(element.getAttribute('required'), null,
+ "select required attribute should be enabled");
+
+ element.removeAttribute('required');
+ ok(!element.required, "select required attribute should be disabled");
+ is(element.getAttribute('required'), null,
+ "select required attribute should be disabled");
+}
+
+function checkRequiredAndOptionalSelectors(element)
+{
+ is(document.querySelector("select:optional"), element,
+ "select should be optional");
+ is(document.querySelector("select:required"), null,
+ "select shouldn't be required");
+
+ element.required = true;
+
+ is(document.querySelector("select:optional"), null,
+ "select shouldn't be optional");
+ is(document.querySelector("select:required"), element,
+ "select should be required");
+
+ element.required = false;
+}
+
+function checkInvalidWhenValueMissing(element)
+{
+ checkNotSufferingFromBeingMissing(select);
+
+ element.required = true;
+ checkSufferingFromBeingMissing(select);
+
+ /**
+ * Non-multiple and size=1.
+ */
+ select.appendChild(new Option());
+ checkSufferingFromBeingMissing(select);
+
+ // When removing the required attribute, element should not be invalid.
+ element.required = false;
+ checkNotSufferingFromBeingMissing(select);
+
+ element.required = true;
+ select.options[0].textContent = "foo";
+ // TODO: having that working would require us to add a mutation observer on
+ // the select element.
+ checkNotSufferingFromBeingMissing(select, true);
+
+ select.remove(0);
+ checkSufferingFromBeingMissing(select);
+
+ select.add(new Option("foo", "foo"), null);
+ checkNotSufferingFromBeingMissing(select);
+
+ select.add(new Option(), null);
+ checkNotSufferingFromBeingMissing(select);
+
+ select.options[1].selected = true;
+ checkSufferingFromBeingMissing(select);
+
+ select.selectedIndex = 0;
+ checkNotSufferingFromBeingMissing(select);
+
+ select.selectedIndex = 1;
+ checkSufferingFromBeingMissing(select);
+
+ select.remove(1);
+ checkNotSufferingFromBeingMissing(select);
+
+ select.options[0].disabled = true;
+ // TODO: having that working would require us to add a mutation observer on
+ // the select element.
+ checkSufferingFromBeingMissing(select, true);
+
+ select.options[0].disabled = false
+ select.remove(0);
+ checkSufferingFromBeingMissing(select);
+
+ var option = new Option("foo", "foo");
+ option.disabled = true;
+ select.add(option, null);
+ select.add(new Option("bar"), null);
+ option.selected = true;
+ checkSufferingFromBeingMissing(select);
+
+ select.remove(0);
+ select.remove(0);
+
+ /**
+ * Non-multiple and size > 1.
+ * Everything should be the same except moving the selection.
+ */
+ select.multiple = false;
+ select.size = 4;
+ checkSufferingFromBeingMissing(select);
+
+ select.add(new Option("", "", true), null);
+ checkSufferingFromBeingMissing(select);
+
+ select.add(new Option("foo", "foo"), null);
+ select.remove(0);
+ checkSufferingFromBeingMissing(select);
+
+ select.options[0].selected = true;
+ checkNotSufferingFromBeingMissing(select);
+
+ select.remove(0);
+
+ /**
+ * Multiple, any size.
+ * We can select more than one element and at least needs a value.
+ */
+ select.multiple = true;
+ select.size = 4;
+ checkSufferingFromBeingMissing(select);
+
+ select.add(new Option("", "", true), null);
+ checkSufferingFromBeingMissing(select);
+
+ select.add(new Option("", "", true), null);
+ checkSufferingFromBeingMissing(select);
+
+ select.add(new Option("foo"), null);
+ checkSufferingFromBeingMissing(select);
+
+ select.options[2].selected = true;
+ checkNotSufferingFromBeingMissing(select);
+}
+
+var select = document.createElement("select");
+var content = document.getElementById('content');
+content.appendChild(select);
+
+checkRequiredAttribute(select);
+checkRequiredAndOptionalSelectors(select);
+checkInvalidWhenValueMissing(select);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug598643.html b/dom/html/test/test_bug598643.html
new file mode 100644
index 000000000..53c1df97c
--- /dev/null
+++ b/dom/html/test/test_bug598643.html
@@ -0,0 +1,80 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=598643
+-->
+<head>
+ <title>Test for Bug 598643</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=598643">Mozilla Bug 598643</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 598643 **/
+
+function createFileWithData(fileName, fileData)
+{
+ return new File([new Blob([fileData], { type: "text/plain" })], fileName);
+}
+
+function testFileControl(aElement)
+{
+ aElement.type = 'file';
+
+ var file = createFileWithData("file_bug598643", "file content");
+ SpecialPowers.wrap(aElement).mozSetFileArray([file]);
+
+ ok(aElement.validity.valid, "the file control should be valid");
+ ok(!aElement.validity.tooLong,
+ "the file control shouldn't suffer from being too long");
+}
+
+var types = [
+ // These types can be too long.
+ [ "text", "email", "password", "url", "search", "tel" ],
+ // These types can't be too long.
+ [ "radio", "checkbox", "submit", "button", "reset", "image", "hidden",
+ 'number', 'range', 'date', 'time', 'color', 'month', 'week',
+ 'datetime-local' ],
+];
+
+var input = document.createElement("input");
+input.maxLength = 1;
+input.value = "foo";
+
+// Too long types.
+for (type of types[0]) {
+ input.type = type
+ if (type == 'email') {
+ input.value = "foo@bar.com";
+ } else if (type == 'url') {
+ input.value = 'http://foo.org';
+ }
+
+ todo(!input.validity.valid, "the element should be invalid [type=" + type + "]");
+ todo(input.validity.tooLong,
+ "the element should suffer from being too long [type=" + type + "]");
+
+ if (type == 'email' || type == 'url') {
+ input.value = 'foo';
+ }
+}
+
+// Not too long types.
+for (type of types[1]) {
+ input.type = type
+ ok(input.validity.valid, "the element should be valid [type=" + type + "]");
+ ok(!input.validity.tooLong,
+ "the element shouldn't suffer from being too long [type=" + type + "]");
+}
+
+testFileControl(input);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug598833-1.html b/dom/html/test/test_bug598833-1.html
new file mode 100644
index 000000000..6b50b8df8
--- /dev/null
+++ b/dom/html/test/test_bug598833-1.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=598833
+-->
+<head>
+ <title>Test for Bug 598833</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=598833">Mozilla Bug 598833</a>
+<p id="display">
+ <fieldset disabled>
+ <select id="s" multiple required>
+ <option>one</option>
+ </select>
+ </fieldset>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 598833 **/
+var s = $("s");
+is(s.matches(":invalid"), false, "Disabled select should not be invalid");
+is(s.matches(":valid"), false, "Disabled select should not be valid");
+var p = s.parentNode;
+p.removeChild(s);
+is(s.matches(":invalid"), true,
+ "Required valueless select not in tree should be invalid");
+is(s.matches(":valid"), false,
+ "Required valueless select not in tree should not be valid");
+p.appendChild(s);
+p.disabled = false;
+is(s.matches(":invalid"), true,
+ "Required valueless select should be invalid");
+is(s.matches(":valid"), false,
+ "Required valueless select should not be valid");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug600155.html b/dom/html/test/test_bug600155.html
new file mode 100644
index 000000000..bb10ddfb7
--- /dev/null
+++ b/dom/html/test/test_bug600155.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=600155
+-->
+<head>
+ <title>Test for Bug 600155</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=600155">Mozilla Bug 600155</a>
+<p id="display"></p>
+<div id='content' style='display:none;'>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 600155 **/
+
+var subjectForConstraintValidation = [ "input", "select", "textarea" ];
+var content = document.getElementById('content');
+
+for (var eName of subjectForConstraintValidation) {
+ var e = document.createElement(eName);
+ content.appendChild(e);
+ e.setAttribute("x-moz-errormessage", "foo");
+ if ("required" in e) {
+ e.required = true;
+ } else {
+ e.setCustomValidity("bar");
+ }
+
+ // At this point, the element is invalid.
+ is(e.validationMessage, "foo",
+ "the validation message should be the author one");
+
+ content.removeChild(e);
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug601030.html b/dom/html/test/test_bug601030.html
new file mode 100644
index 000000000..f4fc5b986
--- /dev/null
+++ b/dom/html/test/test_bug601030.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=601030
+-->
+<head>
+ <title>Test for Bug 601030</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=601030">Mozilla Bug 601030</a>
+<p id="display"></p>
+<div id="content">
+ <iframe src="data:text/html,<input autofocus>"></iframe>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 601030 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ var f = document.createElement("iframe");
+ var content = document.getElementById('content');
+
+ f.addEventListener("load", function() {
+ f.removeEventListener("load", arguments.callee, false);
+ SimpleTest.executeSoon(function() {
+ isnot(document.activeElement, f,
+ "autofocus should not work when another frame is inserted in the document");
+
+ content.removeChild(f);
+ content.removeChild(document.getElementsByTagName('iframe')[0]);
+ f = document.createElement('iframe');
+ f.addEventListener("load", function() {
+ f.removeEventListener("load", arguments.callee, false);
+ isnot(document.activeElement, f,
+ "autofocus should not work in a frame if the top document is already loaded");
+ SimpleTest.finish();
+ }, false);
+ f.src = "data:text/html,<input autofocus>";
+ content.appendChild(f);
+ });
+ }, false);
+
+ f.src = "data:text/html,<input autofocus>";
+ content.appendChild(f);
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug605124-1.html b/dom/html/test/test_bug605124-1.html
new file mode 100644
index 000000000..7c3a8ee9b
--- /dev/null
+++ b/dom/html/test/test_bug605124-1.html
@@ -0,0 +1,107 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=605124
+-->
+<head>
+ <title>Test for Bug 605124</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=605124">Mozilla Bug 605124</a>
+<p id="display"></p>
+<div id="content">
+ <form>
+ <textarea required></textarea>
+ <input required>
+ <select required></select>
+ <button type='submit'></button>
+ </form>
+
+ <table>
+ <form>
+ <tr>
+ <textarea required></textarea>
+ <input required>
+ <select required></select>
+ <button type='submit'></button>
+ </tr>
+ </form>
+ </table>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 605124 **/
+
+function checkPseudoClass(aElement, aExpected)
+{
+ is(aElement.matches(":-moz-ui-invalid"), aExpected,
+ "matches(':-moz-ui-invalid') should return " + aExpected + " for " + aElement);
+}
+
+var os = SpecialPowers.Cc['@mozilla.org/observer-service;1']
+ .getService(SpecialPowers.Ci.nsIObserverService);
+var observers = os.enumerateObservers("invalidformsubmit");
+
+if (observers.hasMoreElements()) {
+ var content = document.getElementById('content');
+ var textarea = document.getElementsByTagName('textarea')[0];
+ var input = document.getElementsByTagName('input')[0];
+ var select = document.getElementsByTagName('select')[0];
+ var button = document.getElementsByTagName('button')[0];
+ var form = document.forms[0];
+
+ checkPseudoClass(textarea, false);
+ checkPseudoClass(input, false);
+ checkPseudoClass(select, false);
+
+ // Try to submit.
+ button.click();
+ checkPseudoClass(textarea, true);
+ checkPseudoClass(input, true);
+ checkPseudoClass(select, true);
+
+ // No longer in the form.
+ content.appendChild(textarea);
+ content.appendChild(input);
+ content.appendChild(select);
+ checkPseudoClass(textarea, false);
+ checkPseudoClass(input, false);
+ checkPseudoClass(select, false);
+
+ // Back in the form.
+ form.appendChild(textarea);
+ form.appendChild(input);
+ form.appendChild(select);
+ checkPseudoClass(textarea, true);
+ checkPseudoClass(input, true);
+ checkPseudoClass(select, true);
+
+ /* Case when elements get orphaned. */
+ var textarea = document.getElementsByTagName('textarea')[1];
+ var input = document.getElementsByTagName('input')[1];
+ var select = document.getElementsByTagName('select')[1];
+ var button = document.getElementsByTagName('button')[1];
+ var form = document.forms[1];
+
+ // Try to submit.
+ button.click();
+ checkPseudoClass(textarea, true);
+ checkPseudoClass(input, true);
+ checkPseudoClass(select, true);
+
+ // Remove the form.
+ document.getElementsByTagName('table')[0].removeChild(form);
+ checkPseudoClass(textarea, false);
+ checkPseudoClass(input, false);
+ checkPseudoClass(select, false);
+} else {
+ todo(false, "No 'invalidformsubmit' observers. Skip test.");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug605124-2.html b/dom/html/test/test_bug605124-2.html
new file mode 100644
index 000000000..8ac9027f5
--- /dev/null
+++ b/dom/html/test/test_bug605124-2.html
@@ -0,0 +1,112 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=605124
+-->
+<head>
+ <title>Test for Bug 605124</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=605124">Mozilla Bug 605124</a>
+<p id="display"></p>
+<div id="content">
+ <input required>
+ <textarea required></textarea>
+ <select required>
+ <option value="">foo</option>
+ <option>bar</option>
+ </select>
+ <select multiple required>
+ <option value="">foo</option>
+ <option>bar</option>
+ </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 605124 **/
+
+function checkPseudoClass(aElement, aExpected)
+{
+ is(aElement.matches(":-moz-ui-invalid"), aExpected,
+ "matches(':-moz-ui-invalid') should return " + aExpected + " for " + aElement);
+}
+
+function checkElement(aElement)
+{
+ checkPseudoClass(aElement, false);
+
+ // Focusing while :-moz-ui-invalid doesn't apply,
+ // the pseudo-class should not apply while typing.
+ aElement.focus();
+ checkPseudoClass(aElement, false);
+ // with keys
+ synthesizeKey('f', {});
+ checkPseudoClass(aElement, false);
+ synthesizeKey('VK_BACK_SPACE', {});
+ checkPseudoClass(aElement, false);
+ // with .value
+ aElement.value = 'f';
+ checkPseudoClass(aElement, false);
+ aElement.value = '';
+ checkPseudoClass(aElement, false);
+
+ aElement.blur();
+ checkPseudoClass(aElement, true);
+
+ // Focusing while :-moz-ui-invalid applies,
+ // the pseudo-class should apply while typing if appropriate.
+ aElement.focus();
+ checkPseudoClass(aElement, true);
+ // with keys
+ synthesizeKey('f', {});
+ checkPseudoClass(aElement, false);
+ synthesizeKey('VK_BACK_SPACE', {});
+ checkPseudoClass(aElement, true);
+ // with .value
+ aElement.value = 'f';
+ checkPseudoClass(aElement, false);
+ aElement.value = '';
+ checkPseudoClass(aElement, true);
+}
+
+function checkSelectElement(aElement)
+{
+ checkPseudoClass(aElement, false);
+
+ // Focusing while :-moz-ui-invalid doesn't apply,
+ // the pseudo-class should not apply while changing selection.
+ aElement.focus();
+ checkPseudoClass(aElement, false);
+
+ aElement.selectedIndex = 1;
+ checkPseudoClass(aElement, false);
+ aElement.selectedIndex = 0;
+ checkPseudoClass(aElement, false);
+
+ aElement.blur();
+ checkPseudoClass(aElement, true);
+
+ // Focusing while :-moz-ui-invalid applies,
+ // the pseudo-class should apply while changing selection if appropriate.
+ aElement.focus();
+ checkPseudoClass(aElement, true);
+
+ aElement.selectedIndex = 1;
+ checkPseudoClass(aElement, false);
+ aElement.selectedIndex = 0;
+ checkPseudoClass(aElement, true);
+}
+
+checkElement(document.getElementsByTagName('input')[0]);
+checkElement(document.getElementsByTagName('textarea')[0]);
+checkSelectElement(document.getElementsByTagName('select')[0]);
+checkSelectElement(document.getElementsByTagName('select')[1]);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug605125-1.html b/dom/html/test/test_bug605125-1.html
new file mode 100644
index 000000000..1a89af7ab
--- /dev/null
+++ b/dom/html/test/test_bug605125-1.html
@@ -0,0 +1,113 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=605125
+-->
+<head>
+ <title>Test for Bug 605125</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=605125">Mozilla Bug 605125</a>
+<p id="display"></p>
+<div id="content">
+ <form id='f1'>
+ <textarea></textarea>
+ <input>
+ <button type='submit'></button>
+ <select></select>
+ </form>
+
+ <table>
+ <form id='f2'>
+ <tr>
+ <textarea></textarea>
+ <input>
+ <button type='submit'></button>
+ <select></select>
+ </tr>
+ </form>
+ </table>
+ <input form='f1' required>
+ <input form='f2' required>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 605125 **/
+
+/**
+ * NOTE: this test is very similar to 605124-1.html.
+ */
+
+function checkPseudoClass(aElement, aExpected)
+{
+ is(aElement.matches(":-moz-ui-valid"), aExpected,
+ "matches(':-moz-ui-valid') should return " + aExpected + " for " + aElement);
+}
+
+var os = SpecialPowers.Cc['@mozilla.org/observer-service;1']
+ .getService(SpecialPowers.Ci.nsIObserverService);
+var observers = os.enumerateObservers("invalidformsubmit");
+
+if (observers.hasMoreElements()) {
+ var content = document.getElementById('content');
+ var textarea = document.getElementsByTagName('textarea')[0];
+ var input = document.getElementsByTagName('input')[0];
+ var button = document.getElementsByTagName('button')[0];
+ var select = document.getElementsByTagName('select')[0];
+ var form = document.forms[0];
+
+ checkPseudoClass(textarea, false);
+ checkPseudoClass(input, false);
+ checkPseudoClass(select, false);
+
+ // Try to submit.
+ button.click();
+ checkPseudoClass(textarea, true);
+ checkPseudoClass(input, true);
+ checkPseudoClass(select, true);
+
+ // No longer in the form.
+ content.appendChild(textarea);
+ content.appendChild(input);
+ content.appendChild(select);
+ checkPseudoClass(textarea, false);
+ checkPseudoClass(input, false);
+ checkPseudoClass(select, false);
+
+ // Back in the form.
+ form.appendChild(textarea);
+ form.appendChild(input);
+ form.appendChild(select);
+ checkPseudoClass(textarea, true);
+ checkPseudoClass(input, true);
+ checkPseudoClass(select, true);
+
+ /* Case when elements get orphaned. */
+ var textarea = document.getElementsByTagName('textarea')[1];
+ var input = document.getElementsByTagName('input')[1];
+ var button = document.getElementsByTagName('button')[1];
+ var select = document.getElementsByTagName('select')[1];
+ var form = document.forms[1];
+
+ // Try to submit.
+ button.click();
+ checkPseudoClass(textarea, true);
+ checkPseudoClass(input, true);
+ checkPseudoClass(select, true);
+
+ // Remove the form.
+ document.getElementsByTagName('table')[0].removeChild(form);
+ checkPseudoClass(textarea, false);
+ checkPseudoClass(input, false);
+ checkPseudoClass(select, false);
+} else {
+ todo(false, "No 'invalidformsubmit' observers. Skip test.");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug605125-2.html b/dom/html/test/test_bug605125-2.html
new file mode 100644
index 000000000..4d5c4a46a
--- /dev/null
+++ b/dom/html/test/test_bug605125-2.html
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=605125
+-->
+<head>
+ <title>Test for Bug 605125</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=605125">Mozilla Bug 605125</a>
+<p id="display"></p>
+<div id="content">
+ <input>
+ <textarea></textarea>
+ <select>
+ <option value="">foo</option>
+ <option>bar</option>
+ </select>
+ <select multiple>
+ <option value="">foo</option>
+ <option>bar</option>
+ </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 605125 **/
+
+function checkPseudoClass(aElement, aExpected)
+{
+ is(aElement.matches(":-moz-ui-valid"), aExpected,
+ "matches(':-moz-ui-valid') should return " + aExpected + " for " + aElement);
+}
+
+function checkElement(aElement)
+{
+ checkPseudoClass(aElement, false);
+
+ // Focusing while :-moz-ui-valid doesn't apply,
+ // the pseudo-class should not apply while typing.
+ aElement.focus();
+ checkPseudoClass(aElement, false);
+ // with keys
+ synthesizeKey('f', {});
+ checkPseudoClass(aElement, false);
+ synthesizeKey('VK_BACK_SPACE', {});
+ checkPseudoClass(aElement, false);
+ // with .value
+ aElement.value = 'f';
+ checkPseudoClass(aElement, false);
+ aElement.value = '';
+ checkPseudoClass(aElement, false);
+
+ aElement.blur();
+ checkPseudoClass(aElement, true);
+
+ // Focusing while :-moz-ui-valid applies,
+ // the pseudo-class should apply while typing if appropriate.
+ aElement.focus();
+ checkPseudoClass(aElement, true);
+ // with keys
+ synthesizeKey('f', {});
+ checkPseudoClass(aElement, true);
+ synthesizeKey('VK_BACK_SPACE', {});
+ checkPseudoClass(aElement, true);
+ // with .value
+ aElement.value = 'f';
+ checkPseudoClass(aElement, true);
+ aElement.value = '';
+ checkPseudoClass(aElement, true);
+
+ aElement.blur();
+ aElement.required = true;
+ checkPseudoClass(aElement, false);
+
+ // Focusing while :-moz-ui-invalid applies,
+ // the pseudo-class should apply while typing if appropriate.
+ aElement.focus();
+ checkPseudoClass(aElement, false);
+ // with keys
+ synthesizeKey('f', {});
+ checkPseudoClass(aElement, true);
+ synthesizeKey('VK_BACK_SPACE', {});
+ checkPseudoClass(aElement, false);
+ // with .value
+ aElement.value = 'f';
+ checkPseudoClass(aElement, true);
+ aElement.value = '';
+ checkPseudoClass(aElement, false);
+}
+
+function checkSelectElement(aElement)
+{
+ checkPseudoClass(aElement, false);
+
+ // Focusing while :-moz-ui-valid doesn't apply,
+ // the pseudo-class should not apply while changing selection.
+ aElement.focus();
+ checkPseudoClass(aElement, false);
+
+ aElement.selectedIndex = 1;
+ checkPseudoClass(aElement, false);
+ aElement.selectedIndex = 0;
+ checkPseudoClass(aElement, false);
+
+ aElement.blur();
+ checkPseudoClass(aElement, true);
+
+ // Focusing while :-moz-ui-valid applies,
+ // the pseudo-class should apply while changing selection if appropriate.
+ aElement.focus();
+ checkPseudoClass(aElement, true);
+
+ aElement.selectedIndex = 1;
+ checkPseudoClass(aElement, true);
+ aElement.selectedIndex = 0;
+ checkPseudoClass(aElement, true);
+
+ aElement.blur();
+ aElement.required = true;
+ checkPseudoClass(aElement, false);
+
+ // Focusing while :-moz-ui-invalid applies,
+ // the pseudo-class should apply while changing selection if appropriate.
+ aElement.focus();
+ checkPseudoClass(aElement, false);
+
+ aElement.selectedIndex = 1;
+ checkPseudoClass(aElement, true);
+ aElement.selectedIndex = 0;
+ checkPseudoClass(aElement, false);
+}
+
+checkElement(document.getElementsByTagName('input')[0]);
+checkElement(document.getElementsByTagName('textarea')[0]);
+checkSelectElement(document.getElementsByTagName('select')[0]);
+checkSelectElement(document.getElementsByTagName('select')[1]);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug606817.html b/dom/html/test/test_bug606817.html
new file mode 100644
index 000000000..3de26efc0
--- /dev/null
+++ b/dom/html/test/test_bug606817.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=606817
+-->
+<head>
+ <title>Test for Bug 606817</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=606817">Mozilla Bug 606817</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 606817 **/
+
+var messageMaxLength = 256;
+
+function checkMessage(aInput, aMsg, aWithTerminalPeriod)
+{
+ ok(aInput.validationMessage != aMsg,
+ "Original content-defined message should have been truncate");
+ is(aInput.validationMessage.length - aInput.validationMessage.indexOf("_42_"),
+ aWithTerminalPeriod ? messageMaxLength+1 : messageMaxLength,
+ "validation message should be 256 characters length");
+}
+
+var input = document.createElement("input");
+
+var msg = "";
+for (var i=0; i<75; ++i) {
+ msg += "_42_";
+}
+// msg is now 300 chars long
+
+// Testing with setCustomValidity().
+input.setCustomValidity(msg);
+checkMessage(input, msg, false);
+
+// The input is still invalid but x-moz-errormessage will be used as the message.
+input.setAttribute("x-moz-errormessage", msg);
+checkMessage(input, msg, false);
+
+// Cleaning.
+input.setCustomValidity("");
+input.removeAttribute("x-moz-errormessage");
+
+// Testing with pattern and titl.
+input.pattern = "[0-9]*";
+input.value = "foo";
+input.title = msg;
+checkMessage(input, msg, true);
+
+// Cleaning.
+input.removeAttribute("pattern");
+input.removeAttribute("title");
+input.value = "";
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug607145.html b/dom/html/test/test_bug607145.html
new file mode 100644
index 000000000..f32fff18f
--- /dev/null
+++ b/dom/html/test/test_bug607145.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=607145
+-->
+<head>
+ <title>Test for Bug 607145</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=607145">Mozilla Bug 607145</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 607145 **/
+
+/**
+ * This is not really reflecting an URL as the HTML5 specs want to.
+ * It's how .action is reflected in Gecko (might change later).
+ *
+ * If this changes, add reflectURL for "formAction" in
+ * dom/html/test/forms/test_input_attributes_reflection.html and
+ * "action" in
+ * dom/html/test/forms/test_form_attributes_reflection.html
+ */
+function reflectURL(aElement, aAttr)
+{
+ var idl = aAttr;
+ var attr = aAttr.toLowerCase();
+ var elmtName = aElement.tagName.toLowerCase();
+
+ ok(idl in aElement, idl + " should be available in " + elmtName);
+
+ // Default values.
+ is(aElement[idl], "", "." + idl + " default value should be the empty string");
+ is(aElement.getAttribute(attr), null,
+ "@" + attr + " default value should be null");
+
+ var previousDir = location.href.replace(/test\/[^\/]*$/, "");
+ var dir = location.href.replace(/test_bug607145.html[^\/]*$/, "");
+ var doc = location.href.replace(/\.html.*/, ".html")
+ var values = [
+ /* value to set, resolved value */
+ [ "foo.html", dir + "foo.html" ],
+ [ "data:text/html,<html></html>", "data:text/html,<html></html>" ],
+ [ "http://example.org/", "http://example.org/" ],
+ [ "//example.org/", "http://example.org/" ],
+ [ "?foo=bar", doc + "?foo=bar" ],
+ [ "#foo", location.href + "#foo" ],
+ [ "", "" ], // TODO: doesn't follow the specs, should be location.href.
+ [ " ", location.href ],
+ [ "../", previousDir ],
+ [ "...", dir + "..." ],
+ // invalid URL
+ [ "http://a b/", "http://a b/" ], // TODO: doesn't follow the specs, should be "".
+ ];
+
+ for (var value of values) {
+ aElement[idl] = value[0];
+ is(aElement[idl], value[1], "." + idl + " value should be " + value[1]);
+ is(aElement.getAttribute(attr), value[0],
+ "@" + attr + " value should be " + value[0]);
+ }
+
+ for (var value of values) {
+ aElement.setAttribute(attr, value[0]);
+ is(aElement[idl], value[1], "." + idl + " value should be " + value[1]);
+ is(aElement.getAttribute(attr), value[0],
+ "@" + attr + " value should be " + value[0]);
+ }
+}
+
+reflectURL(document.createElement("form"), "action");
+reflectURL(document.createElement("input"), "formAction");
+reflectURL(document.createElement("button"), "formAction");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug610212.html b/dom/html/test/test_bug610212.html
new file mode 100644
index 000000000..56bb18dc1
--- /dev/null
+++ b/dom/html/test/test_bug610212.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=610212
+-->
+<head>
+ <title>Test for Bug 610212</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=610212">Mozilla Bug 610212</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 610212 **/
+
+var canvas = document.createElement('canvas');
+
+reflectUnsignedInt({
+ element: canvas,
+ attribute: "width",
+ nonZero: false,
+ defaultValue: 300,
+});
+
+reflectUnsignedInt({
+ element: canvas,
+ attribute: "height",
+ nonZero: false,
+ defaultValue: 150,
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug610687.html b/dom/html/test/test_bug610687.html
new file mode 100644
index 000000000..f319685ed
--- /dev/null
+++ b/dom/html/test/test_bug610687.html
@@ -0,0 +1,201 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=610687
+-->
+<head>
+ <title>Test for Bug 610687</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=610687">Mozilla Bug 610687</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <form>
+ <input type='radio' name='a'>
+ <input type='radio' name='a'>
+ <input type='radio' name='b'>
+ </form>
+ <input type='radio' name='a'>
+ <input type='radio' name='a'>
+ <input type='radio' name='b'>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 610687 **/
+
+function checkPseudoClasses(aElement, aValid, aValidUI, aInvalidUI)
+{
+ if (aValid) {
+ ok(aElement.matches(":valid"), ":valid should apply");
+ } else {
+ ok(aElement.matches(":invalid"), ":invalid should apply");
+ }
+
+ is(aElement.matches(":-moz-ui-valid"), aValidUI,
+ aValid ? ":-moz-ui-valid should apply" : ":-moz-ui-valid should not apply");
+
+ is(aElement.matches(":-moz-ui-invalid"), aInvalidUI,
+ aInvalidUI ? ":-moz-ui-invalid should apply" : ":-moz-ui-invalid should not apply");
+
+ if (aInvalidUI && (aValid || aValidUI)) {
+ ok(false, ":invalid can't apply with :valid or :-moz-valid-ui");
+ }
+}
+
+/**
+ * r1 and r2 should be in the same group.
+ * r3 should be in another group.
+ * form can be null.
+ */
+function checkRadios(r1, r2, r3, form)
+{
+ // Default state.
+ checkPseudoClasses(r1, true, false, false);
+ checkPseudoClasses(r2, true, false, false);
+ checkPseudoClasses(r3, true, false, false);
+
+ // Suffering from being missing (without ui-invalid).
+ r1.required = true;
+ checkPseudoClasses(r1, false, false, false);
+ checkPseudoClasses(r2, false, false, false);
+ checkPseudoClasses(r3, true, false, false);
+
+ // Suffering from being missing (with ui-invalid).
+ r1.checked = false;
+ checkPseudoClasses(r1, false, false, true);
+ checkPseudoClasses(r2, false, false, true);
+ checkPseudoClasses(r3, true, false, false);
+
+ // Do not suffer from being missing (with ui-valid).
+ r1.checked = true;
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, true, true, false);
+ checkPseudoClasses(r3, true, false, false);
+
+ // Do not suffer from being missing (with ui-valid).
+ r1.checked = false;
+ r1.required = false;
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, true, true, false);
+ checkPseudoClasses(r3, true, false, false);
+
+ // Suffering from being missing (with ui-invalid) with required set on one radio
+ // and the checked state changed on another.
+ r1.required = true;
+ r2.checked = false;
+ checkPseudoClasses(r1, false, false, true);
+ checkPseudoClasses(r2, false, false, true);
+ checkPseudoClasses(r3, true, false, false);
+
+ // Do not suffer from being missing (with ui-valid) by checking the radio which
+ // hasn't the required attribute.
+ r2.checked = true;
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, true, true, false);
+ checkPseudoClasses(r3, true, false, false);
+
+ // .setCustomValidity() should not affect the entire group.
+ r1.checked = r2.checked = r3.checked = false;
+ r1.required = false;
+ r1.setCustomValidity('foo');
+ checkPseudoClasses(r1, false, false, true);
+ checkPseudoClasses(r2, true, true, false);
+ checkPseudoClasses(r3, true, true, false);
+
+ r1.setCustomValidity('');
+ r2.setCustomValidity('foo');
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, false, false, true);
+ checkPseudoClasses(r3, true, true, false);
+
+ r2.setCustomValidity('');
+ r3.setCustomValidity('foo');
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, true, true, false);
+ checkPseudoClasses(r3, false, false, true);
+
+ // Removing the radio with the required attribute should make the group valid.
+ r1.setCustomValidity('');
+ r2.setCustomValidity('');
+ r1.required = false;
+ r2.required = true;
+ r1.checked = r2.checked = false;
+ checkPseudoClasses(r1, false, false, true);
+ checkPseudoClasses(r2, false, false, true);
+
+ var p = r2.parentNode;
+ p.removeChild(r2);
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, false, false, true);
+
+ p.appendChild(r2);
+ checkPseudoClasses(r1, false, false, true);
+ checkPseudoClasses(r2, false, false, true);
+
+ // Adding a radio element to an invalid group should make it invalid.
+ p.removeChild(r1);
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, false, false, true);
+
+ p.appendChild(r1);
+ checkPseudoClasses(r1, false, false, true);
+ checkPseudoClasses(r2, false, false, true);
+
+ // Adding a checked radio element to an invalid group should make it valid.
+ p.removeChild(r1);
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, false, false, true);
+
+ r1.checked = true;
+ p.appendChild(r1);
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, true, true, false);
+ r1.checked = false;
+
+ // Adding an invalid radio element by changing the name attribute.
+ r2.name = 'c';
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, false, false, true);
+
+ r2.name = 'a';
+ checkPseudoClasses(r1, false, false, true);
+ checkPseudoClasses(r2, false, false, true);
+
+ // Adding an element to an invalid radio group by changing the name attribute.
+ r1.name = 'c';
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, false, false, true);
+
+ r1.name = 'a';
+ checkPseudoClasses(r1, false, false, true);
+ checkPseudoClasses(r2, false, false, true);
+
+ // Adding a checked element to an invalid radio group with the name attribute.
+ r1.name = 'c';
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, false, false, true);
+
+ r1.checked = true;
+ r1.name = 'a';
+ checkPseudoClasses(r1, true, true, false);
+ checkPseudoClasses(r2, true, true, false);
+ r1.checked = false;
+}
+
+var r1 = document.getElementsByTagName('input')[0];
+var r2 = document.getElementsByTagName('input')[1];
+var r3 = document.getElementsByTagName('input')[2];
+checkRadios(r1, r2, r3);
+
+r1 = document.getElementsByTagName('input')[3];
+r2 = document.getElementsByTagName('input')[4];
+r3 = document.getElementsByTagName('input')[5];
+checkRadios(r1, r2, r3);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug611189.html b/dom/html/test/test_bug611189.html
new file mode 100644
index 000000000..13ca618d6
--- /dev/null
+++ b/dom/html/test/test_bug611189.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=611189
+-->
+<head>
+ <title>Test for Bug 611189</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/WindowSnapshot.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=611189">Mozilla Bug 611189</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 611189 **/
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ var i = document.createElement("input");
+ var b = document.getElementById("content");
+ b.appendChild(i);
+ b.clientWidth; // bind to frame
+ i.focus(); // initialize editor
+ var before = snapshotWindow(window, true);
+ i.value = "L"; // set the value
+ i.style.display = "none";
+ b.clientWidth; // unbind from frame
+ i.value = ""; // set the value without a frame
+ i.style.display = "";
+ b.clientWidth; // rebind to frame
+ is(i.value, "", "Input's value should be correctly updated");
+ var after = snapshotWindow(window, true);
+ ok(compareSnapshots(before, after, true), "The correct value should be rendered inside the control");
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug612730.html b/dom/html/test/test_bug612730.html
new file mode 100644
index 000000000..4c6d906e3
--- /dev/null
+++ b/dom/html/test/test_bug612730.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=612730
+-->
+<head>
+ <title>Test for Bug 612730</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=612730">Mozilla Bug 612730</a>
+<p id="display"></p>
+<div id="content">
+ <select multiple required>
+ <option value="">foo</option>
+ <option value="">bar</option>
+ </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 612730 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest()
+{
+ var select = document.getElementsByTagName('select')[0];
+
+ select.addEventListener("focus", function() {
+ select.removeEventListener("focus", arguments.callee, false);
+
+ isnot(select.selectedIndex, -1, "Something should have been selected");
+
+ ok(!select.matches(":-moz-ui-valid"),
+ ":-moz-ui-valid should not apply");
+ todo(!select.matches(":-moz-ui-invalid"),
+ ":-moz-ui-invalid should not apply");
+
+ SimpleTest.finish();
+ }, false);
+
+ synthesizeMouse(select, 5, 5, {});
+}
+
+SimpleTest.waitForFocus(runTest);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug613019.html b/dom/html/test/test_bug613019.html
new file mode 100644
index 000000000..bb28d108a
--- /dev/null
+++ b/dom/html/test/test_bug613019.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=613019
+-->
+<head>
+ <title>Test for Bug 613019</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613019">Mozilla Bug 613019</a>
+<div id="content">
+ <input type="text" maxlength="2" style="width:200px" value="Test">
+ <textarea maxlength="2" style="width:200px">Test</textarea>
+ <input type="text" minlength="6" style="width:200px" value="Test">
+ <textarea minlength="6" style="width:200px">Test</textarea>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 613019 **/
+
+function testInteractivityOfMaxLength(elem) {
+ // verify that user interactivity is necessary for validity state to apply.
+ is(elem.value, "Test", "Element has incorrect starting value.");
+ is(elem.validity.tooLong, false, "Element should not be tooLong.");
+
+ elem.setSelectionRange(elem.value.length, elem.value.length)
+ elem.focus();
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ is(elem.value, "Tes", "Element value was not changed correctly.");
+ is(elem.validity.tooLong, true, "Element should still be tooLong.");
+
+ synthesizeKey("VK_BACK_SPACE", {});
+ is(elem.value, "Te", "Element value was not changed correctly.");
+ is(elem.validity.tooLong, false, "Element should no longer be tooLong.");
+
+ elem.value = "Test";
+ is(elem.validity.tooLong, false,
+ "Element should not be tooLong after non-interactive value change.");
+}
+
+function testInteractivityOfMinLength(elem) {
+ // verify that user interactivity is necessary for validity state to apply.
+ is(elem.value, "Test", "Element has incorrect starting value.");
+ is(elem.validity.tooLong, false, "Element should not be tooShort.");
+
+ elem.setSelectionRange(elem.value.length, elem.value.length)
+ elem.focus();
+
+ synthesizeKey("e", {});
+ is(elem.value, "Teste", "Element value was not changed correctly.");
+ is(elem.validity.tooShort, true, "Element should still be tooShort.");
+
+ synthesizeKey("d", {});
+ is(elem.value, "Tested", "Element value was not changed correctly.");
+ is(elem.validity.tooShort, false, "Element should no longer be tooShort.");
+
+ elem.value = "Test";
+ is(elem.validity.tooShort, false,
+ "Element should not be tooShort after non-interactive value change.");
+}
+
+function test() {
+ window.getSelection().removeAllRanges();
+ testInteractivityOfMaxLength(document.querySelector("input[type=text][maxlength]"));
+ testInteractivityOfMaxLength(document.querySelector("textarea[maxlength]"));
+ testInteractivityOfMinLength(document.querySelector("input[type=text][minlength]"));
+ testInteractivityOfMinLength(document.querySelector("textarea[minlength]"));
+ SimpleTest.finish();
+}
+
+window.onload = function() {
+ SimpleTest.waitForExplicitFinish();
+ setTimeout(test, 0);
+};
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug613113.html b/dom/html/test/test_bug613113.html
new file mode 100644
index 000000000..3ffe0cf07
--- /dev/null
+++ b/dom/html/test/test_bug613113.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=613113
+-->
+<head>
+ <title>Test for Bug 613113</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613113">Mozilla Bug 613113</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <iframe name='f'></iframe>
+ <form target='f' action="data:text/html,">
+ <output></output>
+ <button></button>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 613113 **/
+
+SimpleTest.waitForExplicitFinish();
+
+var invalidEvent = false;
+
+var form = document.forms[0];
+var button = document.getElementsByTagName('button')[0];
+var output = document.getElementsByTagName('output')[0];
+
+output.addEventListener("invalid", function() {
+ if (invalidEvent) {
+ ok(false, "invalid event has already been caught");
+ } else {
+ invalidEvent = true;
+ ok(true, "invalid event has been caught");
+ setTimeout(function() {
+ SimpleTest.finish();
+ }, 0);
+ }
+}, false);
+
+form.addEventListener("submit", function() {
+ ok(false, "submit event should not have been send");
+}, false);
+
+output.setCustomValidity("foo");
+
+button.click();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug613722.html b/dom/html/test/test_bug613722.html
new file mode 100644
index 000000000..3067c6476
--- /dev/null
+++ b/dom/html/test/test_bug613722.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=613722
+-->
+<head>
+ <title>Test for Bug 613722</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613722">Mozilla Bug 613722</a>
+<p id="display"></p>
+<div id="content">
+ <embed src="test_plugin.tst" hidden>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 613722 **/
+
+var rect = document.getElementsByTagName('embed')[0].getBoundingClientRect();
+
+var hasFrame = rect.left != 0 || rect.right != 0 || rect.top != 0 ||
+ rect.bottom != 0;
+
+ok(hasFrame, "embed should have a frame with hidden set");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug613979.html b/dom/html/test/test_bug613979.html
new file mode 100644
index 000000000..cb77b333e
--- /dev/null
+++ b/dom/html/test/test_bug613979.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=613979
+-->
+<head>
+ <title>Test for Bug 613979</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=613979">Mozilla Bug 613979</a>
+<p id="display"></p>
+<div id="content">
+ <input required>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 613979 **/
+
+var testNum = 0;
+var input = document.getElementsByTagName('input')[0];
+
+input.addEventListener("input", function() {
+ if (testNum == 0) {
+ ok(input.validity.valid, "input should be valid");
+ testNum++;
+ SimpleTest.executeSoon(function() {
+ synthesizeKey("VK_BACK_SPACE", {});
+ });
+ } else if (testNum == 1) {
+ ok(!input.validity.valid, "input should not be valid");
+ input.removeEventListener("input", arguments.callee, false);
+ SimpleTest.finish();
+ }
+}, false);
+
+SimpleTest.waitForExplicitFinish();
+
+SimpleTest.waitForFocus(function() {
+ input.focus();
+ synthesizeKey("a", {});
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug615595.html b/dom/html/test/test_bug615595.html
new file mode 100644
index 000000000..b662103cd
--- /dev/null
+++ b/dom/html/test/test_bug615595.html
Binary files differ
diff --git a/dom/html/test/test_bug615833.html b/dom/html/test/test_bug615833.html
new file mode 100644
index 000000000..f72245d4c
--- /dev/null
+++ b/dom/html/test/test_bug615833.html
@@ -0,0 +1,156 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=615697
+-->
+<head>
+ <title>Test for Bug 615697</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=615697">Mozilla Bug 615697</a>
+<p id="display"></p>
+<div id="content">
+ <input>
+ <textarea></textarea>
+ <input type='radio'>
+ <input type='checkbox'>
+ <select>
+ <option>foo</option>
+ <option>bar</option>
+ </select>
+ <select multiple size='1'>
+ <option>tulip</option>
+ </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 615697 **/
+
+/**
+ * This test is making all elements trigger 'change' event.
+ * You should read the test from bottom to top:
+ * events are registered from the last one to the first one.
+ *
+ * Sometimes, elements are focused before a click. This might sound useless
+ * but it guarantees to have the element visible before simulating the click.
+ */
+
+var input = document.getElementsByTagName('input')[0];
+var textarea = document.getElementsByTagName('textarea')[0];
+var radio = document.getElementsByTagName('input')[1];
+var checkbox= document.getElementsByTagName('input')[2];
+var select = document.getElementsByTagName('select')[0];
+var selectMultiple = document.getElementsByTagName('select')[1];
+
+function checkChangeEvent(aEvent)
+{
+ ok(aEvent.bubbles, "change event should bubble");
+ ok(!aEvent.cancelable, "change event shouldn't be cancelable");
+}
+
+selectMultiple.addEventListener("change", function(aEvent) {
+ selectMultiple.removeEventListener("change", arguments.callee, false);
+ checkChangeEvent(aEvent);
+ SimpleTest.finish();
+}, false);
+
+selectMultiple.addEventListener("focus", function() {
+ selectMultiple.removeEventListener("focus", arguments.callee, false);
+ SimpleTest.executeSoon(function () {
+ synthesizeMouseAtCenter(selectMultiple, {});
+ });
+}, false);
+
+select.addEventListener("change", function(aEvent) {
+ select.removeEventListener("change", arguments.callee, false);
+ checkChangeEvent(aEvent);
+ selectMultiple.focus();
+}, false);
+
+select.addEventListener("keyup", function() {
+ select.removeEventListener("keyup", arguments.callee, false);
+ select.blur();
+}, false);
+
+select.addEventListener("focus", function() {
+ select.removeEventListener("focus", arguments.callee, false);
+ SimpleTest.executeSoon(function () {
+ synthesizeKey("VK_DOWN", {});
+ });
+}, false);
+
+checkbox.addEventListener("change", function(aEvent) {
+ checkbox.removeEventListener("change", arguments.callee, false);
+ checkChangeEvent(aEvent);
+ select.focus();
+}, false);
+
+checkbox.addEventListener("focus", function() {
+ checkbox.removeEventListener("focus", arguments.callee, false);
+ SimpleTest.executeSoon(function () {
+ synthesizeMouseAtCenter(checkbox, {});
+ });
+}, false);
+
+radio.addEventListener("change", function(aEvent) {
+ radio.removeEventListener("change", arguments.callee, false);
+ checkChangeEvent(aEvent);
+ checkbox.focus();
+}, false);
+
+radio.addEventListener("focus", function() {
+ radio.removeEventListener("focus", arguments.callee, false);
+ SimpleTest.executeSoon(function () {
+ synthesizeMouseAtCenter(radio, {});
+ });
+}, false);
+
+textarea.addEventListener("change", function(aEvent) {
+ textarea.removeEventListener("change", arguments.callee, false);
+ checkChangeEvent(aEvent);
+ radio.focus();
+}, false);
+
+textarea.addEventListener("input", function() {
+ textarea.removeEventListener("input", arguments.callee, false);
+ textarea.blur();
+}, false);
+
+textarea.addEventListener("focus", function() {
+ textarea.removeEventListener("focus", arguments.callee, false);
+ SimpleTest.executeSoon(function () {
+ synthesizeKey('f', {});
+ });
+}, false);
+
+input.addEventListener("change", function(aEvent) {
+ input.removeEventListener("change", arguments.callee, false);
+ checkChangeEvent(aEvent);
+ textarea.focus();
+}, false);
+
+input.addEventListener("input", function() {
+ input.removeEventListener("input", arguments.callee, false);
+ input.blur();
+}, false);
+
+input.addEventListener("focus", function() {
+ input.removeEventListener("focus", arguments.callee, false);
+ SimpleTest.executeSoon(function () {
+ synthesizeKey('f', {});
+ });
+}, false);
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ input.focus();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug617528.html b/dom/html/test/test_bug617528.html
new file mode 100644
index 000000000..c8cd62568
--- /dev/null
+++ b/dom/html/test/test_bug617528.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=617528
+-->
+<head>
+ <title>Test for Bug 617528</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=617528">Mozilla Bug 617528</a>
+<p id="display"></p>
+<div id="content">
+ <menu>
+ <menuitem id="checkbox" type="checkbox" label="Checkbox" checked></menuitem>
+ <menuitem id="radio1" type="radio" label="Radio1" checked></menuitem>
+ <menuitem id="radio2" type="radio" label="Radio2"></menuitem>
+ </menu>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 617528 **/
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ function click(element, preventDefault, checked) {
+ function handleClick(event) {
+ is(this.checked, checked,
+ "checking .checked (" + this.id + ")");
+ if (preventDefault)
+ event.preventDefault();
+ }
+ element.addEventListener("click", handleClick);
+ element.click();
+ element.removeEventListener("click", handleClick);
+ }
+
+ function verify(elements, data) {
+ for (var i = 0; i < elements.length; i++) {
+ var element = elements[i];
+ is(element.checked, data[i*2],
+ "checking .checked (" + element.id + ")");
+ is(element.defaultChecked, data[i*2+1],
+ 'checking .defaultChecked (' + element.id + ")");
+ }
+ }
+
+ var checkbox = document.getElementById("checkbox");
+ click(checkbox, false, false);
+ verify([checkbox], [false, true]);
+
+ click(checkbox, true, true);
+ verify([checkbox], [false, true]);
+
+ var radio1 = document.getElementById("radio1");
+ var radio2 = document.getElementById("radio2");
+ click(radio2, false, true);
+ verify([radio1, radio2], [false, true,
+ true, false]);
+
+ click(radio1, true, true);
+ verify([radio1, radio2], [false, true,
+ true, false]);
+
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug618948.html b/dom/html/test/test_bug618948.html
new file mode 100644
index 000000000..258041bdb
--- /dev/null
+++ b/dom/html/test/test_bug618948.html
@@ -0,0 +1,88 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=618948
+-->
+<head>
+ <title>Test for Bug 618948</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=618948">Mozilla Bug 618948</a>
+<p id="display"></p>
+<div id="content">
+ <form>
+ <input type='email' id='i'>
+ <button>submit</button>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 618948 **/
+
+var events = ["focus", "input", "change", "invalid" ];
+
+var handled = ({});
+
+function eventHandler(event)
+{
+ dump("\n" + event.type + "\n");
+ handled[event.type] = true;
+}
+
+function beginTest()
+{
+ for (var e of events) {
+ handled[e] = false;
+ }
+
+ i.focus();
+}
+
+function endTest()
+{
+ for (var e of events) {
+ ok(handled[e], "on" + e + " should have been called");
+ }
+
+ SimpleTest.finish();
+}
+
+var i = document.getElementsByTagName('input')[0];
+var b = document.getElementsByTagName('button')[0];
+
+i.onfocus = function(event) {
+ eventHandler(event);
+ synthesizeKey('f', {});
+ i.onfocus = null;
+};
+
+i.oninput = function(event) {
+ eventHandler(event);
+ b.focus();
+ i.oninput = null;
+};
+
+i.onchange = function(event) {
+ eventHandler(event);
+ i.onchange = null;
+ synthesizeMouseAtCenter(b, {});
+};
+
+i.oninvalid = function(event) {
+ eventHandler(event);
+ i.oninvalid = null;
+ endTest();
+};
+
+SimpleTest.waitForExplicitFinish();
+
+SimpleTest.waitForFocus(beginTest);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug619278.html b/dom/html/test/test_bug619278.html
new file mode 100644
index 000000000..88e4952ec
--- /dev/null
+++ b/dom/html/test/test_bug619278.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=619278
+-->
+<head>
+ <title>Test for Bug 619278</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=619278">Mozilla Bug 619278</a>
+<p id="display"></p>
+<div id="content">
+ <form>
+ <input required><button>submit</button>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 619278 **/
+
+function doElementMatchesSelector(aElement, aSelector)
+{
+ ok(aElement.matches(aSelector),
+ aSelector + " should match for " + aElement);
+}
+
+var e = document.forms[0].elements[0];
+
+e.addEventListener("invalid", function(event) {
+ e.addEventListener("invalid", arguments.callee, false);
+
+ SimpleTest.executeSoon(function() {
+ doElementMatchesSelector(e, ":-moz-ui-invalid");
+ SimpleTest.finish();
+ });
+}, false);
+
+e.addEventListener("focus", function() {
+ e.removeEventListener("focus", arguments.callee, false);
+
+ SimpleTest.executeSoon(function() {
+ synthesizeKey("VK_RETURN", {});
+ });
+}, false);
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ e.focus();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug622558.html b/dom/html/test/test_bug622558.html
new file mode 100644
index 000000000..025eeca03
--- /dev/null
+++ b/dom/html/test/test_bug622558.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=622558
+-->
+<head>
+ <title>Test for Bug 622558</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=622558">Mozilla Bug 622558</a>
+<p id="display"></p>
+<div id="content">
+ <form>
+ <input>
+ <textarea></textarea>
+ <select><option>foo</option></select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+// Bug 940203
+if (navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 1);
+}
+
+/** Test for Bug 622558 **/
+
+function checkSelectors(aElement)
+{
+ ok(aElement.matches(":-moz-ui-invalid"),
+ ":-moz-ui-invalid should match for " + aElement);
+ ok(!aElement.matches(":-moz-ui-valid"),
+ ":-moz-ui-valid should not match for " + aElement);
+}
+
+var input = document.getElementsByTagName('input')[0];
+var textarea = document.getElementsByTagName('textarea')[0];
+var select = document.getElementsByTagName('select')[0];
+
+select.addEventListener("focus", function() {
+ select.removeEventListener("focus", arguments.callee, false);
+
+ SimpleTest.executeSoon(function() {
+ select.setCustomValidity('foo');
+
+ SimpleTest.executeSoon(function() {
+ checkSelectors(select);
+ SimpleTest.finish();
+ });
+ });
+}, false);
+
+textarea.addEventListener("focus", function() {
+ textarea.removeEventListener("focus", arguments.callee, false);
+
+ SimpleTest.executeSoon(function() {
+ textarea.setCustomValidity('foo');
+
+ SimpleTest.executeSoon(function() {
+ checkSelectors(textarea);
+ select.focus();
+ });
+ });
+}, false);
+
+input.addEventListener("focus", function() {
+ input.removeEventListener("focus", arguments.callee, false);
+
+ SimpleTest.executeSoon(function() {
+ input.setCustomValidity('foo');
+
+ SimpleTest.executeSoon(function() {
+ checkSelectors(input);
+ textarea.focus();
+ });
+ });
+}, false);
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ input.focus();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug622597.html b/dom/html/test/test_bug622597.html
new file mode 100644
index 000000000..c0b25ae9e
--- /dev/null
+++ b/dom/html/test/test_bug622597.html
@@ -0,0 +1,115 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=622597
+-->
+<head>
+ <title>Test for Bug 622597</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=622597">Mozilla Bug 622597</a>
+<p id="display"></p>
+<div id="content">
+ <form>
+ <input required>
+ <textarea required></textarea>
+ <select required><option>foo</option><option value="">bar</option></select>
+ <button>submit</button>
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 622597 **/
+
+var form = document.forms[0];
+var input = form.elements[0];
+var textarea = form.elements[1];
+var select = form.elements[2];
+var button = form.elements[3];
+
+function checkPseudoClasses(aElement, aValid, aInvalid)
+{
+ is(aElement.matches(":-moz-ui-valid"), aValid,
+ aValid ? aElement + " should match :-moz-ui-valid"
+ : aElement + " should not match :-moz-ui-valid");
+ is(aElement.matches(":-moz-ui-invalid"), aInvalid,
+ aInvalid ? aElement + " should match :-moz-ui-invalid"
+ : aElement + " should not match :-moz-ui-invalid");
+ if (aValid && aInvalid) {
+ ok(false,
+ aElement + " should not match :-moz-ui-valid AND :-moz-ui-invalid");
+ }
+}
+
+select.addEventListener("focus", function() {
+ select.removeEventListener("focus", arguments.callee, false);
+
+ SimpleTest.executeSoon(function() {
+ form.noValidate = false;
+ SimpleTest.executeSoon(function() {
+ checkPseudoClasses(select, false, true);
+ SimpleTest.finish();
+ });
+ });
+}, false);
+
+textarea.addEventListener("focus", function() {
+ textarea.removeEventListener("focus", arguments.callee, false);
+
+ SimpleTest.executeSoon(function() {
+ form.noValidate = false;
+ SimpleTest.executeSoon(function() {
+ checkPseudoClasses(textarea, false, true);
+ form.noValidate = true;
+ select.selectedIndex = 1;
+ select.focus();
+ });
+ });
+}, false);
+
+input.addEventListener("invalid", function() {
+ input.removeEventListener("invalid", arguments.callee, false);
+
+ input.addEventListener("focus", function() {
+ input.removeEventListener("focus", arguments.callee, false);
+
+ SimpleTest.executeSoon(function() {
+ form.noValidate = false;
+ SimpleTest.executeSoon(function() {
+ checkPseudoClasses(input, false, true);
+ form.noValidate = true;
+ textarea.value = '';
+ textarea.focus();
+ });
+ });
+ }, false);
+
+ SimpleTest.executeSoon(function() {
+ form.noValidate = true;
+ input.blur();
+ input.value = '';
+ input.focus();
+ });
+}, false);
+
+button.addEventListener("focus", function() {
+ button.removeEventListener("focus", arguments.callee, false);
+
+ SimpleTest.executeSoon(function() {
+ synthesizeKey("VK_RETURN", {});
+ });
+}, false);
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ button.focus();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug623291.html b/dom/html/test/test_bug623291.html
new file mode 100644
index 000000000..c61b9213d
--- /dev/null
+++ b/dom/html/test/test_bug623291.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=623291
+-->
+<head>
+ <title>Test for Bug 623291</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=623291">Mozilla Bug 623291</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<input id="textField" onfocus="next()" onblur="done();">
+<button id="b">a button</button>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 623291 **/
+
+function runTest() {
+ document.getElementById("textField").focus();
+}
+
+function next() {
+ synthesizeMouseAtCenter(document.getElementById('b'), {}, window);
+}
+
+function done() {
+ isnot(document.activeElement, document.getElementById("textField"),
+ "TextField should not be active anymore!");
+ SimpleTest.finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(runTest);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug6296.html b/dom/html/test/test_bug6296.html
new file mode 100644
index 000000000..9b4b2fb7c
--- /dev/null
+++ b/dom/html/test/test_bug6296.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=6296
+-->
+<head>
+ <title>Test for Bug 6296</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=6296">Mozilla Bug 6296</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <A HREF="../testdata/test.gif" id="foo" NAME="anchor1" ALT="this is a test of the image
+ attribute">Hi</A>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 6296 **/
+is($("foo").name, "anchor1", "accessing an anchor name should work, and not crash either!")
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug629801.html b/dom/html/test/test_bug629801.html
new file mode 100644
index 000000000..fe3c8d9a9
--- /dev/null
+++ b/dom/html/test/test_bug629801.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=629801
+-->
+<head>
+ <title>Test for Bug 629801</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=629801">Mozilla Bug 629801</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+<div itemscope>
+ This tests itemValue on time elements, first with no datetime attribute, then with no text content,
+ then with both.
+ <time id="t1" itemprop="a">May 10th 2009</time>
+ <time id="t2" itemprop="b" datetime="2009-05-10"></time>
+ <time id="t3" itemprop="c" datetime="2009-05-10">May 10th 2009</time>
+</div>
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 629801 **/
+
+var t1 = document.getElementById("t1"),
+ t2 = document.getElementById("t2"),
+ t3 = document.getElementById("t3"),
+ t4 = document.createElement("time");
+
+// .dateTime IDL
+is(t1.dateTime, "", "dateTime is properly set to empty string if datetime attributeis absent");
+is(t2.dateTime, "2009-05-10", "dateTime is properly set to datetime attribute with datetime and no text content");
+is(t3.dateTime, "2009-05-10", "dateTime is properly set to datetime attribute with datetime and text content");
+
+// dateTime reflects datetime attribute
+reflectString({
+ element: t4,
+ attribute: "dateTime"
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug633058.html b/dom/html/test/test_bug633058.html
new file mode 100644
index 000000000..8ffd1fecd
--- /dev/null
+++ b/dom/html/test/test_bug633058.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=633058
+-->
+<head>
+ <title>Test for Bug 633058</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=633058">Mozilla Bug 633058</a>
+<p id="display"></p>
+<div id="content">
+ <input>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 633058 **/
+
+SimpleTest.waitForExplicitFinish();
+
+// Turn off Spatial Navigation so that the 'keypress' event fires.
+SimpleTest.waitForFocus(function() {
+ SpecialPowers.pushPrefEnv({"set":[['snav.enabled', false]]}, startTest);
+});
+function startTest() {
+ var nbExpectedKeyPress = 8;
+ var inputGotKeyPress = 0;
+ var divGotKeyPress = 0;
+
+ var input = document.getElementsByTagName('input')[0];
+ var content = document.getElementById('content');
+
+ content.addEventListener('keypress', function() {
+ divGotKeyPress++;
+
+ if (divGotKeyPress == nbExpectedKeyPress) {
+ is(inputGotKeyPress, nbExpectedKeyPress, "input got all keypress events");
+ is(divGotKeyPress, nbExpectedKeyPress, "div got all keypress events");
+ SimpleTest.finish();
+ }
+ }, false);
+
+ input.addEventListener('keypress', function() {
+ inputGotKeyPress++;
+ }, false);
+
+ input.addEventListener('focus', function() {
+ input.removeEventListener('focus', arguments.callee, false);
+
+ synthesizeKey('VK_UP', {});
+ synthesizeKey('VK_LEFT', {});
+ synthesizeKey('VK_RIGHT', {});
+ synthesizeKey('VK_DOWN', {});
+ synthesizeKey('VK_BACK_SPACE', {});
+ synthesizeKey('VK_DELETE', {});
+ synthesizeKey('VK_ESCAPE', {});
+ synthesizeKey('VK_RETURN', {});
+ }, false);
+ input.focus();
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug636336.html b/dom/html/test/test_bug636336.html
new file mode 100644
index 000000000..ed6812e8d
--- /dev/null
+++ b/dom/html/test/test_bug636336.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=636336
+-->
+<head>
+ <title>Test for Bug 636336</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=636336">Mozilla Bug 636336</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 636336 **/
+function testIt(tag) {
+ var elem = document.createElement(tag);
+ elem.setAttribute("src", " ");
+ is(elem.getAttribute("src"), " ",
+ tag + " src attribute setter should not strip whitespace");
+ elem.setAttribute("src", " test ");
+ is(elem.getAttribute("src"), " test ",
+ tag + " src attribute setter should not strip whitespace around non-whitespace");
+ is(elem.src, window.location.href.replace(/test_bug636336\.html$/, "test"),
+ tag + ".src should strip whitespace as needed");
+}
+
+testIt("img");
+testIt("source");
+testIt("audio");
+testIt("video");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug641219.html b/dom/html/test/test_bug641219.html
new file mode 100644
index 000000000..ad25d9a57
--- /dev/null
+++ b/dom/html/test/test_bug641219.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=641219
+-->
+<head>
+ <title>Test for Bug 641219</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=641219">Mozilla Bug 641219</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<div id="div">
+<font></font>
+<svg><font/></svg>
+</div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 641219 **/
+var HTML = "http://www.w3.org/1999/xhtml",
+ SVG = "http://www.w3.org/2000/svg";
+var wrapper = document.getElementById("div");
+is(wrapper.getElementsByTagName("FONT").length, 1);
+is(wrapper.getElementsByTagName("FONT")[0].namespaceURI, HTML);
+is(wrapper.getElementsByTagName("font").length, 2);
+is(wrapper.getElementsByTagName("font")[0].namespaceURI, HTML);
+is(wrapper.getElementsByTagName("font")[1].namespaceURI, SVG);
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug643051.html b/dom/html/test/test_bug643051.html
new file mode 100644
index 000000000..4b94e1b0e
--- /dev/null
+++ b/dom/html/test/test_bug643051.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=643051
+-->
+<head>
+ <title>Test for Bug 643051</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=643051">Mozilla Bug 643051</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 643051 **/
+document.cookie = "a=; expires=Thu, 01-Jan-1970 00:00:01 GMT"; // clear cookie
+document.cookie = "a2=; expires=Thu, 01-Jan-1970 00:00:01 GMT"; // clear cookie
+document.cookie = "a3=; expires=Thu, 01-Jan-1970 00:00:01 GMT"; // clear cookie
+
+// single cookie, should work
+document.cookie = "a=bar";
+is(document.cookie, "a=bar", "Can't read stored cookie!");
+
+document.cookie = "a2=bar\na3=bar";
+is(document.cookie, "a=bar; a2=bar", "Wrong cookie value");
+
+document.cookie = "a2=baz; a3=bar";
+is(document.cookie, "a=bar; a2=baz", "Wrong cookie value");
+
+// clear cookies again to avoid affecting other tests
+document.cookie = "a=; expires=Thu, 01-Jan-1970 00:00:01 GMT";
+document.cookie = "a2=; expires=Thu, 01-Jan-1970 00:00:01 GMT";
+document.cookie = "a3=; expires=Thu, 01-Jan-1970 00:00:01 GMT";
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug646157.html b/dom/html/test/test_bug646157.html
new file mode 100644
index 000000000..3924c9f22
--- /dev/null
+++ b/dom/html/test/test_bug646157.html
@@ -0,0 +1,95 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=646157
+-->
+<head>
+ <title>Test for Bug 646157</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=646157">Mozilla Bug 646157</a>
+<p id="display"></p>
+<div id="content">
+ <label id="l1"/><input id="c1" type='checkbox'>
+ <label id="l2"/><input id="c2" type='checkbox'>
+ <label id="l3"/><input id="c3" type='checkbox'>
+ <label id="l4"/><input id="c4" type='checkbox'>
+ <label id="l5"/><input id="c5" type='checkbox'>
+ <label id="l6"/><input id="c6" type='checkbox'>
+ <label id="l7"/><input id="c7" type='checkbox'>
+ <label id="l8"/><input id="c8" type='checkbox'>
+ <label id="l9"/><input id="c9" type='checkbox'>
+ <label id="l10"/><input id="c10" type='checkbox'>
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 646157 **/
+
+var expectedClicks = {
+ // [ Direct clicks, bubbled clicks, synthetic clicks]
+ l1: [0, 2, 1],
+ l2: [0, 2, 1],
+ l3: [0, 2, 1],
+ l4: [0, 2, 1],
+ l5: [0, 2, 1],
+ l6: [0, 2, 1],
+ l7: [0, 2, 1],
+ l8: [0, 2, 1],
+ l9: [0, 2, 1],
+ l10:[1, 2, 1],
+ c1: [0, 0, 0],
+ c2: [0, 0, 0],
+ c3: [0, 0, 0],
+ c4: [0, 0, 0],
+ c5: [0, 0, 0],
+ c6: [0, 0, 0],
+ c7: [0, 0, 0],
+ c8: [0, 0, 0],
+ c9: [0, 0, 0],
+ c10:[1, 1, 1]
+};
+
+function clickhandler(e) {
+ if (!e.currentTarget.clickCount)
+ e.currentTarget.clickCount = 1;
+ else
+ e.currentTarget.clickCount++;
+
+ if (e.currentTarget === e.target)
+ e.currentTarget.directClickCount = 1;
+
+ if (e.target != document.getElementById("l10")) {
+ if (!e.currentTarget.synthClickCount)
+ e.currentTarget.synthClickCount = 1;
+ else
+ e.currentTarget.synthClickCount++;
+ }
+}
+
+for (var i = 1; i <= 10; i++) {
+ document.getElementById("l" + i).addEventListener('click', clickhandler, false);
+ document.getElementById("c" + i).addEventListener('click', clickhandler, false);
+}
+
+document.getElementById("l10").click();
+
+function check(thing) {
+ var expected = expectedClicks[thing.id];
+ is(thing.directClickCount || 0, expected[0], "Wrong number of direct clicks");
+ is(thing.clickCount || 0, expected[1], "Wrong number of clicks");
+ is(thing.synthClickCount || 0, expected[2], "Wrong number of synthetic clicks");
+}
+
+// Compare them all
+for (var i = 1; i <= 10; i++) {
+ check(document.getElementById("l" + i));
+ check(document.getElementById("c" + i));
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug649134.html b/dom/html/test/test_bug649134.html
new file mode 100644
index 000000000..1bedfbe3c
--- /dev/null
+++ b/dom/html/test/test_bug649134.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=649134
+-->
+<head>
+ <title>Test for Bug 649134</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=649134">Mozilla Bug 649134</a>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 649134 **/
+SimpleTest.waitForExplicitFinish();
+
+var calls = 0;
+function finish() {
+ if (++calls == 4)
+ SimpleTest.finish();
+}
+function verifyNoLoad(iframe) {
+ ok(iframe.contentDocument.body.offsetHeight > 0,
+ "HTTP Link stylesheet was ignored " + iframe.src);
+ finish();
+}
+var verifyLoadCalls = 0;
+function verifyLoad(iframe) {
+ if (++verifyLoadCalls == 2) {
+ ok(indexContent == iframe.contentDocument.body.innerHTML,
+ "bug649134/ loads bug649134/index.html " + iframe.src);
+ }
+ finish();
+}
+function indexLoad(iframe) {
+ indexContent = iframe.contentDocument.body.innerHTML;
+ verifyLoad(iframe);
+}
+
+</script>
+</pre>
+<p id="display">
+<!-- Note: the extra sub-directory is needed for the test, see bug 649134 comment 14 -->
+<iframe onload="verifyNoLoad(this);" src="bug649134/file_bug649134-1.sjs"></iframe>
+<iframe onload="verifyNoLoad(this);" src="bug649134/file_bug649134-2.sjs"></iframe>
+<iframe onload="verifyLoad(this);" src="bug649134/"></iframe> <!-- verify that mochitest server loads index.html -->
+<iframe onload="indexLoad(this);" src="bug649134/index.html"></iframe>
+</p>
+</body>
+</html>
diff --git a/dom/html/test/test_bug651956.html b/dom/html/test/test_bug651956.html
new file mode 100644
index 000000000..59fbd3936
--- /dev/null
+++ b/dom/html/test/test_bug651956.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=651956
+-->
+<head>
+ <title>Test for Bug 651956</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=651956">Mozilla Bug 651956</a>
+<p id="display"></p>
+<div id="content">
+ <input>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 651956 **/
+
+var input = document.getElementsByTagName('input')[0];
+
+var gotInputEvent = false;
+
+input.addEventListener("input", function() {
+ input.removeEventListener("input", arguments.callee, false);
+ gotInputEvent = true;
+}, false);
+
+input.addEventListener("focus", function() {
+ input.removeEventListener("focus", arguments.callee, false);
+ synthesizeKey("VK_ESCAPE", {});
+
+ setTimeout(function() {
+ ok(!gotInputEvent, "No input event should have been sent.");
+ SimpleTest.finish();
+ });
+}, false);
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ input.focus();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug658746.html b/dom/html/test/test_bug658746.html
new file mode 100644
index 000000000..df5982547
--- /dev/null
+++ b/dom/html/test/test_bug658746.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=658746
+-->
+<head>
+ <title>Test for Bug 658746</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=658746">Mozilla Bug 658746</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 658746 **/
+
+/**
+ * Sets property, gets property and deletes property.
+ */
+function SetGetDelete(prop)
+{
+ var el = document.createElement('div');
+
+ el.dataset[prop] = 'aaaaaa';
+ is(el.dataset[prop], 'aaaaaa', 'Dataset property "' + prop + '" should have been set.');
+
+ delete el.dataset[prop];
+ is(el.dataset[prop], undefined, 'Dataset property"' + prop + '" should have been deleted.');
+}
+
+/**
+ * Gets, deletes and sets property. Expects exception while trying to set property.
+ */
+function SetExpectException(prop)
+{
+ var el = document.createElement('div');
+
+ is(el.dataset[prop], undefined, 'Dataset property "' + prop + '" should be undefined.');
+ delete el.dataset[prop];
+
+ try {
+ el.dataset[prop] = "xxxxxx";
+ ok(false, 'Exception should have been thrown when setting "' + prop + '".');
+ } catch (ex) {
+ ok(true, 'Exception should have been thrown.');
+ }
+}
+
+// Numbers as properties.
+SetGetDelete(-12345678901234567980);
+SetGetDelete(-1);
+SetGetDelete(0);
+SetGetDelete(1);
+SetGetDelete(12345678901234567980);
+
+// Floating point numbers as properties.
+SetGetDelete(-1.1);
+SetGetDelete(0.0);
+SetGetDelete(1.1);
+
+// Hexadecimal numbers as properties.
+SetGetDelete(0x3);
+SetGetDelete(0xa);
+
+// Octal numbers as properties.
+SetGetDelete(03);
+SetGetDelete(07);
+
+// String numbers as properties.
+SetGetDelete('0');
+SetGetDelete('01');
+SetGetDelete('0x1');
+
+// Undefined as property.
+SetGetDelete(undefined);
+
+// Empty arrays as properties.
+SetGetDelete(new Array());
+SetGetDelete([]);
+
+// Non-empty array and object as properties.
+SetExpectException(['a', 'b']);
+SetExpectException({'a':'b'});
+
+// Objects as properties.
+SetExpectException(new Object());
+SetExpectException(document);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug659596.html b/dom/html/test/test_bug659596.html
new file mode 100644
index 000000000..a8828cf0a
--- /dev/null
+++ b/dom/html/test/test_bug659596.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=659596
+-->
+<head>
+ <title>Test for Bug 659596</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=659596">Mozilla Bug 659596</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 659596 **/
+
+function checkReflection(option, attribute) {
+ /**
+ * Getting.
+ */
+
+ // When attribute isn't present.
+ var tests = [ "", "foo" ];
+ for (var test of tests) {
+ option.removeAttribute(attribute);
+ option.textContent = test;
+ is(option.getAttribute(attribute), null,
+ "option " + attribute + "'s value should be null");
+ is(option[attribute], option.textContent,
+ "option." + attribute + " should reflect the text content when the attribute isn't set");
+ }
+
+ // When attribute is present.
+ tests = [
+ [ "", "" ],
+ [ "", "foo" ],
+ [ "foo", "bar" ],
+ [ "foo", "" ],
+ ];
+ for (var test of tests) {
+ option.setAttribute(attribute, test[0]);
+ option.textContent = test[1];
+ is(option[attribute], option.getAttribute(attribute),
+ "option." + attribute + " should reflect the content attribute when it is set");
+ }
+
+ /**
+ * Setting.
+ */
+
+ // When attribute isn't present.
+ tests = [
+ [ "", "new" ],
+ [ "foo", "new" ],
+ ];
+ for (var test of tests) {
+ option.removeAttribute(attribute);
+ option.textContent = test[0];
+ option[attribute] = test[1]
+
+ is(option.getAttribute(attribute), test[1],
+ "when setting, the content attribute should change");
+ is(option.textContent, test[0],
+ "when setting, the text content should not change");
+ }
+
+ // When attribute is present.
+ tests = [
+ [ "", "", "new" ],
+ [ "", "foo", "new" ],
+ [ "foo", "bar", "new" ],
+ [ "foo", "", "new" ],
+ ];
+ for (var test of tests) {
+ option.setAttribute(attribute, test[0]);
+ option.textContent = test[1];
+ option[attribute] = test[2];
+
+ is(option.getAttribute(attribute), test[2],
+ "when setting, the content attribute should change");
+ is(option.textContent, test[1],
+ "when setting, the text content should not change");
+ }
+}
+
+var option = document.createElement("option");
+
+checkReflection(option, "value");
+checkReflection(option, "label");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug659743.xml b/dom/html/test/test_bug659743.xml
new file mode 100644
index 000000000..12236bdc0
--- /dev/null
+++ b/dom/html/test/test_bug659743.xml
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=659743
+-->
+<head>
+ <title>Test for Bug 659743</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=659743">Mozilla Bug 659743</a>
+<p id="display">
+<map name="a">
+<area shape="rect" coords="25,25,75,75" href="#x"/>
+</map>
+<map id="b">
+<area shape="rect" coords="25,25,75,75" href="#y"/>
+</map>
+<map name="a">
+<area shape="rect" coords="25,25,75,75" href="#FAIL"/>
+</map>
+<map id="b">
+<area shape="rect" coords="25,25,75,75" href="#FAIL"/>
+</map>
+
+<img usemap="#a" src="image.png"/>
+<img usemap="#b" src="image.png"/>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 659743 **/
+SimpleTest.waitForExplicitFinish();
+var images = document.getElementsByTagName("img");
+var second = false;
+onhashchange = function() {
+ if (!second) {
+ second = true;
+ is(location.hash, "#x", "First map");
+ SimpleTest.waitForFocus(() => synthesizeMouse(images[1], 50, 50, {}));
+ } else {
+ is(location.hash, "#y", "Second map");
+ SimpleTest.finish();
+ }
+};
+SimpleTest.waitForFocus(() => synthesizeMouse(images[0], 50, 50, {}));
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug660663.html b/dom/html/test/test_bug660663.html
new file mode 100644
index 000000000..2ce3f9ac6
--- /dev/null
+++ b/dom/html/test/test_bug660663.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=660663
+-->
+<head>
+ <title>Test for Bug 660663</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=660663">Mozilla Bug 660663</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 660663 **/
+reflectLimitedEnumerated({
+ element: document.createElement("div"),
+ attribute: "dir",
+ validValues: ["ltr", "rtl", "auto"],
+ invalidValues: ["cheesecake", ""]
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug660959-1.html b/dom/html/test/test_bug660959-1.html
new file mode 100644
index 000000000..0bffa0e05
--- /dev/null
+++ b/dom/html/test/test_bug660959-1.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=660959
+-->
+<head>
+ <title>Test for Bug 660959</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=660959">Mozilla Bug 660959</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <a href="#" id="testa"></a>
+</div>
+<pre id="test">
+<script>
+ is($("content").querySelector(":link, :visited"), $("testa"),
+ "Should find a link even in a display:none subtree");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug660959-2.html b/dom/html/test/test_bug660959-2.html
new file mode 100644
index 000000000..a4d74b6e3
--- /dev/null
+++ b/dom/html/test/test_bug660959-2.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=660959
+-->
+<head>
+ <title>Test for Bug 660959</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <style>
+ :link, :visited {
+ color: red;
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=660959">Mozilla Bug 660959</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <a href="#" id="a"></a>
+</div>
+<pre id="test">
+<script type="application/javascript">
+ var a = document.getElementById("a");
+ is(window.getComputedStyle(a).color, "rgb(255, 0, 0)", "Link is not right color?");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug660959-3.html b/dom/html/test/test_bug660959-3.html
new file mode 100644
index 000000000..4539a0449
--- /dev/null
+++ b/dom/html/test/test_bug660959-3.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=660959
+-->
+<head>
+ <title>Test for Bug 660959</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=660959">Mozilla Bug 660959</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <a href="http://www.example.com"></a>
+ <div id="foo">
+ <span id="test"></span>
+ </div>
+</div>
+<pre id="test">
+<script>
+ is($("foo").querySelector(":link + * span, :visited + * span"), $("test"),
+ "Should be able to find link siblings even in a display:none subtree");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug666200.html b/dom/html/test/test_bug666200.html
new file mode 100644
index 000000000..d2a748697
--- /dev/null
+++ b/dom/html/test/test_bug666200.html
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=666200
+-->
+<head>
+ <title>Test for Bug 666200</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666200">Mozilla Bug 666200</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+/** Test for Bug 666200 **/
+var sel = document.createElement("select");
+var opt1 = new Option();
+var opt2 = new Option();
+var opt3 = new Option();
+var opt4 = new Option();
+var opt5 = new Option();
+opt1.value = 1;
+opt2.value = 2;
+opt3.value = 3;
+opt4.value = 4;
+opt5.value = 5;
+sel.add(opt1);
+sel.add(opt2, 0);
+sel.add(opt3, 1000);
+sel.options.add(opt4, opt3);
+sel.add(opt5, undefined);
+is(sel[0], opt2, "1st item should be 2");
+is(sel[1], opt1, "2nd item should be 1");
+is(sel[2], opt4, "3rd item should be 4");
+is(sel[3], opt3, "4th item should be 3");
+is(sel[4], opt5, "5th item should be 5");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug666666.html b/dom/html/test/test_bug666666.html
new file mode 100644
index 000000000..3bd1d5832
--- /dev/null
+++ b/dom/html/test/test_bug666666.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=666666
+-->
+<head>
+ <title>Test for Bug 666666</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=666666">Mozilla Bug 666666</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 666666 **/
+["audio", "video"].forEach(function(element) {
+ reflectLimitedEnumerated({
+ element: document.createElement(element),
+ attribute: "preload",
+ validValues: ["none", "metadata", "auto"],
+ invalidValues: ["cheesecake", ""]
+ });
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug669012.html b/dom/html/test/test_bug669012.html
new file mode 100644
index 000000000..e6be933fa
--- /dev/null
+++ b/dom/html/test/test_bug669012.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=669012
+-->
+<head>
+ <title>Test for Bug 669012</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=669012">Mozilla Bug 669012</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<script>
+var run = 0;
+</script>
+<svg>
+<script>
+run++;
+ok(true, "Should run SVG script without attributes")
+</script>
+<script for=window event=onload>
+run++;
+ok(true, "Should run SVG script with for=window event=onload")
+</script>
+<script for=window event=foo>
+run++;
+ok(true, "Should run SVG script with for=window event=foo")
+</script>
+<script for=foo event=onload>
+run++;
+ok(true, "Should run SVG script with for=foo event=onload")
+</script>
+</svg>
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for Bug 669012 **/
+is(run, 4, "Should have run all tests")
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug674558.html b/dom/html/test/test_bug674558.html
new file mode 100644
index 000000000..c728bc14e
--- /dev/null
+++ b/dom/html/test/test_bug674558.html
@@ -0,0 +1,290 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=674558
+-->
+<head>
+ <title>Test for Bug 674558</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=674558">Mozilla Bug 674558</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 674558 **/
+SimpleTest.waitForExplicitFinish();
+
+// Turn off spatial navigation because it hijacks VK_RIGHT and VK_LEFT keydown
+// events.
+SimpleTest.waitForFocus(function() {
+ SpecialPowers.pushPrefEnv({"set":[["snav.enabled", false]]}, startTest);
+});
+function startTest() {
+ function textAreaCtor() {
+ return document.createElement("textarea");
+ }
+ var ctors = [textAreaCtor];
+ ["text", "password", "search"].forEach(function(type) {
+ ctors.push(function inputCtor() {
+ var input = document.createElement("input");
+ input.type = type;
+ return input;
+ });
+ });
+
+ for (var ctor in ctors) {
+ test(ctors[ctor]);
+ }
+
+ SimpleTest.finish();
+}
+
+function test(ctor) {
+ var elem = ctor();
+ ok(true, "Testing " + name(elem));
+
+ ok("selectionDirection" in elem, "elem should have the selectionDirection property");
+
+ is(elem.selectionStart, elem.value.length, "Default value");
+ is(elem.selectionEnd, elem.value.length, "Default value");
+ is(elem.selectionDirection, "forward", "Default value");
+
+ var content = document.getElementById("content");
+ content.appendChild(elem);
+
+ function flush() { document.body.clientWidth; }
+ function hide() {
+ content.style.display = "none";
+ flush();
+ }
+ function show() {
+ content.style.display = "";
+ flush();
+ }
+
+ elem.value = "foobar";
+
+ is(elem.selectionStart, elem.value.length, "Default value");
+ is(elem.selectionEnd, elem.value.length, "Default value");
+ is(elem.selectionDirection, "forward", "Default value");
+
+ elem.setSelectionRange(1, 3);
+ is(elem.selectionStart, 1, "Correct value");
+ is(elem.selectionEnd, 3, "Correct value");
+ is(elem.selectionDirection, "forward", "If not set, should default to forward");
+
+ hide();
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 3, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 3, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ // extend to right
+ elem.focus();
+ synthesizeKey("VK_RIGHT", {shiftKey: true});
+
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 4, "Correct value");
+ is(elem.selectionDirection, "forward", "Still forward");
+
+ hide();
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ // change the direction
+ elem.selectionDirection = "backward";
+
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Correct value");
+
+ hide();
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ // extend to right again
+ synthesizeKey("VK_RIGHT", {shiftKey: true});
+
+ is(elem.selectionStart, 2, "Correct value");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Still backward");
+
+ hide();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ elem.selectionEnd = 5;
+
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Correct value");
+ is(elem.selectionDirection, "backward", "Still backward");
+
+ hide();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ elem.selectionDirection = "none";
+
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "forward", "none not supported");
+
+ hide();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ elem.selectionDirection = "backward";
+
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Correct Value");
+
+ hide();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ elem.selectionDirection = "invalid";
+
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Treated as none");
+
+ hide();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ elem.selectionDirection = "backward";
+
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Correct Value");
+
+ hide();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ elem.setSelectionRange(1, 4);
+
+ is(elem.selectionStart, 1, "Correct value");
+ is(elem.selectionEnd, 4, "Correct value");
+ is(elem.selectionDirection, "forward", "Correct value");
+
+ hide();
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ elem.setSelectionRange(1, 1);
+ synthesizeKey("VK_RIGHT", {shiftKey: true});
+ synthesizeKey("VK_RIGHT", {shiftKey: true});
+ synthesizeKey("VK_RIGHT", {shiftKey: true});
+
+ is(elem.selectionStart, 1, "Correct value");
+ is(elem.selectionEnd, 4, "Correct value");
+ is(elem.selectionDirection, "forward", "Correct value");
+
+ hide();
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 1, "Value unchanged");
+ is(elem.selectionEnd, 4, "Value unchanged");
+ is(elem.selectionDirection, "forward", "Value unchanged");
+
+ elem.setSelectionRange(5, 5);
+ synthesizeKey("VK_LEFT", {shiftKey: true});
+ synthesizeKey("VK_LEFT", {shiftKey: true});
+ synthesizeKey("VK_LEFT", {shiftKey: true});
+
+ is(elem.selectionStart, 2, "Correct value");
+ is(elem.selectionEnd, 5, "Correct value");
+ is(elem.selectionDirection, "backward", "Correct value");
+
+ hide();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+
+ show();
+ is(elem.selectionStart, 2, "Value unchanged");
+ is(elem.selectionEnd, 5, "Value unchanged");
+ is(elem.selectionDirection, "backward", "Value unchanged");
+}
+
+function name(elem) {
+ var tag = elem.localName;
+ if (tag == "input") {
+ tag += "[type=" + elem.type + "]";
+ }
+ return tag;
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug674927.html b/dom/html/test/test_bug674927.html
new file mode 100644
index 000000000..92af59453
--- /dev/null
+++ b/dom/html/test/test_bug674927.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=674927
+-->
+<title>Test for Bug 674927</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<p><span>Hello</span></p>
+<div contenteditable>Contenteditable <i>is</i> splelchecked by default</div>
+<textarea>Textareas are spellchekced by default</textarea>
+<input value="Inputs are not spellcheckde by default">
+<script>
+// Test the effect of setting spellcheck on various elements
+[
+ "html",
+ "body",
+ "p",
+ "span",
+ "div",
+ "i",
+ "textarea",
+ "input",
+].forEach(function(query) {
+ var element = document.querySelector(query);
+
+ // First check what happens if no attributes are set
+ var defaultSpellcheck;
+ if (element.isContentEditable || element.tagName == "TEXTAREA") {
+ defaultSpellcheck = true;
+ } else {
+ defaultSpellcheck = false;
+ }
+ is(element.spellcheck, defaultSpellcheck,
+ "Default spellcheck for <" + element.tagName.toLowerCase() + ">");
+
+ // Now try setting spellcheck on ancestors
+ var ancestor = element;
+ do {
+ testSpellcheck(ancestor, element);
+ ancestor = ancestor.parentNode;
+ } while (ancestor.nodeType == Node.ELEMENT_NODE);
+});
+
+function testSpellcheck(ancestor, element) {
+ ancestor.spellcheck = true;
+ is(element.spellcheck, true,
+ ".spellcheck on <" + element.tagName.toLowerCase() + "> with " +
+ "spellcheck=true on <" + ancestor.tagName.toLowerCase() + ">");
+ ancestor.spellcheck = false;
+ is(element.spellcheck, false,
+ ".spellcheck on <" + element.tagName.toLowerCase() + "> with " +
+ "spellcheck=false on <" + ancestor.tagName.toLowerCase() + ">");
+ ancestor.removeAttribute("spellcheck");
+}
+</script>
diff --git a/dom/html/test/test_bug677463.html b/dom/html/test/test_bug677463.html
new file mode 100644
index 000000000..2d895d8d2
--- /dev/null
+++ b/dom/html/test/test_bug677463.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=677463
+-->
+<head>
+ <title>Test for Bug 677463</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677463">Mozilla Bug 677463</a>
+<p id="display"></p>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 677463 **/
+
+var o = document.createElement("option");
+var m = document.createElement("menuitem");
+is(o.label, m.label, "Should have same labels");
+o.textContent = " ";
+is(o.label, m.label, "Should have same labels");
+m.textContent = " ";
+is(o.label, m.label, "Should have same labels");
+o.textContent = " foo";
+isnot(o.label, m.label, "Shouldn't have same labels");
+m.textContent = "foo ";
+is(o.label, m.label, "Should have same labels");
+m.label = "bar";
+isnot(o.label, m.label, "Shouldn't have same labels");
+o.label = "bar";
+is(o.label, m.label, "Should have same labels");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug677495-1.html b/dom/html/test/test_bug677495-1.html
new file mode 100644
index 000000000..916997f00
--- /dev/null
+++ b/dom/html/test/test_bug677495-1.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=677495
+
+As mandated by the spec, the body of a media document must only contain one child.
+-->
+<head>
+ <title>Test for Bug 571981</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+<script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+
+ function frameLoaded() {
+ var testframe = document.getElementById('testframe');
+ var testframeChildren = testframe.contentDocument.body.childNodes;
+ is(testframeChildren.length, 1, "Body of video document has 1 child");
+ is(testframeChildren[0].nodeName, "VIDEO", "Only child of body must be a <video> element");
+
+ SimpleTest.finish();
+ }
+</script>
+
+</head>
+<body>
+ <p id="display"></p>
+
+ <iframe id="testframe" name="testframe" onload="frameLoaded()"
+ src="data:video/webm,"></iframe>
+
+</body>
+</html>
diff --git a/dom/html/test/test_bug677495.html b/dom/html/test/test_bug677495.html
new file mode 100644
index 000000000..fec1912b4
--- /dev/null
+++ b/dom/html/test/test_bug677495.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=677495
+
+As mandated by the spec, the body of a media document must only contain one child.
+-->
+<head>
+ <title>Test for Bug 571981</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+<script type="application/javascript">
+ SimpleTest.waitForExplicitFinish();
+
+ function frameLoaded() {
+ var testframe = document.getElementById('testframe');
+ var testframeChildren = testframe.contentDocument.body.childNodes;
+ is(testframeChildren.length, 1, "Body of image document has 1 child");
+ is(testframeChildren[0].nodeName, "IMG", "Only child of body must be an <img> element");
+
+ SimpleTest.finish();
+ }
+</script>
+
+</head>
+<body>
+ <p id="display"></p>
+
+ <iframe id="testframe" name="testframe" onload="frameLoaded()"
+ src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9oMFgQGMyFwHucAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC"></iframe>
+
+</body>
+</html>
diff --git a/dom/html/test/test_bug677658.html b/dom/html/test/test_bug677658.html
new file mode 100644
index 000000000..3aab5dba8
--- /dev/null
+++ b/dom/html/test/test_bug677658.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=677658
+-->
+<head>
+ <title>Test for Bug 677658</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=677658">Mozilla Bug 677658</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript"><!--
+
+/** Test for Bug 677658 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function testDone() {
+ ok(window.testPassed, "Script shouldn't have run!");
+ SimpleTest.finish();
+}
+
+function test() {
+ window.testPassed = true;
+ document.getElementById("testtarget").innerHTML =
+ "<script async src='data:text/plain, window.testPassed = false;'></script>";
+ SimpleTest.executeSoon(testDone);
+}
+
+// -->
+</script>
+</pre>
+<div id="testtarget"></div>
+</body>
+</html>
diff --git a/dom/html/test/test_bug682886.html b/dom/html/test/test_bug682886.html
new file mode 100644
index 000000000..b321d017f
--- /dev/null
+++ b/dom/html/test/test_bug682886.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=682886
+-->
+<head>
+ <title>Test for Bug 682886</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=682886">Mozilla Bug 682886</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 682886 **/
+
+
+ var m = document.createElement("menu");
+ var s = "<menuitem>foo</menuitem>";
+ m.innerHTML = s;
+ is(m.innerHTML, s, "Wrong menuitem serialization!");
+
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug691.html b/dom/html/test/test_bug691.html
new file mode 100644
index 000000000..cfdb53985
--- /dev/null
+++ b/dom/html/test/test_bug691.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=691
+-->
+<head>
+ <title>Test for Bug 691</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+<script type="text/javascript">
+
+function show(what) {
+ var stage = document.getElementById("stage");
+ if (what == "modularity") {
+ var spaghetti = document.createElement("IMG",null);
+ spaghetti.setAttribute("SRC","nnc_lockup.gif");
+ spaghetti.setAttribute("id","foo");
+ stage.insertBefore(spaghetti,stage.firstChild);
+ }
+}
+
+function remove() {
+ var stage = document.getElementById("stage");
+ var body = document.getElementsByTagName("BODY")[0];
+ while (stage.firstChild) {
+ stage.removeChild(stage.firstChild);
+ }
+}
+
+</script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=691">Mozilla Bug 691</a>
+<p id="display"></p>
+<div id="content" >
+<ul>
+<li >foo</li>
+</ul>
+<div id="stage">
+</div>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 691 **/
+
+show("modularity");
+remove();
+show("modularity");
+remove();
+show("modularity");
+remove();
+show("modularity");
+
+ok($("foo"), "basic DOM manipulation doesn't crash");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug694.html b/dom/html/test/test_bug694.html
new file mode 100644
index 000000000..8e88dd1cf
--- /dev/null
+++ b/dom/html/test/test_bug694.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=694
+-->
+<head>
+ <title>Test for Bug 694</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=694">Mozilla Bug 694</a>
+<p id="display"></p>
+<div id="content" >
+<img src="/missing_on_purpose" width=123 height=25 alt="Hello, &quot;Quotes&quot; how are you?" id="testimg">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 694 **/
+
+is($("testimg").getAttribute("alt"), "Hello, \"Quotes\" how are you?", "entities in alt attribute works");
+
+
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug694503.html b/dom/html/test/test_bug694503.html
new file mode 100644
index 000000000..6ffd18d64
--- /dev/null
+++ b/dom/html/test/test_bug694503.html
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=694503
+-->
+<head>
+ <title>Test for Bug 694503</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=694503">Mozilla Bug 694503</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+
+<div>
+<map name="map1">
+ <area onclick="++mapClickCount; event.preventDefault();"
+ coords="0,0,50,50" shape="rect">
+</map>
+</div>
+
+<img id="img"
+ usemap="#map1" alt="Foo bar" src="about:logo">
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 694503 **/
+
+var mapClickCount = 0;
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ var m = document.getElementsByTagName("map")[0];
+ var img = document.getElementById('img');
+ var origName = m.name;
+
+ synthesizeMouse(img, 25, 25, {});
+ is(mapClickCount, 1, "Wrong click count (1)");
+
+ m.name = "foo"
+ synthesizeMouse(img, 25, 25, {});
+ is(mapClickCount, 1, "Wrong click count (2)");
+
+ m.removeAttribute("name");
+ m.id = origName;
+ synthesizeMouse(img, 25, 25, {});
+ is(mapClickCount, 2, "Wrong click count (3)");
+
+ // Back to original state
+ m.removeAttribute("id");
+ m.name = origName;
+ synthesizeMouse(img, 25, 25, {});
+ is(mapClickCount, 3, "Wrong click count (4)");
+
+ var p = m.parentNode;
+ p.removeChild(m);
+ synthesizeMouse(img, 25, 25, {});
+ is(mapClickCount, 3, "Wrong click count (5)");
+
+ // Back to original state
+ p.appendChild(m);
+ synthesizeMouse(img, 25, 25, {});
+ is(mapClickCount, 4, "Wrong click count (6)");
+
+ SimpleTest.finish();
+});
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug696.html b/dom/html/test/test_bug696.html
new file mode 100644
index 000000000..35669f565
--- /dev/null
+++ b/dom/html/test/test_bug696.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=696
+-->
+<head>
+ <title>Test for Bug 696</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=696">Mozilla Bug 696</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <table><tr id="mytr"><td>Foo</td><td>Bar</td></tr></table>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 696 **/
+var mytr = $("content").getElementsByTagName("TR")[0];
+is(mytr.getAttribute("ID"),"mytr","TR tags expose their ID attribute");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug717819.html b/dom/html/test/test_bug717819.html
new file mode 100644
index 000000000..9c574dd68
--- /dev/null
+++ b/dom/html/test/test_bug717819.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=717819
+-->
+<head>
+ <title>Test for Bug 717819</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=717819">Mozilla Bug 717819</a>
+<p id="display"></p>
+<div id="content">
+ <table style="position: relative; top: 100px;">
+ <tr>
+ <td>
+ <div id="test" style="position: absolute; top: 50px;"></div>
+ </td>
+ </tr>
+ </table>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 717819 **/
+var div = document.getElementById("test");
+is(div.offsetTop, 50, "The offsetTop must be calculated correctly");
+is(div.offsetParent, document.querySelector("table"),
+ "The offset should be calculated off of the correct parent");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug741266.html b/dom/html/test/test_bug741266.html
new file mode 100644
index 000000000..72db28079
--- /dev/null
+++ b/dom/html/test/test_bug741266.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=741266
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 741266</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=741266">Mozilla Bug 741266</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 741266 **/
+SimpleTest.waitForExplicitFinish();
+
+var url = URL.createObjectURL(new Blob([""], { type: "text/html" }));
+var w = window.open(url, "", "width=100,height=100");
+w.onload = function() {
+ is(w.innerHeight, 100, "Popup height should be 100 when opened with window.open");
+ // XXXbz On at least some platforms, the innerWidth is off by the scrollbar
+ // width for some reason. So just make sure it's the same for both popups.
+ var width = w.innerWidth;
+ w.close();
+
+ w = document.open(url, "", "width=100,height=100");
+ w.onload = function() {
+ is(w.innerHeight, 100, "Popup height should be 100 when opened with document.open");
+ is(w.innerWidth, width, "Popup width should be the same when opened with document.open");
+ w.close();
+ SimpleTest.finish();
+ };
+};
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug742030.html b/dom/html/test/test_bug742030.html
new file mode 100644
index 000000000..c88f38879
--- /dev/null
+++ b/dom/html/test/test_bug742030.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=742030
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 742030</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742030">Mozilla Bug 742030</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 742030 **/
+const str = " color: #ff0000 ";
+var span = document.createElement("span");
+span.setAttribute("style", str);
+is(span.getAttribute("style"), str, "Should have set properly");
+var span2 = span.cloneNode(false);
+is(span2.getAttribute("style"), str, "Should have cloned properly");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug742549.html b/dom/html/test/test_bug742549.html
new file mode 100644
index 000000000..5ab88f36e
--- /dev/null
+++ b/dom/html/test/test_bug742549.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=742549
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 742549</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=742549">Mozilla Bug 742549</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 742549 **/
+var els = [ document.createElement("script"),
+ document.createElementNS("http://www.w3.org/2000/svg", "script") ]
+
+for (var i = 0; i < els.length; ++i) {
+ reflectLimitedEnumerated({
+ element: els[i],
+ attribute: { content: "crossorigin", idl: "crossOrigin" },
+ // "" is a valid value per spec, but gets mapped to the "anonymous" state,
+ // just like invalid values, so just list it under invalidValues
+ validValues: [ "anonymous", "use-credentials" ],
+ invalidValues: [
+ "", " aNOnYmous ", " UsE-CreDEntIALS ", "foobar", "FOOBAR", " fOoBaR "
+ ],
+ defaultValue: { invalid: "anonymous", missing: null },
+ nullable: true,
+ })
+}
+
+
+
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug745685.html b/dom/html/test/test_bug745685.html
new file mode 100644
index 000000000..c4544441e
--- /dev/null
+++ b/dom/html/test/test_bug745685.html
@@ -0,0 +1,105 @@
+<!doctype html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=745685
+-->
+<title>Test for Bug 745685</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=745685">Mozilla Bug 745685</a>
+<font>Test text</font>
+<font size=1>1</font>
+<font size=2>2</font>
+<font size=3>3</font>
+<font size=4>4</font>
+<font size=5>5</font>
+<font size=6>6</font>
+<font size=7>7</font>
+<script>
+/** Test for Bug 745685 **/
+
+var referenceSizes = {};
+for (var i = 1; i <= 7; i++) {
+ referenceSizes[i] =
+ getComputedStyle(document.querySelector('[size="' + i + '"]'))
+ .fontSize;
+ if (i > 1) {
+ isnot(referenceSizes[i], referenceSizes[i - 1],
+ "Sanity check: different <font size>s give different .fontSize");
+ }
+}
+
+function testFontSize(input, expected) {
+ var font = document.querySelector("font");
+ font.setAttribute("size", input);
+ is(font.getAttribute("size"), input,
+ "Setting doesn't round-trip (.getAttribute)");
+ is(font.size, input,
+ "Setting doesn't round-trip (.size)");
+ is(getComputedStyle(font).fontSize, referenceSizes[expected],
+ 'Incorrect size for "' + input + '" : expected the same as ' + expected);
+}
+
+function testFontSizes(input, expected) {
+ testFontSize(input, expected);
+ // Leading whitespace
+ testFontSize(" " + input, expected);
+ testFontSize("\t" + input, expected);
+ testFontSize("\n" + input, expected);
+ testFontSize("\f" + input, expected);
+ testFontSize("\r" + input, expected);
+ // Trailing garbage
+ testFontSize(input + "abcd", expected);
+ testFontSize(input + ".5", expected);
+ testFontSize(input + "e2", expected);
+}
+
+// Parse error
+testFontSizes("", 3);
+
+// No sign
+testFontSizes("0", 1);
+testFontSizes("1", 1);
+testFontSizes("2", 2);
+testFontSizes("3", 3);
+testFontSizes("4", 4);
+testFontSizes("5", 5);
+testFontSizes("6", 6);
+testFontSizes("7", 7);
+testFontSizes("8", 7);
+testFontSizes("9", 7);
+testFontSizes("10", 7);
+testFontSizes("10000000000000000000000", 7);
+
+// Minus sign
+testFontSizes("-0", 3);
+testFontSizes("-1", 2);
+testFontSizes("-2", 1);
+testFontSizes("-3", 1);
+testFontSizes("-4", 1);
+testFontSizes("-5", 1);
+testFontSizes("-6", 1);
+testFontSizes("-7", 1);
+testFontSizes("-8", 1);
+testFontSizes("-9", 1);
+testFontSizes("-10", 1);
+testFontSizes("-10000000000000000000000", 1);
+
+// Plus sign
+testFontSizes("+0", 3);
+testFontSizes("+1", 4);
+testFontSizes("+2", 5);
+testFontSizes("+3", 6);
+testFontSizes("+4", 7);
+testFontSizes("+5", 7);
+testFontSizes("+6", 7);
+testFontSizes("+7", 7);
+testFontSizes("+8", 7);
+testFontSizes("+9", 7);
+testFontSizes("+10", 7);
+testFontSizes("+10000000000000000000000", 7);
+
+// Non-HTML5 whitespace
+testFontSize("\b1", 3);
+testFontSize("\v1", 3);
+testFontSize("\0u00a01", 3);
+</script>
diff --git a/dom/html/test/test_bug763626.html b/dom/html/test/test_bug763626.html
new file mode 100644
index 000000000..960712c39
--- /dev/null
+++ b/dom/html/test/test_bug763626.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=763626
+-->
+<head>
+<title>Test for Bug 763626</title>
+
+<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function boom()
+{
+ var r = document.createElement("iframe").sandbox;
+ SpecialPowers.DOMWindowUtils.garbageCollect();
+ is("" + r, "", "ToString should return empty string when element is gone");
+ SimpleTest.finish();
+}
+
+</script>
+</head>
+
+<body onload="boom();"></body>
+</html>
+
diff --git a/dom/html/test/test_bug765780.html b/dom/html/test/test_bug765780.html
new file mode 100644
index 000000000..975353e2e
--- /dev/null
+++ b/dom/html/test/test_bug765780.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=765780
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 765780</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+ /** Test for Bug 765780 **/
+ SimpleTest.waitForExplicitFinish();
+ window.onload = function() {
+ var f = $("f");
+ var doc = f.contentDocument;
+ doc.designMode = "on";
+ var s = doc.createElement("script");
+ s.textContent = "parent.called = true;";
+
+ window.called = false;
+ doc.body.appendChild(s);
+ ok(called, "Script in designMode iframe should have run");
+
+ doc = doc.querySelector("iframe").contentDocument;
+ var s = doc.createElement("script");
+ s.textContent = "parent.parent.called = true;";
+
+ window.called = false;
+ doc.body.appendChild(s);
+ ok(called, "Script in designMode iframe's child should have run");
+
+ SimpleTest.finish();
+ }
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=765780">Mozilla Bug 765780</a>
+<!-- Important: iframe needs to not be display: none -->
+<p id="display"><iframe id="f" src="data:text/html,<iframe></iframe>"></iframe> </p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug780993.html b/dom/html/test/test_bug780993.html
new file mode 100644
index 000000000..14324e8e4
--- /dev/null
+++ b/dom/html/test/test_bug780993.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test for bug 780993</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var select = document.createElement("select");
+ var option = document.createElement("option");
+ select.appendChild(option);
+ assert_equals(select[0], option);
+ select[0] = null;
+ assert_equals(option.parentNode, null);
+ assert_equals(select[0], undefined);
+}, "Should be able to set select[n] to null.");
+test(function() {
+ var select = document.createElement("select");
+ var option = document.createElement("option");
+ var option2 = document.createElement("option");
+ select.appendChild(option);
+ assert_equals(select[0], option);
+ select[0] = option2;
+ assert_equals(option.parentNode, null);
+ assert_equals(option2.parentNode, select);
+ assert_equals(select[0], option2);
+}, "Should be able to set select[n] to an option element");
+test(function() {
+ var select = document.createElement("select");
+ var option = document.createElement("option");
+ select.appendChild(option);
+ assert_equals(select[0], option);
+ assert_throws(null, function() {
+ select[0] = 42;
+ });
+ assert_equals(option.parentNode, select);
+ assert_equals(select[0], option);
+}, "Should not be able to set select[n] to a primitive.");
+</script>
diff --git a/dom/html/test/test_bug787134.html b/dom/html/test/test_bug787134.html
new file mode 100644
index 000000000..37daa8e33
--- /dev/null
+++ b/dom/html/test/test_bug787134.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=787134
+-->
+<head>
+ <title>Test for Bug 787134</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=787134">Mozilla Bug 787134</a>
+<p id="display"></p>
+<p><a id="link-test1" href="example link">example link</a></p>
+<pre id="test">
+<script>
+ var div = document.createElement('div');
+ div.innerHTML = '<a href=#></a>';
+ var a = div.firstChild;
+ ok(a.matches(':link'), "Should match a link not in a document");
+ is(div.querySelector(':link'), a, "Should find a link not in a document");
+ a = document.querySelector('#link-test1');
+ ok(a.matches(':link'), "Should match a link in a document with an invalid URL");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug797113.html b/dom/html/test/test_bug797113.html
new file mode 100644
index 000000000..6c246eb3c
--- /dev/null
+++ b/dom/html/test/test_bug797113.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Test for bug 780993</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<div id=log></div>
+<script>
+test(function() {
+ var select = document.createElement("select");
+ var option = document.createElement("option");
+ select.appendChild(option);
+ assert_equals(select.options[0], option);
+ select.options[0] = null;
+ assert_equals(option.parentNode, null);
+ assert_equals(select.options[0], undefined);
+}, "Should be able to set select.options[n] to null.");
+test(function() {
+ var select = document.createElement("select");
+ var option = document.createElement("option");
+ var option2 = document.createElement("option");
+ select.appendChild(option);
+ assert_equals(select.options[0], option);
+ select.options[0] = option2;
+ assert_equals(option.parentNode, null);
+ assert_equals(option2.parentNode, select);
+ assert_equals(select.options[0], option2);
+}, "Should be able to set select.options[n] to an option element");
+test(function() {
+ var select = document.createElement("select");
+ var option = document.createElement("option");
+ select.appendChild(option);
+ assert_equals(select.options[0], option);
+ assert_throws(null, function() {
+ select.options[0] = 42;
+ });
+ assert_equals(option.parentNode, select);
+ assert_equals(select.options[0], option);
+}, "Should not be able to set select.options[n] to a primitive.");
+</script>
diff --git a/dom/html/test/test_bug803677.html b/dom/html/test/test_bug803677.html
new file mode 100644
index 000000000..fd754ba00
--- /dev/null
+++ b/dom/html/test/test_bug803677.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=803677
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 803677</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+<style>
+ .base { border:1px solid gray; }
+ .bad-table { display:table-cell; border:1px solid red; }
+</style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=803677">Mozilla Bug 803677</a>
+<p id="display"></p>
+<div id="content">
+ <p class="base">1</p>
+ <p class="base">2</p>
+ <p class="base">3</p>
+ <p class="base bad-table">4</p>
+ <p class="base">7</p>
+ <p class="base">8</p>
+ <p class="base">9</p>
+</div>
+<pre id="test">
+<script type="application/javascript">
+ var p = document.querySelectorAll(".base");
+ var parent = document.querySelector("body");
+ var prevOffset = 0;
+ for (var i = 0; i < p.length; i++) {
+ var t = 0, e = p[i];
+ is(e.offsetParent, parent, "Offset parent of all paragraphs should be the body.");
+ while (e) {
+ t += e.offsetTop;
+ e = e.offsetParent;
+ }
+ p[i].innerHTML = t;
+
+ ok(t > prevOffset, "Offset should increase down the page");
+ prevOffset = t;
+ }
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug821307.html b/dom/html/test/test_bug821307.html
new file mode 100644
index 000000000..46721fcca
--- /dev/null
+++ b/dom/html/test/test_bug821307.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=821307
+-->
+<head>
+ <title>Test for Bug 821307</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=821307">Mozilla Bug 821307</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+
+<input id='dummy'></input>
+<input type="password" id='input' value='11111111111111111' style="width:40em; font-size:40px;"></input>
+
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ var dummy = document.getElementById('dummy');
+ dummy.focus();
+ is(document.activeElement, dummy, "Check dummy element is now focused");
+
+ var input = document.getElementById('input');
+ var rect = input.getBoundingClientRect();
+ synthesizeMouse(input, 100, rect.height/2, {});
+ is(document.activeElement, input, "Check input element is now focused");
+
+ SimpleTest.finish();
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug827126.html b/dom/html/test/test_bug827126.html
new file mode 100644
index 000000000..3d8b1a597
--- /dev/null
+++ b/dom/html/test/test_bug827126.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=827126
+-->
+<head>
+ <title>Test for Bug 827126</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=827126">Mozilla Bug 827126</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test to ensure we reflect <img align> correctly **/
+reflectString({
+ element: new Image(),
+ attribute: "align",
+ otherValues: [ "left", "right", "middle", "justify" ]
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug838582.html b/dom/html/test/test_bug838582.html
new file mode 100644
index 000000000..5c227c2bd
--- /dev/null
+++ b/dom/html/test/test_bug838582.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=838582
+-->
+<head>
+ <title>Test for Bug 838582</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=838582">Mozilla Bug 838582</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<textarea id="t">abc</textarea>
+<script type="application/javascript">
+
+/** Test for Bug 838582 **/
+
+var textarea = document.getElementById("t");
+
+is(t.textLength, 3, "Correct textLength for defaultValue");
+t.value = "abcdef";
+is(t.textLength, 6, "Correct textLength for value");
+ok(!("controllers" in t), "Don't have web-visible controllers property");
+ok("controllers" in SpecialPowers.wrap(t), "Have chrome-visible controllers property");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug839371.html b/dom/html/test/test_bug839371.html
new file mode 100644
index 000000000..293c0c452
--- /dev/null
+++ b/dom/html/test/test_bug839371.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=839371
+-->
+<head>
+ <title>Test for Bug 839371</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=839371">Mozilla Bug 839371</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+<div itemscope>
+ <data id="d1" itemprop="product-id" value="9678AOU879">The Instigator 2000</data>
+</div>
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 839371 **/
+
+var d1 = document.getElementById("d1"),
+ d2 = document.createElement("data");
+
+// .value IDL
+is(d1.value, "9678AOU879", "value property reflects content attribute");
+d1.value = "123";
+is(d1.value, "123", "value property can be set via setter");
+
+// .value reflects value attribute
+reflectString({
+ element: d2,
+ attribute: "value"
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug839913.html b/dom/html/test/test_bug839913.html
new file mode 100644
index 000000000..7397fa3b6
--- /dev/null
+++ b/dom/html/test/test_bug839913.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for HTMLAreaElement's stringifier</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+test(function() {
+ var area = document.createElement("area");
+ area.href = "http://example.org/";
+ assert_equals(area.href, "http://example.org/");
+ assert_equals(String(area), "http://example.org/");
+}, "Area elements should stringify to the href attribute");
+</script>
diff --git a/dom/html/test/test_bug841466.html b/dom/html/test/test_bug841466.html
new file mode 100644
index 000000000..260ecfcca
--- /dev/null
+++ b/dom/html/test/test_bug841466.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=841466
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 841466</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+ <script>
+ /** Test for Bug 841466 **/
+var els = ['button', 'fieldset', 'input', 'keygen', 'object', 'output', 'select', 'textarea'];
+var code = "try { is(foo, 'bar', 'expected value bar from expando on element ' + localName); } catch (e) { ok(false, String(e)); }";
+els.forEach(function(el) {
+ var f = document.createElement("form");
+ f.foo = "bar";
+ f.innerHTML = '<' + el + ' onclick="' + code + '">';
+ var e = f.firstChild
+ if (el === "keygen") {
+ todo_is(e.localName, "keygen", "Bug 101019");
+ return;
+ }
+ e.dispatchEvent(new Event("click"));
+})
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=841466">Mozilla Bug 841466</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug845057.html b/dom/html/test/test_bug845057.html
new file mode 100644
index 000000000..631cd2b5c
--- /dev/null
+++ b/dom/html/test/test_bug845057.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=845057
+-->
+<head>
+ <title>Test for Bug 845057</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=845057">Mozilla Bug 845057</a>
+<p id="display"></p>
+<div id="content">
+ <iframe id="iframe" sandbox="allow-scripts"></iframe>
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+ var iframe = document.getElementById("iframe"),
+ attr = iframe.sandbox;
+ // Security enforcement tests for iframe sandbox are in test_iframe_*
+
+ function eq(a, b) {
+ // check if two attributes are qual modulo permutation
+ return ((a+'').split(" ").sort()+'') == ((b+'').split(" ").sort()+'');
+ }
+
+ ok(attr instanceof DOMTokenList,
+ "Iframe sandbox attribute is instace of DOMTokenList");
+ ok(eq(attr, "allow-scripts") &&
+ eq(iframe.getAttribute("sandbox"), "allow-scripts"),
+ "Stringyfied sandbox attribute is same as that of the DOM element");
+
+ ok(attr.contains("allow-scripts") && !attr.contains("allow-same-origin"),
+ "Set membership of attribute elements is ok");
+
+ attr.add("allow-same-origin");
+
+ ok(attr.contains("allow-scripts") && attr.contains("allow-same-origin"),
+ "Attribute contains added atom");
+ ok(eq(attr, "allow-scripts allow-same-origin") &&
+ eq(iframe.getAttribute("sandbox"), "allow-scripts allow-same-origin"),
+ "Stringyfied attribute with new atom is correct");
+
+ attr.add("allow-forms");
+ attr.remove("allow-scripts");
+
+ ok(!attr.contains("allow-scripts") && attr.contains("allow-forms") &&
+ attr.contains("allow-same-origin"),
+ "Attribute does not contain removed atom");
+ ok(eq(attr, "allow-forms allow-same-origin") &&
+ eq(iframe.getAttribute("sandbox"), "allow-forms allow-same-origin"),
+ "Stringyfied attribute with removed atom is correct");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_bug869040.html b/dom/html/test/test_bug869040.html
new file mode 100644
index 000000000..bfd75c7b7
--- /dev/null
+++ b/dom/html/test/test_bug869040.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=869040
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 869040</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=869040">Mozilla Bug 869040</a>
+<p id="display"></p>
+<div id="content" style="display: none" data-foo="present1" data-bar="present2">
+
+</div>
+<pre id="test">
+</pre>
+ <script type="application/javascript">
+
+ /** Test for Bug 869040 **/
+ var foo = "default1";
+ var dataset = $("content").dataset;
+ for (var i = 0; i < 100000; ++i)
+ foo = dataset.foo;
+
+ var bar = "default2";
+ for (var j = 0; j < 100; ++j)
+ bar = dataset.bar;
+
+ is(foo, "present1", "Our IC should work");
+ is(bar, "present2", "Our non-IC case should work");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/test_bug870787.html b/dom/html/test/test_bug870787.html
new file mode 100644
index 000000000..92a871284
--- /dev/null
+++ b/dom/html/test/test_bug870787.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=870787
+-->
+<head>
+ <title>Test for Bug 870787</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=870787">Mozilla Bug 870787</a>
+
+<p id="msg"></p>
+
+<form id="form0"></form>
+<img name="img0" id="img0id">
+
+<img name="img1" id="img1id" />
+<form id="form1">
+ <img name="img2" id="img2id" />
+</form>
+<img name="img3" id="img3id" />
+
+<table>
+ <form id="form2">
+ <tr><td>
+ <button name="input1" id="input1id" />
+ <input name="input2" id="input2id" />
+ </form>
+</table>
+
+<table>
+ <form id="form3">
+ <tr><td>
+ <img name="img4" id="img4id" />
+ <img name="img5" id="img5id" />
+ </form>
+</table>
+
+<form id="form4"><img id="img6"></form>
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 870787 **/
+
+var form0 = document.getElementById("form0");
+ok(form0, "Form0 exists");
+ok(!form0.img0, "Form0.img0 doesn't exist");
+ok(!form0.img0id, "Form0.img0id doesn't exist");
+
+var form1 = document.getElementById("form1");
+ok(form1, "Form1 exists");
+ok(!form1.img1, "Form1.img1 doesn't exist");
+ok(!form1.img1id, "Form1.img1id doesn't exist");
+is(form1.img2, document.getElementById("img2id"), "Form1.img2 exists");
+is(form1.img2id, document.getElementById("img2id"), "Form1.img2id exists");
+ok(!form1.img3, "Form1.img3 doesn't exist");
+ok(!form1.img3id, "Form1.img3id doesn't exist");
+
+var form2 = document.getElementById("form2");
+ok(form2, "Form2 exists");
+is(form2.input1, document.getElementById("input1id"), "Form2.input1 exists");
+is(form2.input1id, document.getElementById("input1id"), "Form2.input1id exists");
+is(form2.input2, document.getElementById("input2id"), "Form2.input2 exists");
+is(form2.input2id, document.getElementById("input2id"), "Form2.input2id exists");
+
+var form3 = document.getElementById("form3");
+ok(form3, "Form3 exists");
+is(form3.img4, document.getElementById("img4id"), "Form3.img4 doesn't exists");
+is(form3.img4id, document.getElementById("img4id"), "Form3.img4id doesn't exists");
+is(form3.img5, document.getElementById("img5id"), "Form3.img5 doesn't exists");
+is(form3.img5id, document.getElementById("img5id"), "Form3.img5id doesn't exists");
+
+var form4 = document.getElementById("form4");
+ok(form4, "Form4 exists");
+is(Object.getOwnPropertyNames(form4.elements).indexOf("img6"), -1, "Form4.elements should not contain img6");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug871161.html b/dom/html/test/test_bug871161.html
new file mode 100644
index 000000000..c2049b25b
--- /dev/null
+++ b/dom/html/test/test_bug871161.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=871161
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 871161</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 871161 **/
+ SimpleTest.waitForExplicitFinish();
+
+ window.onmessage = function(e) {
+ is(e.data, "windows-1252", "Wrong charset");
+ e.source.close();
+ SimpleTest.finish();
+ }
+
+ function run() {
+ window.open("file_bug871161-1.html");
+ }
+
+ </script>
+</head>
+<body onload="run();">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=871161">Mozilla Bug 871161</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug874758.html b/dom/html/test/test_bug874758.html
new file mode 100644
index 000000000..b8bfe40f3
--- /dev/null
+++ b/dom/html/test/test_bug874758.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html data-expando-prop="xyz">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=874758
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 874758</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 874758 **/
+ Object.prototype.expandoProp = 5;
+ is({}.expandoProp, 5, "Should see this on random objects");
+
+ is(document.head.dataset.expandoProp, 5, "Should see this on dataset too");
+ is(document.documentElement.dataset.expandoProp, "xyz",
+ "But if the dataset has it, we should get it from there");
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=874758">Mozilla Bug 874758</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug879319.html b/dom/html/test/test_bug879319.html
new file mode 100644
index 000000000..a232461ba
--- /dev/null
+++ b/dom/html/test/test_bug879319.html
@@ -0,0 +1,92 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=879319
+-->
+<head>
+ <title>Test for Bug 879319</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=879319">Mozilla Bug 879319</a>
+
+<p id="msg"></p>
+
+<form id="form">
+ <img id="img0" name="bar0" />
+</form>
+<input id="input0" name="foo0" form="form" />
+<input id="input1" name="foo1" form="form" />
+<input id="input2" name="foo2" form="form" />
+
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 879319 **/
+
+var input0 = document.getElementById("input0");
+ok(input0, "input0 exists");
+
+var form = document.getElementById("form");
+ok(form, "form exists");
+is(form.foo0, input0, "Form.foo0 should exist");
+
+ok("foo0" in form.elements, "foo0 in form.elements");
+is(input0.form, form, "input0.form is form");
+
+input0.setAttribute("name", "tmp0");
+ok("tmp0" in form.elements, "tmp0 is in form.elements");
+ok(!("foo0" in form.elements), "foo0 is not in form.elements");
+is(form.tmp0, input0, "Form.tmp0 == input0");
+is(form.foo0, input0, "Form.foo0 is still here");
+
+input0.setAttribute("name", "tmp1");
+ok("tmp1" in form.elements, "tmp1 is in form.elements");
+ok(!("tmp0" in form.elements), "tmp0 is not in form.elements");
+ok(!("foo0" in form.elements), "foo0 is not in form.elements");
+is(form.tmp0, input0, "Form.tmp0 == input0");
+is(form.tmp1, input0, "Form.tmp1 == input0");
+is(form.foo0, input0, "Form.foo0 is still here");
+
+input0.setAttribute("form", "");
+ok(!("foo0" in form.elements), "foo0 is not in form.elements");
+is(form.foo0, undefined, "Form.foo0 should not still be here");
+is(form.tmp0, undefined, "Form.tmp0 should not still be here");
+is(form.tmp1, undefined, "Form.tmp1 should not still be here");
+
+var input1 = document.getElementById("input1");
+ok(input1, "input1 exists");
+is(form.foo1, input1, "Form.foo1 should exist");
+
+ok("foo1" in form.elements, "foo1 in form.elements");
+is(input1.form, form, "input1.form is form");
+
+input1.setAttribute("name", "foo0");
+ok("foo0" in form.elements, "foo0 is in form.elements");
+is(form.foo0, input1, "Form.foo0 should be input1");
+is(form.foo1, input1, "Form.foo1 should be input1");
+
+var input2 = document.getElementById("input2");
+ok(input2, "input2 exists");
+is(form.foo2, input2, "Form.foo2 should exist");
+input2.parentNode.removeChild(input2);
+ok(!("foo2" in form.elements), "foo2 is not in form.elements");
+is(form.foo2, undefined, "Form.foo2 should not longer be there");
+
+var img0 = document.getElementById("img0");
+ok(img0, "img0 exists");
+is(form.bar0, img0, "Form.bar0 should exist");
+
+img0.setAttribute("name", "old_bar0");
+is(form.old_bar0, img0, "Form.bar0 is still here");
+is(form.bar0, img0, "Form.bar0 is still here");
+
+img0.parentNode.removeChild(img0);
+is(form.bar0, undefined, "Form.bar0 should not be here");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug885024.html b/dom/html/test/test_bug885024.html
new file mode 100644
index 000000000..118c140bd
--- /dev/null
+++ b/dom/html/test/test_bug885024.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html data-expando-prop="xyz">
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=885024
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 885024</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=885024">Mozilla Bug 885024</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+
+<img form="t">
+
+<form id="form">
+ <div id="div"></div>
+</form>
+
+<pre id="test">
+ <script type="application/javascript">
+ var img = document.createElement('img');
+ img.setAttribute('id', 'img');
+
+ var div = document.getElementById('div');
+ div.appendChild(img);
+
+ var form = document.getElementById('form');
+ ok(form, "form exists");
+ ok(form.img, "form.img exists");
+
+ var img2 = document.createElement('img');
+ img2.setAttribute('id', 'img2');
+ img2.setAttribute('form', 'blabla');
+ ok(form, "form exists2");
+ div.appendChild(img2);
+ ok(form.img2, "form.img2 exists");
+
+ </script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug893537.html b/dom/html/test/test_bug893537.html
new file mode 100644
index 000000000..5935529d8
--- /dev/null
+++ b/dom/html/test/test_bug893537.html
@@ -0,0 +1,45 @@
+<!doctype html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=893537
+-->
+ <head>
+<title>Test for crash caused by unloading and reloading srcdoc iframes</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=893537">Mozilla Bug 893537</a>
+
+<iframe id="pframe" src="file_bug893537.html"></iframe>
+
+<pre id="test">
+<script>
+ <!-- Bug 895303 -->
+ SimpleTest.expectAssertions(0, 1);
+
+ SimpleTest.waitForExplicitFinish();
+ var pframe = $("pframe");
+
+ var loadState = 1;
+ pframe.contentWindow.addEventListener("load", function () {
+
+ if (loadState == 1) {
+ var iframe = pframe.contentDocument.getElementById("iframe");
+ iframe.removeAttribute("srcdoc");
+ loadState = 2;
+ }
+ if (loadState == 2) {
+ SimpleTest.executeSoon(function () { pframe.contentWindow.location.reload() });
+ loadState = 3;
+ }
+ if (loadState == 3) {
+ ok(true, "This is a mochitest implementation of a crashtest. To finish is to pass");
+ SimpleTest.finish();
+ }
+ });
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug95530.html b/dom/html/test/test_bug95530.html
new file mode 100644
index 000000000..05cbd709b
--- /dev/null
+++ b/dom/html/test/test_bug95530.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=95530
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 95530</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 95530 **/
+ function run() {
+ is(document.compatMode, "CSS1Compat", "Ensure we are in standards mode, not quirks mode.");
+
+ var body = document.getElementsByTagName("body");
+
+ is(computedStyle(body[0],"margin-top"), "100px", "Ensure margin-top matches topmargin");
+ is(computedStyle(body[0],"margin-bottom"), "150px", "Ensure margin-bottom matches bottommargin");
+ is(computedStyle(body[0],"margin-left"), "23px", "Ensure margin-left matches leftmargin");
+ is(computedStyle(body[0],"margin-right"), "64px", "Ensure margin-right matches rightmargin");
+ SimpleTest.finish();
+ }
+ SimpleTest.waitForExplicitFinish();
+ window.addEventListener("load", run, false);
+ </script>
+</head>
+<body topmargin="100" bottommargin="150" leftmargin="23" rightmargin="64">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=95530">Mozilla Bug 95530</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug969346.html b/dom/html/test/test_bug969346.html
new file mode 100644
index 000000000..5be76c46e
--- /dev/null
+++ b/dom/html/test/test_bug969346.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=969346
+-->
+<head>
+<title>Nesting of srcdoc iframes is permitted</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=969349">Mozilla Bug 969346</a>
+
+<iframe id="pframe" srcdoc="<iframe id='iframe' srcdoc='I am nested'></iframe"></iframe>
+
+<pre id="test">
+<script>
+
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(function () {
+ var pframe = $("pframe");
+ var pframeDoc = pframe.contentDocument;
+ var iframe = pframeDoc.getElementById("iframe");
+ var innerDoc = iframe.contentDocument;
+
+ is(innerDoc.body.innerHTML, "I am nested", "Nesting not working?");
+ SimpleTest.finish();
+ });
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_bug982039.html b/dom/html/test/test_bug982039.html
new file mode 100644
index 000000000..22833440f
--- /dev/null
+++ b/dom/html/test/test_bug982039.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=982039
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 982039</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 982039 **/
+ SimpleTest.waitForExplicitFinish();
+ function test() {
+ var f = document.getElementById("testform");
+ f.elements[0].disabled = true;
+ is(f.checkValidity(), false,
+ "Setting a radiobutton to disabled shouldn't make form valid.");
+
+ f.elements[1].checked = true;
+ ok(f.checkValidity(), "Form should be now valid.");
+
+ f.elements[0].required = false;
+ f.elements[1].required = false;
+ f.elements[2].required = false;
+ SimpleTest.finish();
+ }
+
+ </script>
+</head>
+<body onload="test()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982039">Mozilla Bug 982039</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+<form action="#" id="testform">
+ <input type="radio" name="radio" value="1" required>
+ <input type="radio" name="radio" value="2" required>
+ <input type="radio" name="radio" value="3" required>
+</form>
+</body>
+</html>
diff --git a/dom/html/test/test_change_crossorigin.html b/dom/html/test/test_change_crossorigin.html
new file mode 100644
index 000000000..01f31bc09
--- /dev/null
+++ b/dom/html/test/test_change_crossorigin.html
@@ -0,0 +1,89 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=696451
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 696451</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 696451 **/
+
+ SimpleTest.waitForExplicitFinish();
+
+ var img = new Image,
+ canvas = document.createElement("canvas"),
+ ctx = canvas.getContext("2d"),
+ src = "http://example.com/tests/dom/html/test/image-allow-credentials.png",
+ imgDone = false,
+ imgNotAllowedToLoadDone = false;
+
+ img.src = src;
+ img.crossOrigin = "Anonymous";
+
+ img.addEventListener("load", function() {
+ canvas.width = img.width;
+ canvas.height = img.height;
+ ctx.drawImage( img, 0, 0 );
+ try {
+ canvas.toDataURL("image/png");
+ ok(true, "Image was refetched with setting crossOrigin.");
+ } catch (e) {
+ ok(false, "Image was not refetched after setting crossOrigin.");
+ }
+
+ imgDone = true;
+ if (imgDone && imgNotAllowedToLoadDone) {
+ SimpleTest.finish();
+ }
+ });
+
+ img.addEventListener("error", function (event) {
+ ok(false, "Should be able to load cross origin image with proper headers.");
+
+ imgDone = true;
+ if (imgDone && imgNotAllowedToLoadDone) {
+ SimpleTest.finish();
+ }
+ });
+
+ var imgNotAllowedToLoad = new Image;
+
+ imgNotAllowedToLoad.src = "http://example.com/tests/dom/html/test/image.png";
+
+ imgNotAllowedToLoad.crossOrigin = "Anonymous";
+
+ imgNotAllowedToLoad.addEventListener("load", function() {
+ ok(false, "Image should not be allowed to load without " +
+ "allow-cross-origin-access headers.");
+
+ imgNotAllowedToLoadDone = true;
+ if (imgDone && imgNotAllowedToLoadDone) {
+ SimpleTest.finish();
+ }
+ });
+
+ imgNotAllowedToLoad.addEventListener("error", function() {
+ ok(true, "Image should not be allowed to load without " +
+ "allow-cross-origin-access headers.");
+ imgNotAllowedToLoadDone = true;
+ if (imgDone && imgNotAllowedToLoadDone) {
+ SimpleTest.finish();
+ }
+ });
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=696451">Mozilla Bug 696451</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_checked.html b/dom/html/test/test_checked.html
new file mode 100644
index 000000000..9d40a6ded
--- /dev/null
+++ b/dom/html/test/test_checked.html
@@ -0,0 +1,358 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=418756
+https://bugzilla.mozilla.org/show_bug.cgi?id=617528
+-->
+<head>
+ <title>Test for Bug 418756 and 617528</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+Mozilla bug
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=418756">418756</a>
+and
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=617528">617528</a>
+<p id="display"></p>
+<div id="content">
+ <form id="f1">
+ </form>
+ <form id="f2">
+ </form>
+ <menu id="m1">
+ </menu>
+ <menu id="m2">
+ </menu>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript; version=1.7">
+
+/** Test for Bug 418756 and 617528 **/
+var group1;
+var group2;
+var group3;
+
+var tags = ["input", "menuitem"];
+for (let tag of tags) {
+
+function bounce(node) {
+ let n = node.nextSibling;
+ let p = node.parentNode;
+ p.removeChild(node);
+ p.insertBefore(node, n);
+}
+
+var createdNodes = [];
+
+function cleanup() {
+ for (let node of createdNodes) {
+ if (node.parentNode) {
+ node.parentNode.removeChild(node);
+ }
+ }
+
+ createdNodes = [];
+}
+
+var typeMapper = {
+ 'c': 'checkbox',
+ 'r': 'radio'
+};
+
+var id = 0;
+
+// type can be 'c' for 'checkbox' and 'r' for 'radio'
+function createNode(type, name, checked) {
+ let node = document.createElement(tag);
+ node.setAttribute("type", typeMapper[type]);
+ if (checked) {
+ node.setAttribute("checked", "checked");
+ }
+ node.setAttribute("id", type + (++id));
+ node.setAttribute(tag == "input" ? "name" : "radiogroup", name);
+ createdNodes.push(node);
+ return node;
+}
+
+var types = ['c', 'r'];
+
+// First make sure that setting .checked makes .defaultChecked changes no
+// longer affect .checked.
+for (let type of types) {
+ let n = createNode(type, '', false);
+ is(n.defaultChecked, false, "Bogus defaultChecked on " + typeMapper[type]);
+ is(n.checked, false, "Bogus checked on " + typeMapper[type]);
+ n.defaultChecked = true;
+ is(n.defaultChecked, true, "Bogus defaultChecked on " + typeMapper[type] +
+ "after mutation");
+ is(n.checked, true, "Bogus checked on " + typeMapper[type] +
+ "after mutation");
+ n.checked = false;
+ is(n.defaultChecked, true, "Bogus defaultChecked on " + typeMapper[type] +
+ "after second mutation");
+ is(n.checked, false, "Bogus checked on " + typeMapper[type] +
+ "after second mutation");
+ n.defaultChecked = false;
+ is(n.defaultChecked, false, "Bogus defaultChecked on " + typeMapper[type] +
+ "after third mutation");
+ is(n.checked, false, "Bogus checked on " + typeMapper[type] +
+ "after third mutation");
+ n.defaultChecked = true;
+ is(n.defaultChecked, true, "Bogus defaultChecked on " + typeMapper[type] +
+ "after fourth mutation");
+ is(n.checked, false, "Bogus checked on " + typeMapper[type] +
+ "after fourth mutation");
+}
+
+cleanup();
+
+// Now check that bouncing a control that's the only one of its kind has no
+// effect
+for (let type of types) {
+ let n = createNode(type, 'test1', true);
+ $(tag == "input" ? "f1" : "m1").appendChild(n);
+ n.checked = false;
+ n.defaultChecked = false;
+ bounce(n);
+ n.defaultChecked = true;
+ is(n.checked, false, "We set .checked on this " + typeMapper[type]);
+}
+
+cleanup();
+
+// Now check that playing with a single radio in a group affects all
+// other radios in the group (but not radios not in that group)
+group1 = [ createNode('r', 'g1', false),
+ createNode('r', 'g1', false),
+ createNode('r', 'g1', false) ];
+group2 = [ createNode('r', 'g2', false),
+ createNode('r', 'g2', false),
+ createNode('r', 'g2', false) ];
+group3 = [ createNode('r', 'g1', false),
+ createNode('r', 'g1', false),
+ createNode('r', 'g1', false) ];
+for (let g of group1) {
+ $(tag == "input" ? "f1" : "m1").appendChild(g);
+}
+for (let g of group2) {
+ $(tag == "input" ? "f1" : "m1").appendChild(g);
+}
+for (let g of group3) {
+ $(tag == "input" ? "f2" : "m2").appendChild(g);
+}
+
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, false,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 1");
+ is(g.checked, false,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checkedhecked wrong pass 1");
+ }
+}
+
+group1[1].defaultChecked = true;
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1 && group1.indexOf(g) == 1,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 2");
+ is(g.checked, n == 1 && group1.indexOf(g) == 1,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 2");
+ }
+}
+
+group1[0].defaultChecked = true;
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 1 ||
+ group1.indexOf(g) == 0),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 3");
+ is(g.checked, n == 1 && group1.indexOf(g) == 0,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 3");
+ }
+}
+
+group1[2].defaultChecked = true;
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 4");
+ is(g.checked, n == 1 && group1.indexOf(g) == 2,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 4");
+ }
+}
+
+var next = group1[1].nextSibling;
+var p = group1[1].parentNode;
+p.removeChild(group1[1]);
+group1[1].defaultChecked = false;
+group1[1].defaultChecked = true;
+p.insertBefore(group1[1], next);
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 5");
+ is(g.checked, n == 1 && group1.indexOf(g) == 1,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 5");
+ }
+}
+
+for (let g of group1) {
+ g.defaultChecked = false;
+}
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, false,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 6");
+ is(g.checked, false,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checkedhecked wrong pass 6");
+ }
+}
+
+group1[1].checked = true;
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, false,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 7");
+ is(g.checked, n == 1 && group1.indexOf(g) == 1,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 7");
+ }
+}
+
+group1[0].defaultChecked = true;
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1 && group1.indexOf(g) == 0,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 8");
+ is(g.checked, n == 1 && group1.indexOf(g) == 1,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 8");
+ }
+}
+
+group1[2].defaultChecked = true;
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 ||
+ group1.indexOf(g) == 2),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 9");
+ is(g.checked, n == 1 && group1.indexOf(g) == 1,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 9");
+ }
+}
+group1[1].parentNode.removeChild(group1[1]);
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 ||
+ group1.indexOf(g) == 2),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 10");
+ is(g.checked, n == 1 && group1.indexOf(g) == 1,
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 10");
+ }
+}
+
+group1[2].checked = true;
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 ||
+ group1.indexOf(g) == 2),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 11");
+ is(g.checked, n == 1 && (group1.indexOf(g) == 1 ||
+ group1.indexOf(g) == 2),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 11");
+ }
+}
+
+group1[0].checked = true;
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 ||
+ group1.indexOf(g) == 2),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 12");
+ is(g.checked, n == 1 && (group1.indexOf(g) == 1 ||
+ group1.indexOf(g) == 0),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 12");
+ }
+}
+
+next = group2[1].nextSibling;
+p = group2[1].parentNode;
+p.removeChild(group2[1]);
+p.insertBefore(group2[1], next);
+group2[0].checked = true;
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 ||
+ group1.indexOf(g) == 2),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 13");
+ is(g.checked, (n == 1 && (group1.indexOf(g) == 1 ||
+ group1.indexOf(g) == 0)) ||
+ (n == 2 && group2.indexOf(g) == 0),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 13");
+ }
+}
+
+p.insertBefore(group2[1], next);
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, n == 1 && (group1.indexOf(g) == 0 ||
+ group1.indexOf(g) == 2),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 14");
+ is(g.checked, (n == 1 && (group1.indexOf(g) == 1 ||
+ group1.indexOf(g) == 0)) ||
+ (n == 2 && group2.indexOf(g) == 0),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 14");
+ }
+}
+
+group2[1].defaultChecked = true;
+for (let n of [1, 2, 3]) {
+ for (let g of window["group"+n]) {
+ is(g.defaultChecked, (n == 1 && (group1.indexOf(g) == 0 ||
+ group1.indexOf(g) == 2)) ||
+ (n == 2 && group2.indexOf(g) == 1),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] defaultChecked wrong pass 15");
+ is(g.checked, (n == 1 && (group1.indexOf(g) == 1 ||
+ group1.indexOf(g) == 0)) ||
+ (n == 2 && group2.indexOf(g) == 0),
+ "group" + n + "[" + window["group"+n].indexOf(g) +
+ "] checked wrong pass 15");
+ }
+}
+
+cleanup();
+
+}
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_dir_attributes_reflection.html b/dom/html/test/test_dir_attributes_reflection.html
new file mode 100644
index 000000000..c9c4022a3
--- /dev/null
+++ b/dom/html/test/test_dir_attributes_reflection.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLDirectoryElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLDirectoryElement attributes reflection **/
+
+// .name
+reflectBoolean({
+ element: document.createElement("dir"),
+ attribute: "compact",
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_dl_attributes_reflection.html b/dom/html/test/test_dl_attributes_reflection.html
new file mode 100644
index 000000000..1fbab51ab
--- /dev/null
+++ b/dom/html/test/test_dl_attributes_reflection.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLDListElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLDListElement attributes reflection **/
+
+// .compact
+reflectBoolean({
+ element: document.createElement("dl"),
+ attribute: "compact"
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_document-element-inserted.html b/dom/html/test/test_document-element-inserted.html
new file mode 100644
index 000000000..483d0cb0a
--- /dev/null
+++ b/dom/html/test/test_document-element-inserted.html
@@ -0,0 +1,54 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Media test: document-element-inserted</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<iframe id = 'media'>
+</iframe>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+if (navigator.platform.startsWith("Win")) {
+ SimpleTest.expectAssertions(0, 4);
+}
+
+SimpleTest.waitForExplicitFinish();
+var loc;
+
+var observe = function(doc){
+ if (doc == media.contentDocument) {
+ ok(media.contentDocument.location.toString().indexOf(loc) != -1,
+ "The loaded media should be " + loc);
+ next();
+ }
+}
+
+var media = document.getElementById('media');
+var tests = [
+ "../../../media/test/short-video.ogv",
+ "../../../media/test/sound.ogg",
+ "../../content/test/image.png"
+]
+
+function next() {
+ if (tests.length > 0) {
+ var t = tests.shift();
+ loc = t.substring(t.indexOf("test"));
+ media.setAttribute("src",t);
+ }
+ else {
+ SpecialPowers.removeObserver(observe, "document-element-inserted");
+ SimpleTest.finish();
+ }
+}
+
+SpecialPowers.addObserver(observe, "document-element-inserted", false)
+next();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_document.watch.html b/dom/html/test/test_document.watch.html
new file mode 100644
index 000000000..54509823b
--- /dev/null
+++ b/dom/html/test/test_document.watch.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=903332
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 903332</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 903332 **/
+
+ var watch1Called;
+ function watch1(prop, oldValue, newValue)
+ {
+ is(watch1Called, false, "watch1Called not reset properly?");
+ watch1Called = true;
+
+ is(prop, "cookie", "wrong property name passed to watch1");
+ return newValue;
+ }
+
+ var watch2Called;
+ function watch2(prop, oldValue, newValue)
+ {
+ is(watch2Called, false, "watch2Called not reset properly?");
+ watch2Called = true;
+
+ is(prop, "cookie", "wrong property name passed to watch2");
+ return newValue;
+ }
+
+ // Just in case subsequent tests depend on a particular value...
+ var originalValue = document.cookie;
+ ok(true, "originalValue: " + originalValue);
+
+ var originalPrefix = originalValue.length > 0 ? originalValue + "; " : "";
+
+ try
+ {
+ // trial set (no watch) to verify things work
+ document.cookie = "first=set";
+ is(document.cookie, originalPrefix + "first=set",
+ "first value correct");
+
+ // add a watch
+ document.watch("cookie", watch1);
+
+ // set, check for watch invoked
+ watch1Called = false;
+ document.cookie = "second=set";
+ is(watch1Called, true, "watch1 function should be called");
+ is(document.cookie, originalPrefix + "first=set; second=set",
+ "second value correct");
+
+ // and a second time, just in case
+ watch1Called = false;
+ document.cookie = "third=set";
+ is(watch1Called, true, "watch1 function should be called");
+ is(document.cookie, originalPrefix + "first=set; second=set; third=set",
+ "third value correct");
+
+ // overwrite the current watch with a new one
+ document.watch("cookie", watch2);
+
+ // set, check for watch invoked
+ watch1Called = false;
+ watch2Called = false;
+ document.cookie = "fourth=set";
+ is(watch1Called, false, "watch1 invoked erroneously");
+ is(watch2Called, true, "watch2 function should be called");
+ is(document.cookie, originalPrefix + "first=set; second=set; third=set; fourth=set",
+ "fourth value correct");
+
+ // and a second time, just in case
+ watch1Called = false;
+ watch2Called = false;
+ document.cookie = "fifth=set";
+ is(watch1Called, false, "watch1 invoked erroneously");
+ is(watch2Called, true, "watch2 function should be called");
+ is(document.cookie, originalPrefix + "first=set; second=set; third=set; fourth=set; fifth=set",
+ "fifth value correct");
+
+ // remove the watch
+ document.unwatch("cookie");
+
+ // check for non-invocation now
+ watch1Called = false;
+ watch2Called = false;
+ document.cookie = "sixth=set";
+ is(watch1Called, false, "watch1 shouldn't be called");
+ is(watch2Called, false, "watch2 shouldn't be called");
+ is(document.cookie, originalPrefix + "first=set; second=set; third=set; fourth=set; fifth=set; sixth=set",
+ "sixth value correct");
+ }
+ finally
+ {
+ // reset
+ document.unwatch("cookie"); // harmless, should be no-op except if bugs
+
+ var d = new Date();
+ d.setTime(0);
+ var suffix = "=; expires=" + d.toGMTString();
+
+ document.cookie = "first" + suffix;
+ document.cookie = "second" + suffix;
+ document.cookie = "third" + suffix;
+ document.cookie = "fourth" + suffix;
+ document.cookie = "fifth" + suffix;
+ document.cookie = "sixth" + suffix;
+ }
+
+ is(document.cookie, originalValue,
+ "document.cookie isn't what it was initially! expect bustage further " +
+ "down the line");
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=903332">Mozilla Bug 903332</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_documentAll.html b/dom/html/test/test_documentAll.html
new file mode 100644
index 000000000..ec877acec
--- /dev/null
+++ b/dom/html/test/test_documentAll.html
@@ -0,0 +1,167 @@
+<html>
+<!--
+Tests for document.all
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Tests for document.all</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=259332">Mozilla Bug 259332</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=393629">Mozilla Bug 393629</a>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=448904">Mozilla Bug 448904</a>
+<p id="display">
+</p>
+<div id="content" style="display: none">
+ <a id="id1">A</a>
+ <a id="id2">B</a>
+ <a id="id2">C</a>
+ <a id="id3">D</a>
+ <a id="id3">E</a>
+ <a id="id3">F</a>
+</div>
+<iframe id="subframe" src="data:text/html,<span id='x'></span>"
+ style="display: none"></iframe>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+p = document.getElementById("content");
+
+// Test that several elements with the same id or name behave correctly
+function testNumSame() {
+ is(document.all.id0, undefined, "no ids");
+ is(document.all.namedItem("id0"), null, "no ids");
+ is(document.all.id1, p.children[0], "one id");
+ is(document.all.id2[0], p.children[1], "two ids");
+ is(document.all.id2[1], p.children[2], "two ids");
+ is(document.all.id2.length, 2, "two length");
+ is(document.all.id3[0], p.children[3], "three ids");
+ is(document.all.id3[1], p.children[4], "three ids");
+ is(document.all.id3[2], p.children[5], "three ids");
+ is(document.all.id3.length, 3, "three length");
+}
+testNumSame();
+p.innerHTML = p.innerHTML.replace(/id=/g, "name=");
+testNumSame();
+
+
+// Test that dynamic changes behave properly
+
+// Add two elements and check that they are added to the correct lists
+child = Array.prototype.slice.call(p.children);
+child[6] = document.createElement("a");
+child[6].id = "id0";
+p.appendChild(child[6]);
+child[7] = document.createElement("a");
+child[7].id = "id1";
+p.appendChild(child[7]);
+is(document.all.id0, child[6], "now one id");
+is(document.all.id1[0], child[0], "now two ids");
+is(document.all.id1[1], child[7], "now two ids");
+is(document.all.id1.length, 2, "now two length");
+
+// Remove and element and check that the list shrinks
+rC(child[1]);
+is(document.all.id2, child[2], "now just one id");
+
+// Change an id and check that its removed and added to the correct lists
+child[4].name = "id1";
+is(document.all.id1[0], child[0], "now three ids");
+is(document.all.id1[1], child[4], "now three ids");
+is(document.all.id1[2], child[7], "now three ids");
+is(document.all.id1.length, 3, "now three length");
+is(document.all.id3[1], child[5], "now just two ids");
+is(document.all.id3.length, 2, "now two length");
+
+// Remove all elements from a list and check that it goes empty
+id3list = document.all.id3;
+rC(child[3]);
+is(id3list.length, 1, "now one length");
+rC(child[5]);
+is(document.all.id3, undefined, "now none");
+is(document.all.namedItem("id3"), null, "now none (namedItem)");
+is(id3list.length, 0, "now none length");
+
+// Give an element both a name and id and check that it appears in two lists
+p.insertBefore(child[1], child[2]); // restore previously removed
+id1list = document.all.id1;
+id2list = document.all.id2;
+child[1].id = "id1";
+is(id1list[0], child[0], "now four ids");
+is(id1list[1], child[1], "now four ids");
+is(id1list[2], child[4], "now four ids");
+is(id1list[3], child[7], "now four ids");
+is(id1list.length, 4, "now four length");
+is(id2list[0], child[1], "still two ids");
+is(id2list[1], child[2], "still two ids");
+is(id2list.length, 2, "still two length");
+
+
+// Check that document.all behaves list a list of all elements
+allElems = document.getElementsByTagName("*");
+ok(testArraysSame(document.all, allElems), "arrays same");
+length = document.all.length;
+expectedLength = length + p.getElementsByTagName("*").length + 1;
+p.appendChild(p.cloneNode(true));
+ok(testArraysSame(document.all, allElems), "arrays still same");
+is(document.all.length, expectedLength, "grew correctly");
+
+// Check which elements the 'name' attribute works on
+var elementNames =
+ ['applet','abbr','acronym','address','area','a','b','base',
+ 'bgsound','big','blockquote','br','canvas','center','cite','code',
+ 'col','colgroup','dd','del','dfn','dir','div','dir','dl','dt','em','embed',
+ 'fieldset','font','form','frame','frameset','head','i','iframe','img',
+ 'input','ins','isindex','kbd','keygen','label','li','legend','link','menu',
+ 'multicol','noscript','noframes','object','spacer','table','td','td','th',
+ 'thead','tfoot','tr','textarea','select','option','spacer','param',
+ 'marquee','hr','title','hx','tt','u','ul','var','wbr','sub','sup','cite',
+ 'code','q','nobr','ol','p','pre','s','samp','small','body','html','map',
+ 'bdo','legend','listing','style','script','tbody','caption','meta',
+ 'optgroup','button','span','strike','strong','td'].sort();
+var hasName =
+ ['applet','a','embed','form','iframe','img','input','object','textarea',
+ 'select','map','meta','button','frame','frameset'].sort();
+
+elementNames.forEach(function (name) {
+ nameval = 'namefor' + name;
+
+ e = document.createElement(name);
+ p.appendChild(e);
+ e.setAttribute('name', nameval);
+
+ if (name == hasName[0]) {
+ is(document.all[nameval], e, "should have name");
+ hasName.shift();
+ }
+ else {
+ is(document.all[nameval], undefined, "shouldn't have name");
+ is(document.all.namedItem(nameval), null, "shouldn't have name (namedItem)");
+ }
+});
+is(hasName.length, 0, "found all names");
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ var subdoc = $("subframe").contentDocument;
+ is(subdoc.all.x, subdoc.body.firstChild,
+ "document.all should work in a subdocument");
+ SimpleTest.finish();
+});
+
+// Utility functions
+function rC(node) {
+ node.parentNode.removeChild(node);
+}
+function testArraysSame(a1, a2) {
+ return Array.prototype.every.call(a1, function(e, index) {
+ return a2[index] === e;
+ }) && a1.length == a2.length;
+}
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_element_prototype.html b/dom/html/test/test_element_prototype.html
new file mode 100644
index 000000000..44ef4edd6
--- /dev/null
+++ b/dom/html/test/test_element_prototype.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=844127
+-->
+<head>
+ <title>Test for Bug 844127</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=844127">Mozilla Bug 844127</a>
+
+<script type="text/javascript">
+
+/** Test for Bug 844127 **/
+
+var a1 = document.createElement('bgsound');
+var a2 = document.createElement('image');
+var a3 = document.createElement('multicol');
+var a4 = document.createElement('spacer');
+var a5 = document.createElement('isindex');
+
+is(Object.getPrototypeOf(a1), HTMLUnknownElement.prototype, "Prototype for bgsound should be correct");
+is(Object.getPrototypeOf(a2), HTMLElement.prototype, "Prototype for image should be correct");
+is(Object.getPrototypeOf(a3), HTMLUnknownElement.prototype, "Prototype for multicol should be correct");
+is(Object.getPrototypeOf(a4), HTMLUnknownElement.prototype, "Prototype for spacer should be correct");
+is(Object.getPrototypeOf(a5), HTMLUnknownElement.prototype, "Prototype for isindex should be correct");
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_embed_attributes_reflection.html b/dom/html/test/test_embed_attributes_reflection.html
new file mode 100644
index 000000000..85001598a
--- /dev/null
+++ b/dom/html/test/test_embed_attributes_reflection.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLEmbedElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLEmbedElement attributes reflection **/
+
+// .src (URL)
+reflectURL({
+ element: document.createElement("embed"),
+ attribute: "src",
+});
+
+// .type (String)
+reflectString({
+ element: document.createElement("embed"),
+ attribute: "type",
+});
+
+// .width (String)
+reflectString({
+ element: document.createElement("embed"),
+ attribute: "width",
+});
+
+// .height (String)
+reflectString({
+ element: document.createElement("embed"),
+ attribute: "height",
+});
+
+// .align (String)
+reflectString({
+ element: document.createElement("embed"),
+ attribute: "align",
+});
+
+// .name (String)
+reflectString({
+ element: document.createElement("embed"),
+ attribute: "name",
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_filepicker_default_directory.html b/dom/html/test/test_filepicker_default_directory.html
new file mode 100644
index 000000000..c2212baa0
--- /dev/null
+++ b/dom/html/test/test_filepicker_default_directory.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1194893
+-->
+<head>
+ <title>Test for filepicker default directory</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1194893">Mozilla Bug 1194893</a>
+<div id="content">
+ <input type="file" id="f">
+</div>
+<pre id="text">
+<script class="testbody" type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+const { Cc: Cc, Ci: Ci } = SpecialPowers;
+
+// Platform-independent directory names are #define'd in xpcom/io/nsDirectoryServiceDefs.h
+var defaultUploadDirectory = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIDirectoryService)
+ .QueryInterface(Ci.nsIProperties)
+ .get("Desk", Ci.nsIFile);
+
+// When we want to test an upload directory other than the default, we need to
+// get a valid directory in a platform-independent way. Since NS_OS_DESKTOP_DIR
+// may fallback to NS_OS_HOME_DIR, let's use NS_OS_TMP_DIR.
+var customUploadDirectory = Cc["@mozilla.org/file/directory_service;1"]
+ .getService(Ci.nsIDirectoryService)
+ .QueryInterface(Ci.nsIProperties)
+ .get("TmpD", Ci.nsIFile);
+
+// Useful for debugging
+//info("defaultUploadDirectory" + defaultUploadDirectory.path);
+//info("customUploadDirectory" + customUploadDirectory.path);
+
+var MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+
+// need to show the MockFilePicker so .displayDirectory gets set
+var f = document.getElementById("f");
+f.focus();
+
+var testIndex = 0;
+var tests = [
+ ["", defaultUploadDirectory.path],
+ [customUploadDirectory.path, customUploadDirectory.path]
+]
+
+MockFilePicker.showCallback = function(filepicker) {
+ info(SpecialPowers.wrap(MockFilePicker).displayDirectory.path);
+
+ is(SpecialPowers.wrap(MockFilePicker).displayDirectory.path,
+ tests[testIndex][1]);
+
+ if (++testIndex == tests.length) {
+ MockFilePicker.cleanup();
+ SimpleTest.finish();
+ } else {
+ launchNextTest();
+ }
+}
+
+function launchNextTest() {
+ SpecialPowers.pushPrefEnv(
+ { 'set': [
+ ['dom.input.fallbackUploadDir', tests[testIndex][0]],
+ ]},
+ function () {
+ f.click();
+ });
+}
+
+launchNextTest();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_focusshift_button.html b/dom/html/test/test_focusshift_button.html
new file mode 100644
index 000000000..2ae4743be
--- /dev/null
+++ b/dom/html/test/test_focusshift_button.html
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for shifting focus while mouse clicking on button</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+
+<script class="testbody" type="application/javascript;version=1.7">
+
+var result = "";
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.waitForFocus(function() {
+ synthesizeMouseAtCenter(document.getElementById("button"), { });
+ if (/Mac/.test(navigator.platform)) {
+ // Buttons don't focus when clicked on Mac.
+ is(result, "", "Focus button then input");
+ }
+ else {
+ is(result, "(focus button)(blur button)(focus input)", "Focus button then input");
+ }
+ SimpleTest.finish();
+});
+</script>
+
+
+<button id="button" onfocus="result += '(focus button)'; document.getElementById('input').focus()"
+ onblur="result += '(blur button)'">Focus</button>
+<input id="input" value="Test" onfocus="result += '(focus input)'"
+ onblur="result += '(blur input)'">
+
+</body>
+</html>
diff --git a/dom/html/test/test_form-parsing.html b/dom/html/test/test_form-parsing.html
new file mode 100644
index 000000000..6a4a4c54e
--- /dev/null
+++ b/dom/html/test/test_form-parsing.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Form parsing</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<div id="content" style="display: none">
+ <div>
+ <form name="test" action="test" id="test">
+ <input type="text" name="text1" id="text1" />
+ <input type="text" name="text2" id="text2" />
+ </div>
+ <input type="text" name="text3" id="text3" />
+ <input type="text" name="text4" id="text4" />
+ <input type="text" name="text5" id="text5" />
+ <input type="text" name="text6" id="text6" />
+ </form>
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+ var form1 = document.getElementById("test");
+ var elem1 = form1.getElementsByTagName("*");
+ var elem1Length = elem1.length;
+ var form1ElementsLength = form1.elements.length;
+
+ is(form1ElementsLength, 6, "form.elements must include mis-nested elements");
+ is(elem1Length, 2, "form must not include mis-nested elements");
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_formData.html b/dom/html/test/test_formData.html
new file mode 100644
index 000000000..a8b1bc0f7
--- /dev/null
+++ b/dom/html/test/test_formData.html
@@ -0,0 +1,50 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=690659
+-->
+<head>
+ <title>Test for Bug 690659 and 739173</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=690659">Mozilla Bug 690659 & 739173</a>
+<script type="text/javascript" src="./formData_test.js"></script>
+<script type="text/javascript">
+SimpleTest.waitForExplicitFinish();
+
+function runMainThreadAndWorker() {
+ var mt = new Promise(function(resolve) {
+ runTest(resolve);
+ });
+
+ var worker;
+ var w = new Promise(function(resolve) {
+ worker = new Worker("formData_worker.js");
+ worker.onmessage = function(event) {
+ if (event.data.type == 'finish') {
+ resolve();
+ } else if (event.data.type == 'status') {
+ ok(event.data.status, event.data.msg);
+ } else if (event.data.type == 'todo') {
+ todo(event.data.status, event.data.msg);
+ }
+ }
+
+ worker.onerror = function(event) {
+ ok(false, "Worker had an error: " + event.message + " at " + event.lineno);
+ resolve();
+ };
+
+ worker.postMessage(true);
+ });
+
+ return Promise.all([mt, w]);
+}
+
+runMainThreadAndWorker().then(SimpleTest.finish);
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_formSubmission.html b/dom/html/test/test_formSubmission.html
new file mode 100644
index 000000000..0edfeaeb8
--- /dev/null
+++ b/dom/html/test/test_formSubmission.html
@@ -0,0 +1,825 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=523771
+-->
+<head>
+ <title>Test for Bug 523771</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=523771">Mozilla Bug 523771</a>
+<p id="display"></p>
+<iframe name="target_iframe" id="target_iframe"></iframe>
+<form action="form_submit_server.sjs" target="target_iframe" id="form"
+ method="POST" enctype="multipart/form-data">
+ <table>
+ <tr>
+ <td>Control type</td>
+ <td>Name and value</td>
+ <td>Name, empty value</td>
+ <td>Name, no value</td>
+ <td>Empty name, with value</td>
+ <td>No name, with value</td>
+ <td>No name or value</td>
+ <td>Strange name/value</td>
+ </tr>
+ <tr>
+ <td>Default input</td>
+ <td><input name="n1_1" value="v1_1"></td>
+ <td><input name="n1_2" value=""></td>
+ <td><input name="n1_3"></td>
+ <td><input name="" value="v1_4"></td>
+ <td><input value="v1_5"></td>
+ <td><input></td>
+ <td><input name="n1_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v1_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Text input</td>
+ <td><input type=text name="n2_1" value="v2_1"></td>
+ <td><input type=text name="n2_2" value=""></td>
+ <td><input type=text name="n2_3"></td>
+ <td><input type=text name="" value="v2_4"></td>
+ <td><input type=text value="v2_5"></td>
+ <td><input type=text></td>
+ <td><input type=text name="n2_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v2_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Checkbox unchecked</td>
+ <td><input type=checkbox name="n3_1" value="v3_1"></td>
+ <td><input type=checkbox name="n3_2" value=""></td>
+ <td><input type=checkbox name="n3_3"></td>
+ <td><input type=checkbox name="" value="v3_4"></td>
+ <td><input type=checkbox value="v3_5"></td>
+ <td><input type=checkbox></td>
+ <td><input type=checkbox name="n3_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v3_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Checkbox checked</td>
+ <td><input checked type=checkbox name="n4_1" value="v4_1"></td>
+ <td><input checked type=checkbox name="n4_2" value=""></td>
+ <td><input checked type=checkbox name="n4_3"></td>
+ <td><input checked type=checkbox name="" value="v4_4"></td>
+ <td><input checked type=checkbox value="v4_5"></td>
+ <td><input checked type=checkbox></td>
+ <td><input checked type=checkbox
+ name="n4_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v4_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Radio unchecked</td>
+ <td><input type=radio name="n5_1" value="v5_1"></td>
+ <td><input type=radio name="n5_2" value=""></td>
+ <td><input type=radio name="n5_3"></td>
+ <td><input type=radio name="" value="v5_4"></td>
+ <td><input type=radio value="v5_5"></td>
+ <td><input type=radio></td>
+ <td><input type=radio name="n5_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v5_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Radio checked</td>
+ <td><input checked type=radio name="n6_1" value="v6_1"></td>
+ <td><input checked type=radio name="n6_2" value=""></td>
+ <td><input checked type=radio name="n6_3"></td>
+ <td><input checked type=radio name="" value="v6_4"></td>
+ <td><input checked type=radio value="v6_5"></td>
+ <td><input checked type=radio></td>
+ <td><input checked type=radio
+ name="n6_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v6_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Hidden input</td>
+ <td><input type=hidden name="n7_1" value="v7_1"></td>
+ <td><input type=hidden name="n7_2" value=""></td>
+ <td><input type=hidden name="n7_3"></td>
+ <td><input type=hidden nane="" value="v7_4"></td>
+ <td><input type=hidden value="v7_5"></td>
+ <td><input type=hidden></td>
+ <td><input type=hidden name="n7_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v7_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Password input</td>
+ <td><input type=password name="n8_1" value="v8_1"></td>
+ <td><input type=password name="n8_2" value=""></td>
+ <td><input type=password name="n8_3"></td>
+ <td><input type=password name="" value="v8_4"></td>
+ <td><input type=password value="v8_5"></td>
+ <td><input type=password></td>
+ <td><input type=password name="n8_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v8_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Submit input</td>
+ <td><input type=submit name="n9_1" value="v9_1"></td>
+ <td><input type=submit name="n9_2" value=""></td>
+ <td><input type=submit name="n9_3"></td>
+ <td><input type=submit name="" value="v9_4"></td>
+ <td><input type=submit value="v9_5"></td>
+ <td><input type=submit></td>
+ <td><input type=submit name="n9_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v9_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Button input</td>
+ <td><input type=button name="n10_1" value="v10_1"></td>
+ <td><input type=button name="n10_2" value=""></td>
+ <td><input type=button name="n10_3"></td>
+ <td><input type=button name="" value="v10_4"></td>
+ <td><input type=button value="v10_5"></td>
+ <td><input type=button></td>
+ <td><input type=button name="n10_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v10_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Image input</td>
+ <td><input type=image src="file_formSubmission_img.jpg" name="n11_1" value="v11_1"></td>
+ <td><input type=image src="file_formSubmission_img.jpg" name="n11_2" value=""></td>
+ <td><input type=image src="file_formSubmission_img.jpg" name="n11_3"></td>
+ <td><input type=image src="file_formSubmission_img.jpg" name="" value="v11_4"></td>
+ <td><input type=image src="file_formSubmission_img.jpg" value="v11_5"></td>
+ <td><input type=image src="file_formSubmission_img.jpg"></td>
+ <td><input type=image src="file_formSubmission_img.jpg"
+ name="n11_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v11_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Reset input</td>
+ <td><input type=reset name="n12_1" value="v12_1"></td>
+ <td><input type=reset name="n12_2" value=""></td>
+ <td><input type=reset name="n12_3"></td>
+ <td><input type=reset name="" value="v12_4"></td>
+ <td><input type=reset value="v12_5"></td>
+ <td><input type=reset></td>
+ <td><input type=reset name="n12_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v12_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Unknown input</td>
+ <td><input type=foobar name="n13_1" value="v13_1"></td>
+ <td><input type=foobar name="n13_2" value=""></td>
+ <td><input type=foobar name="n13_3"></td>
+ <td><input type=foobar name="" value="v13_4"></td>
+ <td><input type=foobar value="v13_5"></td>
+ <td><input type=foobar></td>
+ <td><input type=foobar name="n13_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v13_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></td>
+ </tr>
+ <tr>
+ <td>Default button</td>
+ <td><button name="n14_1" value="v14_1"></button></td>
+ <td><button name="n14_2" value=""></button></td>
+ <td><button name="n14_3"></button></td>
+ <td><button name="" value="v14_4"></button></td>
+ <td><button value="v14_5"></button></td>
+ <td><button></button></td>
+ <td><button name="n14_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v14_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></button></td>
+ </tr>
+ <tr>
+ <td>Submit button</td>
+ <td><button type=submit name="n15_1" value="v15_1"></button></td>
+ <td><button type=submit name="n15_2" value=""></button></td>
+ <td><button type=submit name="n15_3"></button></td>
+ <td><button type=submit name="" value="v15_4"></button></td>
+ <td><button type=submit value="v15_5"></button></td>
+ <td><button type=submit></button></td>
+ <td><button type=submit name="n15_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v15_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></button></td>
+ </tr>
+ <tr>
+ <td>Button button</td>
+ <td><button type=button name="n16_1" value="v16_1"></button></td>
+ <td><button type=button name="n16_2" value=""></button></td>
+ <td><button type=button name="n16_3"></button></td>
+ <td><button type=button name="" value="v16_4"></button></td>
+ <td><button type=button value="v16_5"></button></td>
+ <td><button type=button></button></td>
+ <td><button type=button name="n16_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v16_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></button></td>
+ </tr>
+ <tr>
+ <td>Reset button</td>
+ <td><button type=reset name="n17_1" value="v17_1"></button></td>
+ <td><button type=reset name="n17_2" value=""></button></td>
+ <td><button type=reset name="n17_3"></button></td>
+ <td><button type=reset name="" value="v17_4"></button></td>
+ <td><button type=reset value="v17_5"></button></td>
+ <td><button type=reset></button></td>
+ <td><button type=reset name="n17_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v17_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></button></td>
+ </tr>
+ <tr>
+ <td>Unknown button</td>
+ <td><button type=foobar name="n18_1" value="v18_1"></button></td>
+ <td><button type=foobar name="n18_2" value=""></button></td>
+ <td><button type=foobar name="n18_3"></button></td>
+ <td><button type=foobar name="" value="v18_4"></button></td>
+ <td><button type=foobar value="v18_5"></button></td>
+ <td><button type=foobar ></button></td>
+ <td><button type=foobar name="n18_7_&#13;_&#10;_&#13;&#10;_ _&quot;"
+ value="v18_7_&#13;_&#10;_&#13;&#10;_ _&quot;"></button></td>
+ </tr>
+ <tr>
+ <td>&lt;input type='url'&gt;</td>
+ <td><input type=url name="n19_1" value="http://v19_1.org"></td>
+ <td><input type=url name="n19_2" value=""></td>
+ <td><input type=url name="n19_3"></td>
+ <td><input type=url name="" value="http://v19_4.org"></td>
+ <td><input type=url value="http://v19_5.org"></td>
+ <td><input type=url ></td>
+ <td><input type=url name="n19_7_&#13;_&#10;_&#13;&#10;__&quot;"
+ value="http://v19_7_&#13;_&#10;_&#13;&#10;__&quot;">
+ <!-- Put UTF-8 value in the "strange" column. -->
+ <input type=url name="n19_8" value="http://m&#xf3;zill&auml;.&#xf3;rg"></td>
+ </tr>
+ <tr>
+ <td>&lt;input type='email'&gt;</td>
+ <td><input type=email name="n20_1" value="v20_1@bar"></td>
+ <td><input type=email name="n20_2" value=""></td>
+ <td><input type=email name="n20_3"></td>
+ <td><input type=email name="" value="v20_4@bar"></td>
+ <td><input type=email value="v20_5@bar"></td>
+ <td><input type=email ></td>
+ <td><input type=email name="n20_7_&#13;_&#10;_&#13;&#10;__&quot;"
+ value="v20_7_&#13;_&#10;_&#13;&#10;__&quot;@bar">
+ <!-- Put UTF-8 value is the "strange" column. -->
+ <input type=email name="n20_8" value="foo@mózillä.órg"></td>
+ </tr>
+ </table>
+
+ <p>
+ File input:
+ <input type=file name="file_1" class="setfile">
+ <input type=file name="file_2">
+ <input type=file name="" class="setfile">
+ <input type=file name="">
+ <input type=file class="setfile">
+ <input type=file>
+ </p>
+ <p>
+ Multifile input:
+ <input multiple type=file name="file_3" class="setfile">
+ <input multiple type=file name="file_4" class="setfile multi">
+ <input multiple type=file name="file_5">
+ <input multiple type=file name="" class="setfile">
+ <input multiple type=file name="" class="setfile multi">
+ <input multiple type=file name="">
+ <input multiple type=file class="setfile">
+ <input multiple type=file class="setfile multi">
+ <input multiple type=file>
+ </p>
+
+ <p>
+ Textarea:
+ <textarea name="t1">t_1_v</textarea>
+ <textarea name="t2"></textarea>
+ <textarea name="">t_3_v</textarea>
+ <textarea>t_4_v</textarea>
+ <textarea></textarea>
+ <textarea name="t6">
+t_6_v</textarea>
+ <textarea name="t7">t_7_v
+</textarea>
+ <textarea name="t8">
+
+ t_8_v
+</textarea>
+ <textarea name="t9_&#13;_&#10;_&#13;&#10;_ _&quot;">t_9_&#13;_&#10;_&#13;&#10;_ _&quot;_v</textarea>
+ <textarea name="t10" value="t_10_bogus">t_10_v</textarea>
+ </p>
+
+ <p>
+ Select one:
+
+ <select name="sel_1"></select>
+ <select name="sel_1b"><option></option></select>
+ <select name="sel_1c"><option selected></option></select>
+
+ <select name="sel_2"><option value="sel_2_v"></option></select>
+ <select name="sel_3"><option selected value="sel_3_v"></option></select>
+
+ <select name="sel_4"><option value="sel_4_v1"></option><option value="sel_4_v2"></option></select>
+ <select name="sel_5"><option selected value="sel_5_v1"></option><option value="sel_5_v2"></option></select>
+ <select name="sel_6"><option value="sel_6_v1"></option><option selected value="sel_6_v2"></option></select>
+
+ <select name="sel_7"><option>sel_7_v1</option><option>sel_7_v2</option></select>
+ <select name="sel_8"><option selected>sel_8_v1</option><option>sel_8_v2</option></select>
+ <select name="sel_9"><option>sel_9_v1</option><option selected>sel_9_v2</option></select>
+
+ <select name="sel_10"><option value="sel_10_v1">sel_10_v1_text</option><option value="sel_10_v2">sel_10_v2_text</option></select>
+ <select name="sel_11"><option selected value="sel_11_v1">sel_11_v1_text</option><option value="sel_11_v2">sel_11_v2_text</option></select>
+ <select name="sel_12"><option value="sel_12_v1">sel_12_v1_text</option><option selected value="sel_12_v2">sel_12_v2_text</option></select>
+
+ <select name="sel_13"><option disabled>sel_13_v1</option><option>sel_13_v2</option></select>
+ <select name="sel_14"><option disabled selected>sel_14_v1</option><option>sel_14_v2</option></select>
+ <select name="sel_15"><option disabled>sel_15_v1</option><option selected>sel_15_v2</option></select>
+
+ <select name="sel_16"><option>sel_16_v1</option><option disabled>sel_16_v2</option></select>
+ <select name="sel_17"><option selected>sel_17_v1</option><option disabled>sel_17_v2</option></select>
+ <select name="sel_18"><option>sel_18_v1</option><option disabled selected>sel_18_v2</option></select>
+
+ <select name=""><option selected value="sel_13_v1"></option><option value="sel_13_v2"></option></select>
+ <select name=""><option value="sel_14_v1"></option><option selected value="sel_14_v2"></option></select>
+ <select name=""><option selected>sel_15_v1</option><option>sel_15_v2</option></select>
+ <select name=""><option>sel_16_v1</option><option selected>sel_16_v2</option></select>
+
+ <select><option selected value="sel_17_v1"></option><option value="sel_17_v2"></option></select>
+ <select><option value="sel_18_v1"></option><option selected value="sel_18_v2"></option></select>
+ <select><option selected>sel_19_v1</option><option>sel_19_v2</option></select>
+ <select><option>sel_20_v1</option><option selected>sel_20_v2</option></select>
+ </p>
+
+ <p>
+ Select multiple:
+
+ <select multiple name="msel_1"></select>
+ <select multiple name="msel_1b"><option></option></select>
+ <select multiple name="msel_1c"><option selected></option></select>
+
+ <select multiple name="msel_2"><option value="msel_2_v"></option></select>
+ <select multiple name="msel_3"><option selected value="msel_3_v"></option></select>
+
+ <select multiple name="msel_4"><option value="msel_4_v1"></option><option value="msel_4_v2"></option></select>
+ <select multiple name="msel_5"><option selected value="msel_5_v1"></option><option value="msel_5_v2"></option></select>
+ <select multiple name="msel_6"><option value="msel_6_v1"></option><option selected value="msel_6_v2"></option></select>
+ <select multiple name="msel_7"><option selected value="msel_7_v1"></option><option selected value="msel_7_v2"></option></select>
+
+ <select multiple name="msel_8"><option>msel_8_v1</option><option>msel_8_v2</option></select>
+ <select multiple name="msel_9"><option selected>msel_9_v1</option><option>msel_9_v2</option></select>
+ <select multiple name="msel_10"><option>msel_10_v1</option><option selected>msel_10_v2</option></select>
+ <select multiple name="msel_11"><option selected>msel_11_v1</option><option selected>msel_11_v2</option></select>
+
+ <select multiple name="msel_12"><option value="msel_12_v1">msel_12_v1_text</option><option value="msel_12_v2">msel_12_v2_text</option></select>
+ <select multiple name="msel_13"><option selected value="msel_13_v1">msel_13_v1_text</option><option value="msel_13_v2">msel_13_v2_text</option></select>
+ <select multiple name="msel_14"><option value="msel_14_v1">msel_14_v1_text</option><option selected value="msel_14_v2">msel_14_v2_text</option></select>
+ <select multiple name="msel_15"><option selected value="msel_15_v1">msel_15_v1_text</option><option selected value="msel_15_v2">msel_15_v2_text</option></select>
+
+ <select multiple name="msel_16"><option>msel_16_v1</option><option>msel_16_v2</option><option>msel_16_v3</option></select>
+ <select multiple name="msel_17"><option selected>msel_17_v1</option><option>msel_17_v2</option><option>msel_17_v3</option></select>
+ <select multiple name="msel_18"><option>msel_18_v1</option><option selected>msel_18_v2</option><option>msel_18_v3</option></select>
+ <select multiple name="msel_19"><option selected>msel_19_v1</option><option selected>msel_19_v2</option><option>msel_19_v3</option></select>
+ <select multiple name="msel_20"><option>msel_20_v1</option><option>msel_20_v2</option><option selected>msel_20_v3</option></select>
+ <select multiple name="msel_21"><option selected>msel_21_v1</option><option>msel_21_v2</option><option selected>msel_21_v3</option></select>
+ <select multiple name="msel_22"><option>msel_22_v1</option><option selected>msel_22_v2</option><option selected>msel_22_v3</option></select>
+ <select multiple name="msel_23"><option selected>msel_23_v1</option><option selected>msel_23_v2</option><option selected>msel_23_v3</option></select>
+
+ <select multiple name="msel_24"><option disabled>msel_24_v1</option><option>msel_24_v2</option></select>
+ <select multiple name="msel_25"><option disabled selected>msel_25_v1</option><option>msel_25_v2</option></select>
+ <select multiple name="msel_26"><option disabled>msel_26_v1</option><option selected>msel_26_v2</option></select>
+ <select multiple name="msel_27"><option disabled selected>msel_27_v1</option><option selected>msel_27_v2</option></select>
+
+ <select multiple name="msel_28"><option>msel_28_v1</option><option disabled>msel_28_v2</option></select>
+ <select multiple name="msel_29"><option selected>msel_29_v1</option><option disabled>msel_29_v2</option></select>
+ <select multiple name="msel_30"><option>msel_30_v1</option><option disabled selected>msel_30_v2</option></select>
+ <select multiple name="msel_31"><option selected>msel_31_v1</option><option disabled selected>msel_31_v2</option></select>
+
+ <select multiple name="msel_32"><option disabled selected>msel_32_v1</option><option disabled selected>msel_32_v2</option></select>
+
+ <select multiple name=""><option>msel_33_v1</option><option>msel_33_v2</option></select>
+ <select multiple name=""><option selected>msel_34_v1</option><option>msel_34_v2</option></select>
+ <select multiple name=""><option>msel_35_v1</option><option selected>msel_35_v2</option></select>
+ <select multiple name=""><option selected>msel_36_v1</option><option selected>msel_36_v2</option></select>
+
+ <select multiple><option>msel_37_v1</option><option>msel_37_v2</option></select>
+ <select multiple><option selected>msel_38_v1</option><option>msel_38_v2</option></select>
+ <select multiple><option>msel_39_v1</option><option selected>msel_39_v2</option></select>
+ <select multiple><option selected>msel_40_v1</option><option selected>msel_40_v2</option></select>
+ </p>
+</form>
+<pre id="test">
+<script class="testbody" type="text/javascript;version=1.8">
+
+SimpleTest.waitForExplicitFinish();
+
+const placeholder_myFile1 = {};
+const placeholder_myFile2 = {};
+const placeholder_emptyFile = {};
+
+var myFile1, myFile2, emptyFile;
+let openerURL = SimpleTest.getTestFileURL("formSubmission_chrome.js");
+let opener = SpecialPowers.loadChromeScript(openerURL);
+
+{
+ let xhr = new XMLHttpRequest;
+ xhr.open("GET", "/dynamic/getMyDirectory.sjs", false);
+ xhr.send();
+ let basePath = xhr.responseText;
+
+ opener.addMessageListener("files.opened", onFilesOpened);
+ opener.sendAsyncMessage("files.open", [
+ basePath + "file_formSubmission_text.txt",
+ basePath + "file_formSubmission_img.jpg",
+ ]);
+}
+
+function onFilesOpened(files) {
+ let [textFile, imageFile] = files;
+ opener.destroy();
+
+ let singleFile = textFile;
+ let multiFile = [textFile, imageFile];
+
+ var addList = document.getElementsByClassName("setfile");
+ let i = 0;
+ var input;
+ while (input = addList[i++]) {
+ if (input.classList.contains("multi")) {
+ SpecialPowers.wrap(input).mozSetFileArray(multiFile);
+ } else {
+ SpecialPowers.wrap(input).mozSetFileArray([singleFile]);
+ }
+ }
+
+ input = document.createElement("input");
+ input.type = "file";
+ input.multiple = true;
+ SpecialPowers.wrap(input).mozSetFileArray(multiFile);
+ myFile1 = input.files[0];
+ myFile2 = input.files[1];
+ is(myFile1.size, 20, "File1 size");
+ is(myFile2.size, 2711, "File2 size");
+ emptyFile = { name: "", type: "application/octet-stream" };
+
+ // Now, actually run the tests; see below.
+ onFilesSet();
+};
+
+var expectedSub = [
+ // Default input
+ { name: "n1_1", value: "v1_1" },
+ { name: "n1_2", value: "" },
+ { name: "n1_3", value: "" },
+ { name: "n1_7_\r\n_\r\n_\r\n_ _\"", value: "v1_7____ _\"" },
+ // Text input
+ { name: "n2_1", value: "v2_1" },
+ { name: "n2_2", value: "" },
+ { name: "n2_3", value: "" },
+ { name: "n2_7_\r\n_\r\n_\r\n_ _\"", value: "v2_7____ _\"" },
+ // Checkbox unchecked
+ // Checkbox checked
+ { name: "n4_1", value: "v4_1" },
+ { name: "n4_2", value: "" },
+ { name: "n4_3", value: "on" },
+ { name: "n4_7_\r\n_\r\n_\r\n_ _\"", value: "v4_7_\r\n_\r\n_\r\n_ _\"" },
+ // Radio unchecked
+ // Radio checked
+ { name: "n6_1", value: "v6_1" },
+ { name: "n6_2", value: "" },
+ { name: "n6_3", value: "on" },
+ { name: "n6_7_\r\n_\r\n_\r\n_ _\"", value: "v6_7_\r\n_\r\n_\r\n_ _\"" },
+ // Hidden input
+ { name: "n7_1", value: "v7_1" },
+ { name: "n7_2", value: "" },
+ { name: "n7_3", value: "" },
+ { name: "n7_7_\r\n_\r\n_\r\n_ _\"", value: "v7_7_\r\n_\r\n_\r\n_ _\"" },
+ // Password input
+ { name: "n8_1", value: "v8_1" },
+ { name: "n8_2", value: "" },
+ { name: "n8_3", value: "" },
+ { name: "n8_7_\r\n_\r\n_\r\n_ _\"", value: "v8_7____ _\"" },
+ // Submit input
+ // Button input
+ // Image input
+ // Reset input
+ // Unknown input
+ { name: "n13_1", value: "v13_1" },
+ { name: "n13_2", value: "" },
+ { name: "n13_3", value: "" },
+ { name: "n13_7_\r\n_\r\n_\r\n_ _\"", value: "v13_7____ _\"" },
+ // <input type='url'>
+ { name: "n19_1", value: "http://v19_1.org" },
+ { name: "n19_2", value: "" },
+ { name: "n19_3", value: "" },
+ { name: "n19_7_\r\n_\r\n_\r\n__\"", value: "http://v19_7_____\"" },
+ { name: "n19_8", value: "http://m\xf3zill\xe4.\xf3rg" },
+ // <input type='email'>
+ { name: "n20_1", value: "v20_1@bar" },
+ { name: "n20_2", value: "" },
+ { name: "n20_3", value: "" },
+ { name: "n20_7_\r\n_\r\n_\r\n__\"", value: "v20_7_____\"@bar" },
+ { name: "n20_8", value: "foo@mózillä.órg" },
+ // Default button
+ // Submit button
+ // Button button
+ // Reset button
+ // Unknown button
+ // File
+ { name: "file_1", value: placeholder_myFile1 },
+ { name: "file_2", value: placeholder_emptyFile },
+ // Multiple file
+ { name: "file_3", value: placeholder_myFile1 },
+ { name: "file_4", value: placeholder_myFile1 },
+ { name: "file_4", value: placeholder_myFile2 },
+ { name: "file_5", value: placeholder_emptyFile },
+ // Textarea
+ { name: "t1", value: "t_1_v" },
+ { name: "t2", value: "" },
+ { name: "t6", value: "t_6_v" },
+ { name: "t7", value: "t_7_v\r\n" },
+ { name: "t8", value: "\r\n t_8_v \r\n" },
+ { name: "t9_\r\n_\r\n_\r\n_ _\"", value: "t_9_\r\n_\r\n_\r\n_ _\"_v" },
+ { name: "t10", value: "t_10_v" },
+
+ // Select one
+ { name: "sel_1b", value: "" },
+ { name: "sel_1c", value: "" },
+ { name: "sel_2", value: "sel_2_v" },
+ { name: "sel_3", value: "sel_3_v" },
+ { name: "sel_4", value: "sel_4_v1" },
+ { name: "sel_5", value: "sel_5_v1" },
+ { name: "sel_6", value: "sel_6_v2" },
+ { name: "sel_7", value: "sel_7_v1" },
+ { name: "sel_8", value: "sel_8_v1" },
+ { name: "sel_9", value: "sel_9_v2" },
+ { name: "sel_10", value: "sel_10_v1" },
+ { name: "sel_11", value: "sel_11_v1" },
+ { name: "sel_12", value: "sel_12_v2" },
+ { name: "sel_13", value: "sel_13_v2" },
+ { name: "sel_15", value: "sel_15_v2" },
+ { name: "sel_16", value: "sel_16_v1" },
+ { name: "sel_17", value: "sel_17_v1" },
+ // Select three
+ { name: "msel_1c", value: "" },
+ { name: "msel_3", value: "msel_3_v" },
+ { name: "msel_5", value: "msel_5_v1" },
+ { name: "msel_6", value: "msel_6_v2" },
+ { name: "msel_7", value: "msel_7_v1" },
+ { name: "msel_7", value: "msel_7_v2" },
+ { name: "msel_9", value: "msel_9_v1" },
+ { name: "msel_10", value: "msel_10_v2" },
+ { name: "msel_11", value: "msel_11_v1" },
+ { name: "msel_11", value: "msel_11_v2" },
+ { name: "msel_13", value: "msel_13_v1" },
+ { name: "msel_14", value: "msel_14_v2" },
+ { name: "msel_15", value: "msel_15_v1" },
+ { name: "msel_15", value: "msel_15_v2" },
+ { name: "msel_17", value: "msel_17_v1" },
+ { name: "msel_18", value: "msel_18_v2" },
+ { name: "msel_19", value: "msel_19_v1" },
+ { name: "msel_19", value: "msel_19_v2" },
+ { name: "msel_20", value: "msel_20_v3" },
+ { name: "msel_21", value: "msel_21_v1" },
+ { name: "msel_21", value: "msel_21_v3" },
+ { name: "msel_22", value: "msel_22_v2" },
+ { name: "msel_22", value: "msel_22_v3" },
+ { name: "msel_23", value: "msel_23_v1" },
+ { name: "msel_23", value: "msel_23_v2" },
+ { name: "msel_23", value: "msel_23_v3" },
+ { name: "msel_26", value: "msel_26_v2" },
+ { name: "msel_27", value: "msel_27_v2" },
+ { name: "msel_29", value: "msel_29_v1" },
+ { name: "msel_31", value: "msel_31_v1" },
+];
+
+var expectedAugment = [
+ { name: "aName", value: "aValue" },
+ //{ name: "aNameBool", value: "false" },
+ { name: "aNameNum", value: "9.2" },
+ { name: "aNameFile1", value: placeholder_myFile1 },
+ { name: "aNameFile2", value: placeholder_myFile2 },
+ //{ name: "aNameObj", value: "[object XMLHttpRequest]" },
+ //{ name: "aNameNull", value: "null" },
+ //{ name: "aNameUndef", value: "undefined" },
+];
+
+function checkMPSubmission(sub, expected, test) {
+ function getPropCount(o) {
+ var x, l = 0;
+ for (x in o) ++l;
+ return l;
+ }
+ function mpquote(s) {
+ return s.replace(/\r\n/g, " ")
+ .replace(/\r/g, " ")
+ .replace(/\n/g, " ")
+ .replace(/\"/g, "\\\"");
+ }
+
+ is(sub.length, expected.length,
+ "Correct number of multipart items in " + test);
+
+ if (sub.length != expected.length) {
+ alert(JSON.stringify(sub));
+ }
+
+ var i;
+ for (i = 0; i < expected.length; ++i) {
+ if (!("fileName" in expected[i])) {
+ is(sub[i].headers["Content-Disposition"],
+ "form-data; name=\"" + mpquote(expected[i].name) + "\"",
+ "Correct name in " + test);
+ is (getPropCount(sub[i].headers), 1,
+ "Wrong number of headers in " + test);
+ is(sub[i].body,
+ expected[i].value.replace(/\r\n|\r|\n/, "\r\n"),
+ "Correct value in " + test);
+ }
+ else {
+ is(sub[i].headers["Content-Disposition"],
+ "form-data; name=\"" + mpquote(expected[i].name) + "\"; filename=\"" +
+ mpquote(expected[i].fileName) + "\"",
+ "Correct name in " + test);
+ is(sub[i].headers["Content-Type"],
+ expected[i].contentType,
+ "Correct content type in " + test);
+ is (getPropCount(sub[i].headers), 2,
+ "Wrong number of headers in " + test);
+ is(sub[i].body,
+ expected[i].value,
+ "Correct value in " + test);
+ }
+ }
+}
+
+function utf8encode(s) {
+ return unescape(encodeURIComponent(s));
+}
+
+function checkURLSubmission(sub, expected) {
+ function urlEscape(s) {
+ return escape(utf8encode(s)).replace(/%20/g, "+")
+ .replace(/\//g, "%2F")
+ .replace(/@/g, "%40");
+ }
+
+ subItems = sub.split("&");
+ is(subItems.length, expected.length,
+ "Correct number of url items");
+ var i;
+ for (i = 0; i < expected.length; ++i) {
+ let expect = urlEscape(expected[i].name) + "=" +
+ urlEscape(("fileName" in expected[i]) ? expected[i].fileName : expected[i].value);
+ is (subItems[i], expect, "expected URL part");
+ }
+}
+
+function checkPlainSubmission(sub, expected) {
+
+ is(sub,
+ expected.map(function(v) {
+ return v.name + "=" +
+ (("fileName" in v) ? v.fileName : v.value) +
+ "\r\n";
+ }).join(""),
+ "Correct submission");
+}
+
+function setDisabled(list, state) {
+ Array.prototype.forEach.call(list, function(e) {
+ e.disabled = state;
+ });
+}
+
+var gen;
+function onFilesSet() {
+ gen = runTest();
+ addLoadEvent(function() {
+ gen.next();
+ });
+}
+
+function runTest() {
+ // Set up the expectedSub array
+ fileReader1 = new FileReader;
+ fileReader1.readAsBinaryString(myFile1);
+ fileReader2 = new FileReader;
+ fileReader2.readAsBinaryString(myFile2);
+ fileReader1.onload = fileReader2.onload = function() { gen.next(); };
+ yield undefined; // Wait for both FileReaders. We don't care which order they finish.
+ yield undefined;
+ function fileFixup(o) {
+ if (o.value === placeholder_myFile1) {
+ o.value = fileReader1.result;
+ o.fileName = myFile1.name;
+ o.contentType = myFile1.type;
+ }
+ else if (o.value === placeholder_myFile2) {
+ o.value = fileReader2.result;
+ o.fileName = myFile2.name;
+ o.contentType = myFile2.type;
+ }
+ else if (o.value === placeholder_emptyFile) {
+ o.value = "";
+ o.fileName = emptyFile.name;
+ o.contentType = emptyFile.type;
+ }
+ };
+ expectedSub.forEach(fileFixup);
+ expectedAugment.forEach(fileFixup);
+
+ var form = $("form");
+
+ // multipart/form-data
+
+ var iframe = $("target_iframe");
+ iframe.onload = function() { gen.next(); };
+
+ // Make normal submission
+ form.submit();
+ yield undefined; // Wait for iframe to load as a result of the submission
+ var submission = JSON.parse(iframe.contentDocument.documentElement.textContent);
+ checkMPSubmission(submission, expectedSub, "normal submission");
+
+ // Disabled controls
+ setDisabled(document.querySelectorAll("input, select, textarea"), true);
+ form.submit();
+ yield undefined;
+ submission = JSON.parse(iframe.contentDocument.documentElement.textContent);
+ checkMPSubmission(submission, [], "disabled controls");
+
+ // Reenabled controls
+ setDisabled(document.querySelectorAll("input, select, textarea"), false);
+ form.submit();
+ yield undefined;
+ submission = JSON.parse(iframe.contentDocument.documentElement.textContent);
+ checkMPSubmission(submission, expectedSub, "reenabled controls");
+
+ // text/plain
+ form.action = "form_submit_server.sjs?plain";
+ form.enctype = "text/plain";
+ form.submit();
+ yield undefined;
+ submission = JSON.parse(iframe.contentDocument.documentElement.textContent);
+ checkPlainSubmission(submission, expectedSub);
+
+ // application/x-www-form-urlencoded
+ form.action = "form_submit_server.sjs?url";
+ form.enctype = "application/x-www-form-urlencoded";
+ form.submit();
+ yield undefined;
+ submission = JSON.parse(iframe.contentDocument.documentElement.textContent);
+ checkURLSubmission(submission, expectedSub);
+
+ // application/x-www-form-urlencoded
+ form.action = "form_submit_server.sjs?xxyy";
+ form.method = "GET";
+ form.enctype = "";
+ form.submit();
+ yield undefined;
+ submission = JSON.parse(iframe.contentDocument.documentElement.textContent);
+ checkURLSubmission(submission, expectedSub);
+
+ // application/x-www-form-urlencoded
+ form.action = "form_submit_server.sjs";
+ form.method = "";
+ form.enctype = "";
+ form.submit();
+ yield undefined;
+ submission = JSON.parse(iframe.contentDocument.documentElement.textContent);
+ checkURLSubmission(submission, expectedSub);
+
+ // Send form using XHR and FormData
+ xhr = new XMLHttpRequest();
+ xhr.onload = function() { gen.next(); };
+ xhr.open("POST", "form_submit_server.sjs");
+ xhr.send(new FormData(form));
+ yield undefined; // Wait for XHR load
+ checkMPSubmission(JSON.parse(xhr.responseText), expectedSub, "send form using XHR and FormData");
+
+ // Send disabled form using XHR and FormData
+ setDisabled(document.querySelectorAll("input, select, textarea"), true);
+ xhr.open("POST", "form_submit_server.sjs");
+ xhr.send(new FormData(form));
+ yield undefined;
+ checkMPSubmission(JSON.parse(xhr.responseText), [], "send disabled form using XHR and FormData");
+ setDisabled(document.querySelectorAll("input, select, textarea"), false);
+
+ // Send FormData
+ function addToFormData(fd) {
+ fd.append("aName", "aValue");
+ fd.append("aNameNum", 9.2);
+ fd.append("aNameFile1", myFile1);
+ fd.append("aNameFile2", myFile2);
+ }
+ var fd = new FormData();
+ addToFormData(fd);
+ xhr.open("POST", "form_submit_server.sjs");
+ xhr.send(fd);
+ yield undefined;
+ checkMPSubmission(JSON.parse(xhr.responseText), expectedAugment, "send FormData");
+
+ // Augment <form> using FormData
+ fd = new FormData(form);
+ addToFormData(fd);
+ xhr.open("POST", "form_submit_server.sjs");
+ xhr.send(fd);
+ yield undefined;
+ checkMPSubmission(JSON.parse(xhr.responseText),
+ expectedSub.concat(expectedAugment), "send augmented FormData");
+
+ SimpleTest.finish();
+ yield undefined;
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_formSubmission2.html b/dom/html/test/test_formSubmission2.html
new file mode 100644
index 000000000..2d0eb42f9
--- /dev/null
+++ b/dom/html/test/test_formSubmission2.html
@@ -0,0 +1,221 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=523771
+-->
+<head>
+ <title>Test for Bug 523771</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=523771">Mozilla Bug 523771</a>
+<p id="display"></p>
+<iframe name="target_iframe" id="target_iframe"></iframe>
+<form action="form_submit_server.sjs" target="target_iframe" id="form"
+ method="POST" enctype="multipart/form-data">
+ <table>
+ <tr>
+ <td>Control type</td>
+ <td>Name and value</td>
+ <td>Name, empty value</td>
+ <td>Name, no value</td>
+ <td>Empty name, with value</td>
+ <td>No name, with value</td>
+ <td>No name or value</td>
+ </tr>
+ <tr>
+ <td>Submit input</td>
+ <td><input type=submit name="n1_1" value="v1_1"></td>
+ <td><input type=submit name="n1_2" value=""></td>
+ <td><input type=submit name="n1_3"></td>
+ <td><input type=submit name="" value="v1_4"></td>
+ <td><input type=submit value="v1_5"></td>
+ <td><input type=submit></td>
+ </tr>
+ <tr>
+ <td>Image input</td>
+ <td><input type=image src="file_formSubmission_img.jpg" name="n2_1" value="v2_1"></td>
+ <td><input type=image src="file_formSubmission_img.jpg" name="n2_2" value=""></td>
+ <td><input type=image src="file_formSubmission_img.jpg" name="n2_3"></td>
+ <td><input type=image src="file_formSubmission_img.jpg" name="" value="v2_4"></td>
+ <td><input type=image src="file_formSubmission_img.jpg" value="v2_5"></td>
+ <td><input type=image src="file_formSubmission_img.jpg"></td>
+ </tr>
+ <tr>
+ <td>Submit button</td>
+ <td><button type=submit name="n3_1" value="v3_1"></button></td>
+ <td><button type=submit name="n3_2" value=""></button></td>
+ <td><button type=submit name="n3_3"></button></td>
+ <td><button type=submit name="" value="v3_4"></button></td>
+ <td><button type=submit value="v3_5"></button></td>
+ <td><button type=submit ></button></td>
+ </tr>
+ <tr>
+ <td>Submit button with text</td>
+ <td><button type=submit name="n4_1" value="v4_1">text here</button></td>
+ <td><button type=submit name="n4_2" value="">text here</button></td>
+ <td><button type=submit name="n4_3">text here</button></td>
+ <td><button type=submit name="" value="v4_4">text here</button></td>
+ <td><button type=submit value="v4_5">text here</button></td>
+ <td><button type=submit>text here</button></td>
+ </tr>
+ </table>
+</form>
+<pre id="test">
+<script class="testbody" type="text/javascript;version=1.8">
+
+var gen = runTest();
+
+SimpleTest.waitForExplicitFinish();
+addLoadEvent(function() {
+ gen.next();
+});
+
+var expectedSub = [
+ // Submit input
+ [{ name: "n1_1", value: "v1_1" }],
+ [{ name: "n1_2", value: "" }],
+ [{ name: "n1_3", value: "Submit Query" }],
+ [],
+ [],
+ [],
+ // Image input
+ [{ name: "n2_1.x", value: "10" },
+ { name: "n2_1.y", value: "7" }],
+ [{ name: "n2_2.x", value: "10" },
+ { name: "n2_2.y", value: "7" }],
+ [{ name: "n2_3.x", value: "10" },
+ { name: "n2_3.y", value: "7" }],
+ [{ name: "x", value: "10" },
+ { name: "y", value: "7" }],
+ [{ name: "x", value: "10" },
+ { name: "y", value: "7" }],
+ [{ name: "x", value: "10" },
+ { name: "y", value: "7" }],
+ // Submit button
+ [{ name: "n3_1", value: "v3_1" }],
+ [{ name: "n3_2", value: "" }],
+ [{ name: "n3_3", value: "" }],
+ [],
+ [],
+ [],
+ // Submit button with text
+ [{ name: "n4_1", value: "v4_1" }],
+ [{ name: "n4_2", value: "" }],
+ [{ name: "n4_3", value: "" }],
+ [],
+ [],
+ [],
+];
+
+function checkSubmission(sub, expected) {
+ function getPropCount(o) {
+ var x, l = 0;
+ for (x in o) ++l;
+ return l;
+ }
+
+ is(sub.length, expected.length,
+ "Correct number of items");
+ var i;
+ for (i = 0; i < expected.length; ++i) {
+ if (!("fileName" in expected[i])) {
+ is(sub[i].headers["Content-Disposition"],
+ "form-data; name=\"" + expected[i].name + "\"",
+ "Correct name");
+ is (getPropCount(sub[i].headers), 1,
+ "Wrong number of headers");
+ }
+ else {
+ is(sub[i].headers["Content-Disposition"],
+ "form-data; name=\"" + expected[i].name + "\"; filename=\"" +
+ expected[i].fileName + "\"",
+ "Correct name");
+ is(sub[i].headers["Content-Type"],
+ expected[i].contentType,
+ "Correct content type");
+ is (getPropCount(sub[i].headers), 2,
+ "Wrong number of headers");
+ }
+ is(sub[i].body,
+ expected[i].value,
+ "Correct value");
+ }
+}
+
+function clickImage(aTarget, aX, aY)
+{
+ aTarget.style.position = "absolute";
+ aTarget.style.top = "0";
+ aTarget.style.left = "0";
+ aTarget.offsetTop;
+
+ var wu = SpecialPowers.getDOMWindowUtils(aTarget.ownerDocument.defaultView);
+
+ wu.sendMouseEvent('mousedown', aX, aY, 0, 1, 0);
+ wu.sendMouseEvent('mouseup', aX, aY, 0, 0, 0);
+
+ aTarget.style.position = "";
+ aTarget.style.top = "";
+ aTarget.style.left = "";
+}
+
+function runTest() {
+ // Make normal submission
+ var form = $("form");
+ var iframe = $("target_iframe");
+ iframe.onload = function() { gen.next(); };
+
+ var elements = form.querySelectorAll("input, button");
+
+ is(elements.length, expectedSub.length,
+ "tests vs. expected out of sync");
+
+ var i;
+ for (i = 0; i < elements.length && i < expectedSub.length; ++i) {
+ elem = elements[i];
+ if (elem.localName != "input" || elem.type != "image") {
+ elem.click();
+ }
+ else {
+ clickImage(elem, 10, 7);
+ }
+ yield undefined;
+
+ var submission = JSON.parse(iframe.contentDocument.documentElement.textContent);
+ checkSubmission(submission, expectedSub[i]);
+ }
+
+ // Disabled controls
+ var i;
+ for (i = 0; i < elements.length && i < expectedSub.length; ++i) {
+ elem = elements[i];
+ form.onsubmit = function() {
+ elem.disabled = true;
+ }
+ if (elem.localName != "input" || elem.type != "image") {
+ elem.click();
+ }
+ else {
+ clickImage(elem, 10, 7);
+ }
+ yield undefined;
+
+ is(elem.disabled, true, "didn't disable");
+ elem.disabled = false;
+ form.onsubmit = undefined;
+
+ var submission = JSON.parse(iframe.contentDocument.documentElement.textContent);
+ checkSubmission(submission, []);
+ }
+
+ SimpleTest.finish();
+ yield undefined;
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_formelements.html b/dom/html/test/test_formelements.html
new file mode 100644
index 000000000..c4714aa6b
--- /dev/null
+++ b/dom/html/test/test_formelements.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=772869
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 772869</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772869">Mozilla Bug 772869</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <form id="f">
+ <input name="x">
+ <input type="image" name="a">
+ <input type="file" name="y">
+ <input type="submit" name="z">
+ <input id="w">
+ <input name="w">
+ </form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 772869 **/
+var x = $("f").elements;
+x.something = "another";
+names = [];
+for (var name in x) {
+ names.push(name);
+}
+is(names.length, 9, "Should have 9 enumerated names");
+is(names[0], "0", "Enum entry 1");
+is(names[1], "1", "Enum entry 2");
+is(names[2], "2", "Enum entry 3");
+is(names[3], "3", "Enum entry 4");
+is(names[4], "4", "Enum entry 5");
+is(names[5], "something", "Enum entry 6");
+is(names[6], "namedItem", "Enum entry 7");
+is(names[7], "item", "Enum entry 8");
+is(names[8], "length", "Enum entry 9");
+
+names = Object.getOwnPropertyNames(x);
+is(names.length, 10, "Should have 10 items");
+// Now sort entries 5 through 8, for comparison purposes. We don't sort the
+// whole array, because we want to make sure the ordering between the parts
+// is correct
+temp = names.slice(5, 9);
+temp.sort();
+names.splice.bind(names, 5, 4).apply(null, temp);
+is(names.length, 10, "Should still have 10 items");
+is(names[0], "0", "Entry 1")
+is(names[1], "1", "Entry 2")
+is(names[2], "2", "Entry 3")
+is(names[3], "3", "Entry 4")
+is(names[4], "4", "Entry 5")
+is(names[5], "w", "Entry 6")
+is(names[6], "x", "Entry 7")
+is(names[7], "y", "Entry 8")
+is(names[8], "z", "Entry 9")
+is(names[9], "something", "Entry 10")
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_fragment_form_pointer.html b/dom/html/test/test_fragment_form_pointer.html
new file mode 100644
index 000000000..c9ed9dbc5
--- /dev/null
+++ b/dom/html/test/test_fragment_form_pointer.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=946585
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 946585</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=946585">Mozilla Bug 946585</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<form><div id="formdiv"></div></form>
+</div>
+<pre id="test">
+</pre>
+<script type="application/javascript">
+/** Test for Bug 946585 **/
+var formDiv = document.getElementById("formdiv");
+formDiv.innerHTML = '<form>';
+is(formDiv.firstChild, null, "InnerHTML should not produce form element because the div has a form pointer.");
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_fullscreen-api-race.html b/dom/html/test/test_fullscreen-api-race.html
new file mode 100644
index 000000000..03c6c6da3
--- /dev/null
+++ b/dom/html/test/test_fullscreen-api-race.html
@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test for race conditions of Fullscreen API</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<script>
+
+function Deferred() {
+ this.promise = new Promise(resolve => {
+ this.resolve = resolve;
+ });
+}
+
+function checkIsChromeFullscreen(win, inFullscreen) {
+ return SimpleTest.promiseWaitForCondition(
+ () => win.fullScreen == inFullscreen,
+ "The window should exit fullscreen state");
+}
+
+SimpleTest.waitForExplicitFinish();
+// XXX This actually exposes a true race condition, but it could rarely
+// happen in real world, because it only happens when requestFullscreen
+// is called immediately after exiting fullscreen in certain condition,
+// and in real life, requestFullscreen can only be called inside a user
+// event handler. But we want to fix this race condition at some point,
+// via queuing all exiting request as well as entering request together
+// which we may eventually need to do for bug 1188256.
+SimpleTest.requestFlakyTimeout(
+ "Need to wait for potential fullscreen transition");
+addLoadEvent(function () {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["full-screen-api.unprefix.enabled", true],
+ ["full-screen-api.allow-trusted-requests-only", false]
+ ]
+ }, next);
+});
+
+const OPEN_WINDOW_FUNCS = [
+ function openNewTab() {
+ return window.open("about:blank");
+ },
+ function openNewWindow() {
+ return window.open("about:blank", "", "width=300,height=200");
+ }
+];
+
+const ACTION_FUNCS = [
+ function navigate(win) {
+ info("About to navigate to another page");
+ var deferred = new Deferred();
+ win.location = "data:text/html,<html>";
+ setTimeout(() => {
+ SimpleTest.waitForFocus(() => {
+ checkIsChromeFullscreen(win, false).then(() => {
+ win.close();
+ deferred.resolve();
+ });
+ }, win);
+ }, 0);
+ return deferred.promise;
+ },
+ function closeWindow(win) {
+ info("About to close the window");
+ win.close();
+ return Promise.resolve();
+ },
+ function exitFullscreen(win) {
+ info("About to cancel fullscreen");
+ var deferred = new Deferred();
+ function listener() {
+ win.removeEventListener("fullscreenchange", listener);
+ ok(!win.document.fullscreenElement, "Should exit fullscreen");
+ checkIsChromeFullscreen(win, false).then(() => {
+ win.close();
+ deferred.resolve();
+ });
+ }
+ win.addEventListener("fullscreenchange", listener);
+ win.document.exitFullscreen();
+ return deferred.promise;
+ },
+ function exitAndClose(win) {
+ info("About to cancel fullscreen and close the window");
+ win.document.exitFullscreen();
+ win.close();
+ return Promise.resolve();
+ }
+];
+
+function* testGenerator() {
+ for (var openWinFunc of OPEN_WINDOW_FUNCS) {
+ for (var actionFunc of ACTION_FUNCS) {
+ info(`Testing ${openWinFunc.name}, ${actionFunc.name}`);
+ yield { openWinFunc: openWinFunc, actionFunc: actionFunc };
+ }
+ }
+}
+
+function runTest(test) {
+ var win = test.openWinFunc();
+ return new Promise(resolve => {
+ SimpleTest.waitForFocus(resolve, win, true);
+ }).then(() => {
+ return new Promise((resolve, reject) => {
+ var retried = false;
+ function listener(evt) {
+ if (!retried && evt.type == "fullscreenerror") {
+ todo(false, "Failed to enter fullscreen, but try again");
+ retried = true;
+ SimpleTest.waitForFocus(() => {
+ win.document.documentElement.requestFullscreen();
+ }, win, true);
+ return;
+ }
+ win.removeEventListener("fullscreenchange", listener);
+ win.removeEventListener("fullscreenerror", listener);
+ is(evt.type, "fullscreenchange", "Should get fullscreenchange");
+ ok(win.document.fullscreenElement, "Should have entered fullscreen");
+ ok(win.fullScreen, "The window should be in fullscreen");
+ test.actionFunc(win).then(resolve);
+ }
+ if (win.fullScreen) {
+ todo(false, "Should not open in fullscreen mode");
+ win.close();
+ reject();
+ return;
+ }
+ info("About to enter fullscreen");
+ win.addEventListener("fullscreenchange", listener);
+ win.addEventListener("fullscreenerror", listener);
+ win.document.documentElement.requestFullscreen();
+ });
+ }).then(() => {
+ ok(win.closed, "The window should have been closed");
+ });
+}
+
+var tests = testGenerator();
+
+function next() {
+ var test = tests.next().value;
+ if (test) {
+ runTest(test).catch(() => {
+ return new Promise(resolve => {
+ SimpleTest.waitForFocus(resolve);
+ }).then(() => runTest(test));
+ }).catch(() => {
+ ok(false, "Fail to run test " +
+ `${test.openWinFunc.name}, ${test.actionFunc.name}`);
+ }).then(() => {
+ setTimeout(() => SimpleTest.waitForFocus(next), 1000);
+ });
+ } else {
+ SimpleTest.finish();
+ return;
+ }
+}
+
+</script>
+</body>
+</html>
diff --git a/dom/html/test/test_fullscreen-api.html b/dom/html/test/test_fullscreen-api.html
new file mode 100644
index 000000000..1ac5b3b51
--- /dev/null
+++ b/dom/html/test/test_fullscreen-api.html
@@ -0,0 +1,106 @@
+ <!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Bug 545812</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <style>
+ body {
+ background-color: black;
+ }
+ </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=545812">Mozilla Bug 545812</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Tests for Bug 545812 **/
+SimpleTest.requestFlakyTimeout("untriaged");
+
+// Run the tests which go full-screen in new windows, as mochitests normally
+// run in an iframe, which by default will not have the allowfullscreen
+// attribute set, so full-screen won't work.
+var gTestWindows = [
+ "file_fullscreen-multiple.html",
+ "file_fullscreen-rollback.html",
+ "file_fullscreen-esc-exit.html",
+ "file_fullscreen-denied.html",
+ "file_fullscreen-api.html",
+ "file_fullscreen-plugins.html",
+ "file_fullscreen-hidden.html",
+ "file_fullscreen-svg-element.html",
+ "file_fullscreen-navigation.html",
+ "file_fullscreen-scrollbar.html",
+ "file_fullscreen-selector.html",
+ "file_fullscreen-top-layer.html",
+ "file_fullscreen-backdrop.html",
+ "file_fullscreen-nested.html",
+ "file_fullscreen-prefixed.html",
+ "file_fullscreen-unprefix-disabled.html",
+ "file_fullscreen-lenient-setters.html",
+];
+
+var testWindow = null;
+var gTestIndex = 0;
+
+function finish() {
+ SimpleTest.finish();
+}
+
+function nextTest() {
+ if (testWindow) {
+ testWindow.close();
+ }
+ SimpleTest.executeSoon(runNextTest);
+}
+
+function runNextTest() {
+ if (gTestIndex < gTestWindows.length) {
+ info("Run test " + gTestWindows[gTestIndex]);
+ testWindow = window.open(gTestWindows[gTestIndex], "", "width=500,height=500,scrollbars=yes");
+ // We'll wait for the window to load, then make sure our window is refocused
+ // before starting the test, which will get kicked off on "focus".
+ // This ensures that we're essentially back on the primary "desktop" on
+ // OS X Lion before we run the test.
+ testWindow.addEventListener("load", function onload() {
+ testWindow.removeEventListener("load", onload, false);
+ SimpleTest.waitForFocus(function() {
+ SimpleTest.waitForFocus(testWindow.begin, testWindow);
+ });
+ }, false);
+ gTestIndex++;
+ } else {
+ SimpleTest.finish();
+ }
+}
+
+try {
+ window.fullScreen = true;
+} catch (e) {
+}
+is(window.fullScreen, false, "Shouldn't be able to set window fullscreen from content");
+// Ensure the full-screen api is enabled, and will be disabled on test exit.
+// Disable the requirement for trusted contexts only, so the tests are easier
+// to write
+addLoadEvent(function() {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["full-screen-api.enabled", true],
+ ["full-screen-api.unprefix.enabled", true],
+ ["full-screen-api.allow-trusted-requests-only", false],
+ ["full-screen-api.transition-duration.enter", "0 0"],
+ ["full-screen-api.transition-duration.leave", "0 0"]
+ ]}, nextTest);
+});
+SimpleTest.waitForExplicitFinish();
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_hash_encoded.html b/dom/html/test/test_hash_encoded.html
new file mode 100644
index 000000000..f814c8ae9
--- /dev/null
+++ b/dom/html/test/test_hash_encoded.html
@@ -0,0 +1,118 @@
+<!doctype html>
+<html>
+<head>
+<title>Test link.hash attribute</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<pre id="test">
+
+<script>
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [['dom.url.encode_decode_hash', false]]}, runTest);
+
+function runTest() {
+ setupTest();
+ doTestEncoded();
+ SimpleTest.finish();
+}
+
+function setupTest() {
+ var target1 = document.createElement("a");
+ target1.id = "target1";
+ target1.href = "http://www.example.com/#q=♥â¥#hello";
+ document.body.appendChild(target1);
+
+ var target2 = document.createElement("a");
+ target2.id = "target2";
+ target2.href = "http://www.example.com/#q=%E2%99%A5%C3%A2%C2%A5";
+ document.body.appendChild(target2);
+
+ var target3 = document.createElement("a");
+ target3.id = "target3";
+ target3.href = "http://www.example.com/#/search/%23important";
+ document.body.appendChild(target3);
+
+ var target4 = document.createElement("a");
+ target4.id = "target4";
+ target4.href = 'http://www.example.com/#{"a":[13, 42], "b":{"key":"value"}}';
+ document.body.appendChild(target4);
+}
+
+function doTestEncoded() {
+ // Tests Link::GetHash
+
+ // Check that characters aren't being encoded
+ var target = document.getElementById("target1");
+ is(target.hash, '#q=♥â¥#hello', 'Unexpected link hash');
+
+ // Check that encoded characters aren't being decoded
+ target = document.getElementById("target2");
+ is(target.hash, '#q=%E2%99%A5%C3%A2%C2%A5', 'Unexpected link hash');
+
+ // A more regular use case
+ target = document.getElementById("target3");
+ is(target.hash, '#/search/%23important', 'Unexpected link hash');
+
+ // Some JSON
+ target = document.getElementById("target4");
+ is(target.hash, '#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected link hash');
+
+ // Tests URL::GetHash
+
+ var url = new URL("http://www.example.com/#q=♥â¥#hello")
+ is(url.hash, '#q=♥â¥#hello', 'Unexpected url hash');
+
+ url = new URL("http://www.example.com/#q=%E2%99%A5%C3%A2%C2%A5")
+ is(url.hash, '#q=%E2%99%A5%C3%A2%C2%A5', 'Unexpected url hash');
+
+ url = new URL("http://www.example.com/#/search/%23important")
+ is(url.hash, '#/search/%23important', 'Unexpected url hash');
+
+ // Test getters and setters
+
+ url = new URL("http://www.example.com/");
+ url.hash = "#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important"
+ is(url.hash, '#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important', 'Unexpected url hash');
+
+ // codepath in nsStandardUrl::SetRef is different if the path is non-empty
+ url = new URL("http://www.example.com/test/");
+ url.hash = "#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important"
+ is(url.hash, '#q=♥â¥#hello%E2%99%A5%C3%A2%C2%A5#/search/%23important', 'Unexpected url hash');
+
+ url = new URL("http://www.example.com/");
+ url.hash = '#{"a":[13, 42], "b":{"key":"value"}}';
+ is(target.hash, '#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected url hash');
+ var parsed = JSON.parse(target.hash.substring(1));
+ is(parsed.b.key, 'value', 'JSON not parsed correctly');
+
+ url = new URL("http://www.example.com/test/");
+ url.hash = '#{"a":[13, 42], "b":{"key":"value"}}';
+ is(target.hash, '#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected url hash');
+ parsed = JSON.parse(target.hash.substring(1));
+ is(parsed.b.key, 'value', 'JSON not parsed correctly');
+
+ // Tests Location::GetHash
+
+ window.history.pushState(1, document.title, '#q=♥â¥#hello');
+ is(location.hash,'#q=♥â¥#hello', 'Unexpected location hash');
+
+ window.history.pushState(1, document.title, '#q=%E2%99%A5%C3%A2%C2%A5');
+ is(location.hash,'#q=%E2%99%A5%C3%A2%C2%A5', 'Unexpected location hash');
+
+ window.history.pushState(1, document.title, '#/search/%23important');
+ is(location.hash,'#/search/%23important', 'Unexpected location hash');
+
+ window.history.pushState(1, document.title, '#{"a":[13, 42], "b":{"key":"value"}}');
+ is(location.hash,'#{"a":[13, 42], "b":{"key":"value"}}', 'Unexpected location hash');
+
+}
+
+</script>
+
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_hidden.html b/dom/html/test/test_hidden.html
new file mode 100644
index 000000000..7b9d488c0
--- /dev/null
+++ b/dom/html/test/test_hidden.html
@@ -0,0 +1,52 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=567663
+-->
+<head>
+ <title>Test for Bug 567663</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=567663">Mozilla Bug 567663</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <p></p>
+ <p hidden></p>
+</div>
+<pre id="test">
+<script>
+/** Test for Bug 567663 **/
+var ps = document.getElementById("content").getElementsByTagName("p");
+is(ps[0].hidden, false, "First p's IDL attribute was wrong.");
+is(ps[0].hasAttribute("hidden"), false, "First p had a content attribute.");
+is(ps[1].hidden, true, "Second p's IDL attribute was wrong.");
+is(ps[1].hasAttribute("hidden"), true,
+ "Second p didn't have a content attribute.");
+is(ps[1].getAttribute("hidden"), "",
+ "Second p's content attribute was wrong.");
+
+ps[0].hidden = true;
+is(ps[0].getAttribute("hidden"), "",
+ "Content attribute was set to an incorrect value.");
+ps[1].hidden = false;
+is(ps[1].hasAttribute("hidden"), false,
+ "Second p still had a content attribute.");
+
+ps[0].setAttribute("hidden", "banana");
+is(ps[0].hidden, true, "p's IDL attribute was wrong after setting.");
+is(ps[0].getAttribute("hidden"), "banana", "Content attribute changed.");
+
+ps[0].setAttribute("hidden", "false");
+is(ps[0].hidden, true, "p's IDL attribute was wrong after setting.");
+is(ps[0].getAttribute("hidden"), "false", "Content attribute changed.");
+
+ps[0].removeAttribute("hidden");
+is(ps[0].hidden, false,
+ "p's IDL attribute was wrong after removing the content attribute.");
+is(ps[0].hasAttribute("hidden"), false);
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_html_attributes_reflection.html b/dom/html/test/test_html_attributes_reflection.html
new file mode 100644
index 000000000..372c2503a
--- /dev/null
+++ b/dom/html/test/test_html_attributes_reflection.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLHtmlElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLHtmlElement attributes reflection **/
+
+// .version
+reflectString({
+ element: document.createElement("html"),
+ attribute: "version",
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_htmlcollection.html b/dom/html/test/test_htmlcollection.html
new file mode 100644
index 000000000..1452f0c3c
--- /dev/null
+++ b/dom/html/test/test_htmlcollection.html
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=772869
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 772869</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772869">Mozilla Bug 772869</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <a class="foo" name="x"></a>
+ <span class="foo" id="y"></span>
+ <span class="foo" name="x"></span>
+ <form class="foo" name="z" id="w"></form>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 772869 **/
+var x = document.getElementsByClassName("foo");
+x.something = "another";
+var names = [];
+for (var name in x) {
+ names.push(name);
+}
+is(names.length, 8, "Should have 8 enumerated names");
+is(names[0], "0", "Enum entry 1")
+is(names[1], "1", "Enum entry 2")
+is(names[2], "2", "Enum entry 3")
+is(names[3], "3", "Enum entry 4")
+is(names[4], "something", "Enum entry 5")
+is(names[5], "item", "Enum entry 6")
+is(names[6], "namedItem", "Enum entry 7")
+is(names[7], "length", "Enum entry 8");
+
+names = Object.getOwnPropertyNames(x);
+is(names.length, 9, "Should have 9 items");
+is(names[0], "0", "Entry 1")
+is(names[1], "1", "Entry 2")
+is(names[2], "2", "Entry 3")
+is(names[3], "3", "Entry 4")
+is(names[4], "x", "Entry 5")
+is(names[5], "y", "Entry 6")
+is(names[6], "w", "Entry 7")
+is(names[7], "z", "Entry 8")
+is(names[8], "something", "Entry 9")
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_general.html b/dom/html/test/test_iframe_sandbox_general.html
new file mode 100644
index 000000000..6d3a190ee
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_general.html
@@ -0,0 +1,283 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=341604
+Implement HTML5 sandbox attribute for IFRAMEs - general tests
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 341604 and Bug 766282</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs - general tests **/
+
+SimpleTest.expectAssertions(0, 1);
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestCompleteLog();
+
+// a postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin' to communicate pass/fail back to this main page.
+// it expects to be called with an object like {ok: true/false, desc:
+// <description of the test> which it then forwards to ok()
+window.addEventListener("message", receiveMessage, false);
+
+function receiveMessage(event)
+{
+ ok_wrapper(event.data.ok, event.data.desc);
+}
+
+var completedTests = 0;
+var passedTests = 0;
+
+function ok_wrapper(result, desc) {
+ ok(result, desc);
+
+ completedTests++;
+
+ if (result) {
+ passedTests++;
+ }
+
+ if (completedTests == 33) {
+ is(passedTests, completedTests, "There are " + completedTests + " general tests that should pass");
+ SimpleTest.finish();
+ }
+}
+
+function doTest() {
+ // passes twice if good
+ // 1) test that inline scripts (<script>) can run in an iframe sandboxed with "allow-scripts"
+ // (done in file_iframe_sandbox_c_if1.html which has 'allow-scripts')
+
+ // passes twice if good
+ // 2) test that <script src=...> can run in an iframe sandboxed with "allow-scripts"
+ // (done in file_iframe_sandbox_c_if1.html which has 'allow-scripts')
+
+ // passes twice if good
+ // 3) test that script in an event listener (body onload) can run in an iframe sandboxed with "allow-scripts"
+ // (done in file_iframe_sandbox_c_if1.html which has 'allow-scripts')
+
+ // passes twice if good
+ // 4) test that script in an javascript:url can run in an iframe sandboxed with "allow-scripts"
+ // (done in file_iframe_sandbox_c_if1.html which has 'allow-scripts')
+
+ // fails if bad
+ // 5) test that inline scripts cannot run in an iframe sandboxed without "allow-scripts"
+ // (done in file_iframe_sandbox_c_if2.html which has sandbox='')
+
+ // fails if bad
+ // 6) test that <script src=...> cannot run in an iframe sandboxed without "allow-scripts"
+ // (done in file_iframe_sandbox_c_if2.html which has sandbox='')
+
+ // fails if bad
+ // 7) test that script in an event listener (body onload) cannot run in an iframe sandboxed without "allow-scripts"
+ // (done in file_iframe_sandbox_c_if2.html which has sandbox='')
+
+ // fails if bad
+ // 8) test that script in an event listener (img onerror) cannot run in an iframe sandboxed without "allow-scripts"
+ // (done in file_iframe_sandbox_c_if2.html which has sandbox='')
+
+ // fails if bad
+ // 9) test that script in an javascript:url cannot run in an iframe sandboxed without "allow-scripts"
+ // (done in file_iframe_sandbox_c_if_5.html which has sandbox='allow-same-origin')
+ var if_w = document.getElementById('if_5').contentWindow;
+ sendMouseEvent({type:'click'}, 'a_link', if_w);
+
+ // passes if good
+ // 10) test that a new iframe has sandbox attribute
+ var ifr = document.createElement("iframe");
+ ok_wrapper("sandbox" in ifr, "a new iframe should have a sandbox attribute");
+
+ // passes if good
+ // 11) test that the sandbox attribute's default stringyfied value is an empty string
+ ok_wrapper(ifr.sandbox.length === 0 && ifr.sandbox == "", "default sandbox attribute should be an empty string");
+
+ // passes if good
+ // 12) test that a sandboxed iframe with 'allow-forms' can submit forms
+ // (done in file_iframe_sandbox_c_if3.html which has 'allow-forms' and 'allow-scripts')
+
+ // fails if bad
+ // 13) test that a sandboxed iframe without 'allow-forms' can NOT submit forms
+ // (done in file_iframe_sandbox_c_if1.html which only has 'allow-scripts')
+
+ // fails if bad
+ // 14) test that a sandboxed iframe can't open a new window using the target.attribute
+ // this is done via file_iframe_sandbox_c_if4.html which is sandboxed with "allow-scripts" and "allow-same-origin"
+ // the window it attempts to open calls window.opener.ok(false, ...) and file_iframe_c_if4.html has an ok()
+ // function that calls window.parent.ok_wrapper
+
+ // passes if good
+ // 15) test that a sandboxed iframe can't open a new window using window.open
+ // this is done via file_iframe_sandbox_c_if4.html which is sandboxed with "allow-scripts" and "allow-same-origin"
+ // the window it attempts to open calls window.opener.ok(false, ...) and file_iframe_c_if4.html has an ok()
+ // function that calls window.parent.ok_wrapper
+
+ // passes if good
+ // 16) test that a sandboxed iframe can't open a new window using window.ShowModalDialog
+ // this is done via file_iframe_sandbox_c_if4.html which is sandboxed with "allow-scripts" and "allow-same-origin"
+ // the window it attempts to open calls window.opener.ok(false, ...) and file_iframe_c_if4.html has an ok()
+ // function that calls window.parent.ok_wrapper
+
+ // passes twice if good
+ // 17) test that a sandboxed iframe can access same-origin documents and run scripts when its sandbox attribute
+ // is separated with two spaces
+ // done via file_iframe_sandbox_c_if6.html which is sandboxed with " allow-scripts allow-same-origin "
+
+ // passes twice if good
+ // 18) test that a sandboxed iframe can access same-origin documents and run scripts when its sandbox attribute
+ // is separated with tabs
+ // done via file_iframe_sandbox_c_if6.html which is sandboxed with "&#x09;allow-scripts&#x09;allow-same-origin&#x09;"
+
+ // passes twice if good
+ // 19) test that a sandboxed iframe can access same-origin documents and run scripts when its sandbox attribute
+ // is separated with line feeds
+ // done via file_iframe_sandbox_c_if6.html which is sandboxed with "&#x0a;allow-scripts&#x0a;allow-same-origin&#x0a;"
+
+ // passes twice if good
+ // 20) test that a sandboxed iframe can access same-origin documents and run scripts when its sandbox attribute
+ // is separated with form feeds
+ // done via file_iframe_sandbox_c_if6.html which is sandboxed with "&#x0c;allow-scripts&#x0c;allow-same-origin&#x0c;"
+
+ // passes twice if good
+ // 21) test that a sandboxed iframe can access same-origin documents and run scripts when its sandbox attribute
+ // is separated with carriage returns
+ // done via file_iframe_sandbox_c_if6.html which is sandboxed with "&#x0d;allow-scripts&#x0d;allow-same-origin&#x0d;"
+
+ // fails if bad
+ // 22) test that an iframe with sandbox="" does NOT have script in a src attribute created by a javascript:
+ // URL executed
+ // done by this page, see if_7
+
+ // passes if good
+ // 23) test that an iframe with sandbox="allow-scripts" DOES have script in a src attribute created by a javascript:
+ // URL executed
+ // done by this page, see if_8
+
+ // fails if bad
+ // 24) test that an iframe with sandbox="", starting out with a document already loaded, does NOT have script in a newly
+ // set src attribute created by a javascript: URL executed
+ // done by this page, see if_9
+
+ // passes if good
+ // 25) test that an iframe with sandbox="allow-scripts", starting out with a document already loaded, DOES have script
+ // in a newly set src attribute created by a javascript: URL executed
+ // done by this page, see if_10
+
+ // passes if good or fails if bad
+ // 26) test that an sandboxed document without 'allow-same-origin' can NOT access indexedDB
+ // done via file_iframe_sandbox_c_if7.html, which has sandbox='allow-scripts'
+
+ // passes if good or fails if bad
+ // 27) test that an sandboxed document with 'allow-same-origin' can access indexedDB
+ // done via file_iframe_sandbox_c_if8.html, which has sandbox='allow-scripts allow-same-origin'
+
+ // fails if bad
+ // 28) Test that a sandboxed iframe can't open a new window using the target.attribute for a
+ // non-existing browsing context (BC341604).
+ // This is done via file_iframe_sandbox_c_if4.html which is sandboxed with "allow-scripts" and "allow-same-origin"
+ // the window it attempts to open calls window.opener.ok(false, ...) and file_iframe_c_if4.html has an ok()
+ // function that calls window.parent.ok_wrapper.
+
+ // passes twice if good
+ // 29-32) Test that sandboxFlagsAsString returns the set flags.
+ // see if_14 and if_15
+
+ // passes once if good
+ // 33) Test that sandboxFlagsAsString returns null if iframe does not have sandbox flag set.
+ // see if_16
+}
+
+addLoadEvent(doTest);
+
+var started_if_9 = false;
+var started_if_10 = false;
+
+function start_if_9() {
+ if (started_if_9)
+ return;
+
+ started_if_9 = true;
+ sendMouseEvent({type:'click'}, 'a_button');
+}
+
+function start_if_10() {
+ if (started_if_10)
+ return;
+
+ started_if_10 = true;
+ sendMouseEvent({type:'click'}, 'a_button2');
+}
+
+function do_if_9() {
+ var if_9 = document.getElementById('if_9');
+ if_9.src = 'javascript:"<html><script>window.parent.ok_wrapper(false, \'an iframe sandboxed without allow-scripts should not execute script in a javascript URL in a newly set src attribute\');<\/script><\/html>"';
+}
+
+function do_if_10() {
+ var if_10 = document.getElementById('if_10');
+ if_10.src = 'javascript:"<html><script>window.parent.ok_wrapper(true, \'an iframe sandboxed with allow-scripts should execute script in a javascript URL in a newly set src attribute\');<\/script><\/html>"';
+}
+
+function eqFlags(a, b) {
+ // both a and b should be either null or have the array same flags
+ if (a === null && b === null) { return true; }
+ if (a === null || b === null) { return false; }
+ if (a.length !== b.length) { return false; }
+ var a_sorted = a.sort();
+ var b_sorted = b.sort();
+ for (var i in a_sorted) {
+ if (a_sorted[i] !== b_sorted[i]) { return false; }
+ }
+ return true;
+}
+
+function getSandboxFlags(doc) {
+ var flags = doc.sandboxFlagsAsString;
+ if (flags === null) { return null; }
+ return flags? flags.split(" "):[];
+}
+
+function test_sandboxFlagsAsString(name, expected) {
+ var ifr = document.getElementById(name);
+ try {
+ var flags = getSandboxFlags(SpecialPowers.wrap(ifr).contentDocument);
+ ok_wrapper(eqFlags(flags, expected), name + ' expected: "' + expected + '", got: "' + flags + '"');
+ } catch (e) {
+ ok_wrapper(false, name + ' expected "' + expected + ', but failed with ' + e);
+ }
+}
+
+</script>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
+<p id="display"></p>
+<div id="content">
+<iframe sandbox="allow-same-origin allow-scripts" id="if_1" src="file_iframe_sandbox_c_if1.html" height="10" width="10"></iframe>
+<iframe sandbox="aLlOw-SAME-oRiGin ALLOW-sCrIpTs" id="if_1_case_insensitive" src="file_iframe_sandbox_c_if1.html" height="10" width="10"></iframe>
+<iframe sandbox="" id="if_2" src="file_iframe_sandbox_c_if2.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-forms allow-scripts" id="if_3" src="file_iframe_sandbox_c_if3.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin allow-scripts" id="if_4" src="file_iframe_sandbox_c_if4.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin" id="if_5" src="file_iframe_sandbox_c_if5.html" height="10" width="10"></iframe>
+<iframe sandbox=" allow-same-origin allow-scripts " id="if_6_a" src="file_iframe_sandbox_c_if6.html" height="10" width="10"></iframe>
+<iframe sandbox="&#x09;allow-same-origin&#x09;allow-scripts&#x09;" id="if_6_b" src="file_iframe_sandbox_c_if6.html" height="10" width="10"></iframe>
+<iframe sandbox="&#x0a;allow-same-origin&#x0a;allow-scripts&#x0a;" id="if_6_c" src="file_iframe_sandbox_c_if6.html" height="10" width="10"></iframe>
+<iframe sandbox="&#x0c;allow-same-origin&#x0c;allow-scripts&#x0c;" id="if_6_d" src="file_iframe_sandbox_c_if6.html" height="10" width="10"></iframe>
+<iframe sandbox="&#x0d;allow-same-origin&#x0d;allow-scripts&#x0d;" id="if_6_e" src="file_iframe_sandbox_c_if6.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin" id='if_7' src="javascript:'<html><script>window.parent.ok_wrapper(false, \'an iframe sandboxed without allow-scripts should not execute script in a javascript URL in its src attribute\');<\/script><\/html>';" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin allow-scripts" id='if_8' src="javascript:'<html><script>window.parent.ok_wrapper(true, \'an iframe sandboxed without allow-scripts should execute script in a javascript URL in its src attribute\');<\/script><\/html>';" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin" onload='start_if_9()' id='if_9' src="about:blank" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin allow-scripts" onload='start_if_10()' id='if_10' src="about:blank" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id='if_11' src="file_iframe_sandbox_c_if7.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin allow-scripts" id='if_12' src="file_iframe_sandbox_c_if8.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation " id='if_13' src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_13",["allow-forms", "allow-pointer-lock", "allow-popups", "allow-same-origin", "allow-scripts", "allow-top-navigation"])'></iframe>
+<iframe sandbox="&#x09;allow-same-origin&#x09;allow-scripts&#x09;" id="if_14" src="file_iframe_sandbox_c_if6.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_14",["allow-same-origin","allow-scripts"])'></iframe>
+<iframe sandbox="" id="if_15" src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_15",[])'></iframe>
+<iframe id="if_16" src="file_iframe_sandbox_c_if9.html" height="10" width="10" onload='test_sandboxFlagsAsString("if_16",null)'></iframe>
+<input type='button' id="a_button" onclick='do_if_9()'>
+<input type='button' id="a_button2" onclick='do_if_10()'>
+</div>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_inheritance.html b/dom/html/test/test_iframe_sandbox_inheritance.html
new file mode 100644
index 000000000..ddf45f70b
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_inheritance.html
@@ -0,0 +1,203 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=341604
+Implement HTML5 sandbox attribute for IFRAMEs - inheritance tests
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/
+/** Inheritance Tests **/
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+// A postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin' to communicate pass/fail back to this main page.
+// It expects to be called with an object like {ok: true/false, desc:
+// <description of the test> which it then forwards to ok().
+window.addEventListener("message", receiveMessage, false);
+
+function receiveMessage(event) {
+ switch (event.data.type) {
+ case "attempted":
+ testAttempted();
+ break;
+ case "ok":
+ ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
+ break;
+ default:
+ // allow for old style message
+ if (event.data.ok != undefined) {
+ ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
+ }
+ }
+}
+
+var attemptedTests = 0;
+var passedTests = 0;
+var totalTestsToPass = 15;
+var totalTestsToAttempt = 19;
+
+function ok_wrapper(result, desc, addToAttempted = true) {
+ ok(result, desc);
+
+ if (result) {
+ passedTests++;
+ }
+
+ if (addToAttempted) {
+ testAttempted();
+ }
+}
+
+// Added so that tests that don't register unless they fail,
+// can at least notify that they've attempted to run.
+function testAttempted() {
+ attemptedTests++;
+ if (attemptedTests == totalTestsToAttempt) {
+ // Make sure all tests have had a chance to complete.
+ setTimeout(function() {finish();}, 1000);
+ }
+}
+
+var finishCalled = false;
+
+function finish() {
+ if (!finishCalled) {
+ finishCalled = true;
+ is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " inheritance tests that should pass");
+
+ SimpleTest.finish();
+ }
+}
+
+function doTest() {
+ // fails if bad
+ // 1) an iframe with no sandbox attribute inside an iframe that has sandbox = ""
+ // should not be able to execute scripts (cannot ever loosen permissions)
+ // (done by file_iframe_sandbox_a_if2.html contained within file_iframe_sandbox_a_if1.html)
+ testAttempted();
+
+ // fails if bad
+ // 2) an iframe with sandbox = "allow-scripts" inside an iframe that has sandbox = ""
+ // should not be able to execute scripts (cannot ever loosen permissions)
+ // (done by file_iframe_sandbox_a_if2.html contained within file_iframe_sandbox_a_if1.html)
+ testAttempted();
+
+ // passes if good and fails if bad
+ // 3) an iframe with no sandbox attribute inside an iframe that has sandbox = "allow-scripts"
+ // should not be same origin with the top window
+ // (done by file_iframe_sandbox_a_if4.html contained within file_iframe_sandbox_a_if3.html)
+
+ // passes if good and fails if bad
+ // 4) an iframe with no sandbox attribute inside an iframe that has sandbox = "allow-scripts"
+ // should not be same origin with its parent
+ // (done by file_iframe_sandbox_a_if4.html contained within file_iframe_sandbox_a_if3.html)
+
+ // passes if good
+ // 5) an iframe with 'allow-same-origin' and 'allow-scripts' inside an iframe with 'allow-same-origin'
+ // and 'allow-scripts' should be same origin with the top window
+ // (done by file_iframe_sandbox_a_if6.html contained within file_iframe_sandbox_a_if5.html)
+
+ // passes if good
+ // 6) an iframe with 'allow-same-origin' and 'allow-scripts' inside an iframe with 'allow-same-origin'
+ // and 'allow-scripts' should be same origin with its parent
+ // (done by file_iframe_sandbox_a_if6.html contained within file_iframe_sandbox_a_if5.html)
+
+ // passes if good
+ // 7) an iframe with no sandbox attribute inside an iframe that has sandbox = "allow-scripts"
+ // should be able to execute scripts
+ // (done by file_iframe_sandbox_a_if7.html contained within file_iframe_sandbox_a_if3.html)
+
+ // fails if bad
+ // 8) an iframe with sandbox="" inside an iframe that has allow-scripts should not be able
+ // to execute scripts
+ // (done by file_iframe_sandbox_a_if2.html contained within file_iframe_sandbox_a_if3.html)
+ testAttempted();
+
+ // passes if good
+ // 9) make sure that changing the sandbox flags on an iframe (if_8) doesn't affect
+ // the sandboxing of subloads of content within that iframe
+ var if_8 = document.getElementById('if_8');
+ if_8.sandbox = 'allow-scripts';
+ if_8.contentWindow.doSubload();
+
+ // passes if good
+ // 10) a <frame> inside an <iframe> sandboxed with 'allow-scripts' should not be same
+ // origin with this document
+ // done by file_iframe_sandbox_a_if11.html which is contained with file_iframe_sandbox_a_if10.html
+
+ // passes if good
+ // 11) a <frame> inside a <frame> inside an <iframe> sandboxed with 'allow-scripts' should not be same
+ // origin with its parent frame or this document
+ // done by file_iframe_sandbox_a_if12.html which is contained with file_iframe_sandbox_a_if11.html
+
+ // passes if good, fails if bad
+ // 12) An <object> inside an <iframe> sandboxed with 'allow-scripts' should not be same
+ // origin with this document
+ // Done by file_iframe_sandbox_a_if14.html which is contained within file_iframe_sandbox_a_if13.html
+
+ // passes if good, fails if bad
+ // 13) An <object> inside an <object> inside an <iframe> sandboxed with 'allow-scripts' should not be same
+ // origin with its parent frame or this document
+ // Done by file_iframe_sandbox_a_if15.html which is contained within file_iframe_sandbox_a_if14.html
+
+ // passes if good, fails if bad
+ // 14) An <object> inside a <frame> inside an <iframe> sandboxed with 'allow-scripts' should not be same
+ // origin with its parent frame or this document
+ // Done by file_iframe_sandbox_a_if15.html which is contained within file_iframe_sandbox_a_if16.html
+ // which is contained within file_iframe_sandbox_a_if10.html
+
+ // passes if good
+ // 15) An <object> inside an <object> inside an <iframe> sandboxed with 'allow-scripts allow-forms'
+ // should be able to submit forms.
+ // Done by file_iframe_sandbox_a_if15.html which is contained within file_iframe_sandbox_a_if14.html
+
+ // passes if good
+ // 16) An <object> inside a <frame> inside an <iframe> sandboxed with 'allow-scripts allow-forms'
+ // should be able to submit forms.
+ // Done by file_iframe_sandbox_a_if15.html which is contained within file_iframe_sandbox_a_if16.html
+ // which is contained within file_iframe_sandbox_a_if10.html
+
+ // fails if bad
+ // 17) An <object> inside an <iframe> sandboxed with 'allow-same-origin'
+ // should not be able to run scripts.
+ // Done by iframe "if_no_scripts" using a data: load.
+ testAttempted();
+
+ // passes if good
+ // 18) An <object> inside an <iframe> sandboxed with 'allow-scripts allow-same-origin'
+ // should be able to run scripts and be same origin with this document.
+ // Done by iframe "if_scripts" using a data: load.
+
+ // passes if good, fails if bad
+ // 19) Make sure that the parent's document's sandboxing flags are copied when
+ // changing the sandbox flags on an iframe inside an iframe.
+ // Done in file_iframe_sandbox_a_if17.html and file_iframe_sandbox_a_if18.html
+}
+
+addLoadEvent(doTest);
+</script>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
+<p id="display"></p>
+<div id="content">
+<iframe sandbox="" id="if_1" src="file_iframe_sandbox_a_if1.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_3" src="file_iframe_sandbox_a_if3.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts allow-same-origin" id="if_5" src="file_iframe_sandbox_a_if5.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts allow-same-origin" id="if_8" src="file_iframe_sandbox_a_if8.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts allow-forms" id="if_10" src="file_iframe_sandbox_a_if10.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts allow-forms" id="if_13" src="file_iframe_sandbox_a_if13.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin" id="if_no_scripts" src="data:text/html,<object%20data='data:text/html,<script>parent.parent.ok_wrapper(false, &quot;an object inside an iframe sandboxed with only allow-same-origin should not be able to run scripts&quot;)</script>'></object>" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts allow-same-origin" id="if_scripts" src="data:text/html,<object%20data='data:text/html,<script>parent.parent.ok_wrapper(true, &quot;an object inside an iframe sandboxed with allow-scripts allow-same-origin should be able to run scripts and call functions in the parent of the iframe&quot;)</script>'></object>" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin" id="if_19" src="data:text/html,<iframe%20data='data:text/html,<script>parent.parent.ok_wrapper(true, &quot;an object inside an iframe sandboxed with allow-scripts allow-same-origin should be able to run scripts and call functions in the parent of the iframe&quot;)</script>'></object>" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_17" src="file_iframe_sandbox_a_if17.html" height="10" width="10"></iframe>
+</div>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_modal.html b/dom/html/test/test_iframe_sandbox_modal.html
new file mode 100644
index 000000000..1307ea9a5
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_modal.html
@@ -0,0 +1,122 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=766282
+implement allow-popups directive for iframe sandbox
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 766282</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script>
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+// A postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin' to communicate pass/fail back to this main page.
+window.addEventListener("message", receiveMessage, false);
+
+function receiveMessage(event) {
+ switch (event.data.type) {
+ case "attempted":
+ testAttempted();
+ break;
+ case "ok":
+ ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
+ break;
+ default:
+ // allow for old style message
+ if (event.data.ok != undefined) {
+ ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
+ }
+ }
+}
+
+var attemptedTests = 0;
+var passedTests = 0;
+var totalTestsToPass = 5;
+var totalTestsToAttempt = 5;
+
+function ok_wrapper(result, desc, addToAttempted = true) {
+ ok(result, desc);
+
+ if (result) {
+ passedTests++;
+ }
+
+ if (addToAttempted) {
+ testAttempted();
+ }
+}
+
+// Added so that tests that don't register unless they fail,
+// can at least notify that they've attempted to run.
+function testAttempted() {
+ attemptedTests++;
+ if (attemptedTests == totalTestsToAttempt) {
+ // Make sure all tests have had a chance to complete.
+ setTimeout(function() {finish();}, 1000);
+ }
+}
+
+var finishCalled = false;
+
+function finish() {
+ if (!finishCalled) {
+ finishCalled = true;
+ is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " modal tests that should pass");
+
+ SimpleTest.finish();
+ }
+}
+
+function doTest() {
+ // passes if good and fails if bad
+ // 1) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups
+ // allow-same-origin" should not have its origin sandbox flag set and be able to access
+ // document.cookie. (Done by file_iframe_sandbox_k_if5.html opened from
+ // file_iframe_sandbox_j_if1.html) using showModalDialog.)
+
+ // passes if good
+ // 2) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups
+ // allow-top-navigation" should not have its top-level navigation sandbox flag set and be able to
+ // navigate top. (Done by file_iframe_sandbox_k_if5.html (and if6) opened from
+ // file_iframe_sandbox_j_if1.html) using showModalDialog.)
+
+ // passes if good
+ // 3) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups
+ // all-forms" should not have its forms sandbox flag set and be able to submit forms.
+ // (Done by file_iframe_sandbox_k_if7.html opened from
+ // file_iframe_sandbox_j_if1.html) using showModalDialog.)
+
+ // passes if good
+ // 4) Make sure that the sandbox flags copied to a new browsing context are taken from the
+ // current active document not the browsing context (iframe / docShell).
+ // This is done by removing allow-same-origin and calling doSubOpens from file_iframe_sandbox_j_if2.html,
+ // which opens file_iframe_sandbox_k_if9.html using showModalDialog.
+ var if_2 = document.getElementById('if_2');
+ if_2.sandbox = 'allow-scripts allow-popups';
+ if_2.contentWindow.doSubOpens();
+
+ // passes if good
+ // 5) Test that a sandboxed iframe with "allow-popups" can open a new window using window.ShowModalDialog.
+ // This is done via file_iframe_sandbox_j_if3.html which is sandboxed with "allow-popups allow-scripts
+ // allow-same-origin". The window it attempts to open calls window.opener.ok(true, ...) and
+ // file_iframe_j_if3.html has an ok() function that calls window.parent.ok_wrapper.
+}
+
+addLoadEvent(doTest);
+</script>
+
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=766282">Mozilla Bug 766282</a> - implement allow-popups directive for iframe sandbox
+<p id="display"></p>
+<div id="content">
+<iframe sandbox="allow-scripts allow-popups allow-modals allow-same-origin allow-forms allow-top-navigation" id="if_1" src="file_iframe_sandbox_j_if1.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts allow-popups allow-modals allow-same-origin" id="if_2" src="file_iframe_sandbox_j_if2.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-popups allow-modals allow-same-origin allow-scripts" id="if_3" src="file_iframe_sandbox_j_if3.html" height="10" width="10"></iframe>
+</div>
diff --git a/dom/html/test/test_iframe_sandbox_navigation.html b/dom/html/test/test_iframe_sandbox_navigation.html
new file mode 100644
index 000000000..b60f715f3
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_navigation.html
@@ -0,0 +1,281 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=341604
+Implement HTML5 sandbox attribute for IFRAMEs
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604 - navigation</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/
+/** Navigation tests Part 1**/
+
+SimpleTest.requestLongerTimeout(2); // slow on Android
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+// a postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin'/other windows to communicate pass/fail back to this main page.
+// it expects to be called with an object like {ok: true/false, desc:
+// <description of the test> which it then forwards to ok()
+window.addEventListener("message", receiveMessage, false);
+
+var testPassesReceived = 0;
+
+function receiveMessage(event) {
+ switch (event.data.type) {
+ case "attempted":
+ testAttempted();
+ break;
+ case "ok":
+ ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
+ break;
+ case "if_10":
+ doIf10TestPart2();
+ break;
+ default:
+ // allow for old style message
+ if (event.data.ok != undefined) {
+ ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
+ }
+ }
+}
+
+// Open windows for tests to attempt to navigate later.
+var windowsToClose = new Array();
+
+var attemptedTests = 0;
+var passedTests = 0;
+var totalTestsToPass = 7;
+var totalTestsToAttempt = 13;
+
+function ok_wrapper(result, desc, addToAttempted = true) {
+ ok(result, desc);
+
+ if (result) {
+ passedTests++;
+ }
+
+ if (addToAttempted) {
+ testAttempted();
+ }
+}
+
+// Added so that tests that don't register unless they fail,
+// can at least notify that they've attempted to run.
+function testAttempted() {
+ attemptedTests++;
+ if (attemptedTests == totalTestsToAttempt) {
+ // Make sure all tests have had a chance to complete.
+ setTimeout(function() {finish();}, 1000);
+ }
+}
+
+var finishCalled = false;
+
+function finish() {
+ if (!finishCalled) {
+ finishCalled = true;
+ is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " navigation tests that should pass");
+
+ closeWindows();
+
+ SimpleTest.finish();
+ }
+}
+
+function checkTestsFinished() {
+ // If our own finish() has not been called, probably failed due to a timeout, so close remaining windows.
+ if (!finishCalled) {
+ closeWindows();
+ }
+}
+
+function closeWindows() {
+ for (var i = 0; i < windowsToClose.length; i++) {
+ windowsToClose[i].close();
+ }
+}
+
+function doTest() {
+ // passes if good
+ // 1) A sandboxed iframe is allowed to navigate itself
+ // (done by file_iframe_sandbox_d_if1.html which has 'allow-scripts' and navigates to
+ // file_iframe_sandbox_navigation_pass.html).
+
+ // passes if good
+ // 2) A sandboxed iframe is allowed to navigate its children, even if they are sandboxed
+ // (done by file_iframe_sandbox_d_if2.html which has 'allow-scripts', it navigates a child
+ // iframe containing file_iframe_sandbox_navigation_start.html to file_iframe_sandbox_navigation_pass.html).
+
+ // fails if bad
+ // 3) A sandboxed iframe is not allowed to navigate its ancestor
+ // (done by file_iframe_sandbox_d_if4.html contained within file_iframe_sandbox_d_if3.html,
+ // it attempts to navigate file_iframe_sandbox_d_if3.html to file_iframe_sandbox_navigation_fail.html).
+
+ // fails if bad
+ // 4) A sandboxed iframe is not allowed to navigate its sibling
+ // (done by file_iframe_sandbox_d_if5.html which has 'allow scripts allow-same-origin'
+ // and attempts to navigate file_iframe_navigation_start.html contained in if_sibling on this
+ // page to file_iframe_sandbox_navigation_fail.html).
+
+ // passes if good, fails if bad
+ // 5) When a link is clicked in a sandboxed iframe, the document navigated to is sandboxed
+ // the same as the original document and is not same origin with parent document
+ // (done by file_iframe_sandbox_d_if6.html which simulates a link click and navigates
+ // to file_iframe_sandbox_d_if7.html which attempts to call back into its parent).
+
+ // fails if bad
+ // 6) An iframe (if_8) has sandbox="allow-same-origin allow-scripts", the sandboxed document
+ // (file_iframe_sandbox_d_if_8.html) that it contains accesses its parent (this file) and removes
+ // 'allow-same-origin' and then triggers a reload.
+ // The document should not be able to access its parent (this file).
+
+ // fails if bad
+ // 7) An iframe (if_9) has sandbox="allow-same-origin allow-scripts", the sandboxed document
+ // (file_iframe_sandbox_d_if_9.html) that it contains accesses its parent (this file) and removes
+ // 'allow-scripts' and then triggers a reload.
+ // The document should not be able to run a script and access its parent (this file).
+
+ // passes if good
+ // 8) a document in an iframe with sandbox='allow-scripts' should have a different null
+ // principal in its original document than a document to which it navigates itself
+ // file_iframe_sandbox_d_if_10.html does this, co-ordinating with this page via postMessage
+
+ // passes if good
+ // 9) a document (file_iframe_sandbox_d_if11.html in an iframe (if_11) with sandbox='allow-scripts'
+ // is navigated to file_iframe_sandbox_d_if12.html - when that document loads
+ // a message is sent back to this document, which adds 'allow-same-origin' to if_11 and then
+ // calls .back on it - file_iframe_sandbox_if12.html should be able to call back into this
+ // document - this is all contained in file_iframe_sandbox_d_if13.html which is opened in another
+ // tab so it has its own isolated session history
+ window.open("file_iframe_sandbox_d_if13.html");
+
+ // open up the top navigation tests
+
+ // fails if bad
+ // 10) iframe with sandbox='allow-scripts' can NOT navigate top
+ // file_iframe_sandbox_e_if1.html contains file_iframe_sandbox_e_if6.html which
+ // attempts to navigate top
+ windowsToClose.push(window.open("file_iframe_sandbox_e_if1.html"));
+
+ // fails if bad
+ // 11) iframe with sandbox='allow-scripts' nested inside iframe with
+ // 'allow-top-navigation allow-scripts' can NOT navigate top
+ // file_iframe_sandbox_e_if2.html contains file_iframe_sandbox_e_if1.html which
+ // contains file_iframe_sandbox_e_if6.html which attempts to navigate top
+ windowsToClose.push(window.open("file_iframe_sandbox_e_if2.html"));
+
+ // passes if good
+ // 12) iframe with sandbox='allow-top-navigation allow-scripts' can navigate top
+ // file_iframe_sandbox_e_if3.html contains file_iframe_sandbox_e_if5.html which navigates top
+ window.open("file_iframe_sandbox_e_if3.html");
+
+ // passes if good
+ // 13) iframe with sandbox='allow-top-navigation allow-scripts' nested inside an iframe with
+ // 'allow-top-navigation allow-scripts' can navigate top
+ // file_iframe_sandbox_e_if4.html contains file_iframe_sandbox_e_if3.html which contains
+ // file_iframe_sandbox_e_if5.html which navigates top
+ window.open("file_iframe_sandbox_e_if4.html");
+}
+
+addLoadEvent(doTest);
+
+window.modified_if_8 = false;
+
+function reload_if_8() {
+ var if_8 = document.getElementById('if_8');
+ if_8.src = 'file_iframe_sandbox_d_if8.html';
+}
+
+function modify_if_8() {
+ // If this is the second time this has been called
+ // that's a failed test (allow-same-origin was removed
+ // the first time).
+ if (window.modified_if_8) {
+ ok_wrapper(false, "a sandboxed iframe from which 'allow-same-origin' was removed should not be able to access its parent");
+
+ // need to return here since we end up in an infinite loop otherwise
+ return;
+ }
+
+ var if_8 = document.getElementById('if_8');
+ window.modified_if_8 = true;
+
+ if_8.sandbox = 'allow-scripts';
+ testAttempted();
+ sendMouseEvent({type:'click'}, 'a_button');
+}
+
+window.modified_if_9 = false;
+
+function reload_if_9() {
+ var if_9 = document.getElementById('if_9');
+ if_9.src = 'file_iframe_sandbox_d_if9.html';
+}
+
+function modify_if_9() {
+ // If this is the second time this has been called
+ // that's a failed test (allow-scripts was removed
+ // the first time).
+ if (window.modified_if_9) {
+ ok_wrapper(false, "an sandboxed iframe from which 'allow-scripts' should be removed should not be able to access its parent via a script", false);
+
+ // need to return here since we end up in an infinite loop otherwise
+ return;
+ }
+
+ var if_9 = document.getElementById('if_9');
+ window.modified_if_9 = true;
+
+ if_9.sandbox = 'allow-same-origin';
+
+ testAttempted();
+ sendMouseEvent({type:'click'}, 'a_button2');
+}
+
+var firstPrincipal = "";
+var secondPrincipal;
+
+function doIf10TestPart1() {
+ if (firstPrincipal != "")
+ return;
+
+ // use SpecialPowers to get the principal of if_10.
+ // NB: We stringify here and below because special-powers wrapping doesn't
+ // preserve identity.
+ var if_10 = document.getElementById('if_10');
+ firstPrincipal = SpecialPowers.wrap(if_10).contentDocument.nodePrincipal.origin;
+ if_10.src = 'file_iframe_sandbox_d_if10.html';
+}
+
+function doIf10TestPart2() {
+ var if_10 = document.getElementById('if_10');
+ // use SpecialPowers to get the principal of if_10
+ secondPrincipal = SpecialPowers.wrap(if_10).contentDocument.nodePrincipal.origin;
+ ok_wrapper(firstPrincipal != secondPrincipal, "documents should NOT have the same principal if they are sandboxed without" +
+ " allow-same-origin and the first document is navigated to the second");
+}
+</script>
+<body onunload="checkTestsFinished()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
+<p id="display"></p>
+<div id="content">
+<iframe sandbox="allow-scripts" id="if_1" src="file_iframe_sandbox_d_if1.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_2" src="file_iframe_sandbox_d_if2.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_3" src="file_iframe_sandbox_d_if3.html" height="10" width="10"></iframe>
+<iframe id="if_sibling" name="if_sibling" src="about:blank" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts allow-same-origin" id="if_5" src="file_iframe_sandbox_d_if5.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_6" src="file_iframe_sandbox_d_if6.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin allow-scripts" id="if_8" src="file_iframe_sandbox_d_if8.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin allow-scripts" id="if_9" src="file_iframe_sandbox_d_if9.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_10" src="file_iframe_sandbox_navigation_start.html" onload='doIf10TestPart1()' height="10" width="10"></iframe>
+</div>
+<input type='button' id="a_button" onclick='reload_if_8()'>
+<input type='button' id="a_button2" onclick='reload_if_9()'>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_navigation2.html b/dom/html/test/test_iframe_sandbox_navigation2.html
new file mode 100644
index 000000000..7982d913f
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_navigation2.html
@@ -0,0 +1,212 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=341604
+Implement HTML5 sandbox attribute for IFRAMEs
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604 - navigation</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/
+/** Navigation tests Part 2**/
+
+SimpleTest.expectAssertions(0);
+SimpleTest.requestLongerTimeout(2); // slow on Android
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+// a postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin'/other windows to communicate pass/fail back to this main page.
+// it expects to be called with an object like {ok: true/false, desc:
+// <description of the test> which it then forwards to ok()
+window.addEventListener("message", receiveMessage, false);
+
+var testPassesReceived = 0;
+
+function receiveMessage(event) {
+ switch (event.data.type) {
+ case "attempted":
+ testAttempted();
+ break;
+ case "ok":
+ ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
+ break;
+ default:
+ // allow for old style message
+ if (event.data.ok != undefined) {
+ ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
+ }
+ }
+}
+
+// Open windows for tests to attempt to navigate later.
+var windowsToClose = new Array();
+windowsToClose.push(window.open("about:blank", "window_to_navigate"));
+windowsToClose.push(window.open("about:blank", "window_to_navigate2"));
+var iframesWithWindowsToClose = new Array();
+
+var attemptedTests = 0;
+var passedTests = 0;
+var totalTestsToPass = 12;
+var totalTestsToAttempt = 15;
+
+function ok_wrapper(result, desc, addToAttempted = true) {
+ ok(result, desc);
+
+ if (result) {
+ passedTests++;
+ }
+
+ if (addToAttempted) {
+ testAttempted();
+ }
+}
+
+// Added so that tests that don't register unless they fail,
+// can at least notify that they've attempted to run.
+function testAttempted() {
+ attemptedTests++;
+ if (attemptedTests == totalTestsToAttempt) {
+ // Make sure all tests have had a chance to complete.
+ setTimeout(function() {finish();}, 1000);
+ }
+}
+
+var finishCalled = false;
+
+function finish() {
+ if (!finishCalled) {
+ finishCalled = true;
+ is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " navigation tests that should pass");
+
+ for (var i = 0; i < windowsToClose.length; i++) {
+ windowsToClose[i].close();
+ }
+
+ SimpleTest.finish();
+ }
+}
+
+function checkTestsFinished() {
+ // If our own finish() has not been called, probably failed due to a timeout, so close remaining windows.
+ if (!finishCalled) {
+ for (var i = 0; i < windowsToClose.length; i++) {
+ windowsToClose[i].close();
+ }
+ }
+}
+
+function doTest() {
+ // fails if bad
+ // 14) iframe with sandbox='allow-same-origin allow-scripts allow-top-navigation' should not
+ // be able to navigate another window (opened by another browsing context) using its name.
+ // file_iframe_sandbox_d_if14.html in if_14 attempts to navigate "window_to_navigate",
+ // which has been opened in preparation.
+
+ // fails if bad
+ // 15) iframe with sandbox='allow-scripts' should not be able to navigate top using its
+ // real name (instead of _top) as allow-top-navigation is not specified.
+ // file_iframe_sandbox_e_if7.html contains file_iframe_sandbox_e_if8.html, which
+ // attempts to navigate top by name.
+ windowsToClose.push(window.open("file_iframe_sandbox_e_if7.html"));
+
+ // fails if bad
+ // 16) iframe with sandbox='allow-same-origin allow-scripts allow-top-navigation' should not
+ // be able to use its parent's name (instead of _parent) to navigate it, when it is not top.
+ // (Note: this would apply to other ancestors that are not top as well.)
+ // file_iframe_sandbox_d_if15.html in if_15 contains file_iframe_sandbox_d_if16.html, which
+ // tries to navigate if_15 by its name (if_parent).
+
+ // passes if good, fails if bad
+ // 17) A sandboxed iframe is allowed to navigate itself using window.open().
+ // (Done by file_iframe_sandbox_d_if17.html which has 'allow-scripts' and navigates to
+ // file_iframe_sandbox_navigation_pass.html).
+
+ // passes if good, fails if bad
+ // 18) A sandboxed iframe is allowed to navigate its children with window.open(), even if
+ // they are sandboxed. (Done by file_iframe_sandbox_d_if18.html which has 'allow-scripts',
+ // it navigates a child iframe to file_iframe_sandbox_navigation_pass.html).
+
+ // passes if good, fails if bad
+ // 19) A sandboxed iframe is not allowed to navigate its ancestor with window.open().
+ // (Done by file_iframe_sandbox_d_if20.html contained within file_iframe_sandbox_d_if19.html,
+ // it attempts to navigate file_iframe_sandbox_d_if19.html to file_iframe_sandbox_navigation_fail.html).
+
+ // passes if good, fails if bad
+ // 20) iframe with sandbox='allow-same-origin allow-scripts allow-top-navigation' should not
+ // be able to navigate another window (opened by another browsing context) using window.open(..., "<name>").
+ // file_iframe_sandbox_d_if14.html in if_14 attempts to navigate "window_to_navigate2",
+ // which has been opened in preparation, using window.open(..., "window_to_navigate2").
+
+ // passes if good, fails if bad
+ // 21) iframe with sandbox='allow-same-origin allow-scripts allow-top-navigation' should not
+ // be able to use its parent's name (not _parent) to navigate it using window.open(), when it is not top.
+ // (Note: this would apply to other ancestors that are not top as well.)
+ // file_iframe_sandbox_d_if21.html in if_21 contains file_iframe_sandbox_d_if22.html, which
+ // tries to navigate if_21 by its name (if_parent2).
+
+ // passes if good, fails if bad
+ // 22) iframe with sandbox='allow-top-navigation allow-scripts' can navigate top with window.open().
+ // file_iframe_sandbox_e_if9.html contains file_iframe_sandbox_e_if11.html which navigates top.
+ window.open("file_iframe_sandbox_e_if9.html");
+
+ // passes if good, fails if bad
+ // 23) iframe with sandbox='allow-top-navigation allow-scripts' nested inside an iframe with
+ // 'allow-top-navigation allow-scripts' can navigate top, with window.open().
+ // file_iframe_sandbox_e_if10.html contains file_iframe_sandbox_e_if9.html which contains
+ // file_iframe_sandbox_e_if11.html which navigates top.
+ window.open("file_iframe_sandbox_e_if10.html");
+
+ // passes if good, fails if bad
+ // 24) iframe with sandbox='allow-scripts' can NOT navigate top with window.open().
+ // file_iframe_sandbox_e_if12.html contains file_iframe_sandbox_e_if14.html which navigates top.
+ window.open("file_iframe_sandbox_e_if12.html");
+
+ // passes if good, fails if bad
+ // 25) iframe with sandbox='allow-scripts' nested inside an iframe with
+ // 'allow-top-navigation allow-scripts' can NOT navigate top, with window.open(..., "_top").
+ // file_iframe_sandbox_e_if13.html contains file_iframe_sandbox_e_if12.html which contains
+ // file_iframe_sandbox_e_if14.html which navigates top.
+ window.open("file_iframe_sandbox_e_if13.html");
+
+ // passes if good, fails if bad
+ // 26) iframe with sandbox='allow-scripts' should not be able to navigate top using its real name
+ // (not with _top e.g. window.open(..., "topname")) as allow-top-navigation is not specified.
+ // file_iframe_sandbox_e_if15.html contains file_iframe_sandbox_e_if16.html, which
+ // attempts to navigate top by name using window.open().
+ window.open("file_iframe_sandbox_e_if15.html");
+
+ // passes if good
+ // 27) iframe with sandbox='allow-scripts allow-popups' should be able to
+ // navigate a window, that it has opened, using it's name.
+ // file_iframe_sandbox_d_if23.html in if_23 opens a window and then attempts
+ // to navigate it using it's name in the target of an anchor.
+ iframesWithWindowsToClose.push("if_23");
+
+ // passes if good, fails if bad
+ // 28) iframe with sandbox='allow-scripts allow-popups' should be able to
+ // navigate a window, that it has opened, using window.open(..., "<name>").
+ // file_iframe_sandbox_d_if23.html in if_23 opens a window and then attempts
+ // to navigate it using it's name in the target of window.open().
+}
+
+addLoadEvent(doTest);
+</script>
+<body onunload="checkTestsFinished()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
+<p id="display"></p>
+<div id="content">
+<iframe sandbox="allow-same-origin allow-scripts allow-top-navigation" id="if_14" src="file_iframe_sandbox_d_if14.html" height="10" width="10"></iframe>
+<iframe id="if_15" name="if_parent" src="file_iframe_sandbox_d_if15.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_17" src="file_iframe_sandbox_d_if17.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_18" src="file_iframe_sandbox_d_if18.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_19" src="file_iframe_sandbox_d_if19.html" height="10" width="10"></iframe>
+<iframe id="if_21" name="if_parent2" src="file_iframe_sandbox_d_if21.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts allow-popups" id="if_23" src="file_iframe_sandbox_d_if23.html" height="10" width="10"></iframe>
+</div>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_plugins.html b/dom/html/test/test_iframe_sandbox_plugins.html
new file mode 100644
index 000000000..a8c2bd21b
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_plugins.html
@@ -0,0 +1,141 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=341604
+Implement HTML5 sandbox attribute for IFRAMEs
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604 - plugins</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="plugin-utils.js"></script>
+ <script type="application/javascript">
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ </script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/
+/** Plugin tests **/
+SimpleTest.waitForExplicitFinish();
+
+function doTest() {
+ // 1) test that a plugin can't be loaded with <embed> inside a sandboxed <iframe>
+ // (done by file_iframe_sandbox_f_if1.html loaded in if1 below)
+ // 2) test that a plugin can't be loaded with <object> inside a sandboxed <iframe>
+ // (done by file_iframe_sandbox_f_if1.html loaded in if1 below)
+ // 3) test that plugin can't be loaded by a sandboxed <iframe> with src pointing to
+ // a document that is handled by a plugin (done by if_2 below)
+ // 4) test that when a plugin is loaded in an unsandboxed iframe, a sandbox attribute
+ // is then added to the iframe and the document containing the plugin is reloaded,
+ // the plugin does not load in the sandboxed iframe (done with if_3 below)
+ // 5) test that when when a sandboxed iframe's sandbox attribute is removed,
+ // and a new document is loaded into the iframe, the plugin loads
+ // (done with if_4 below)
+
+ // these are all handled by checking how many instances of the test plugin are loaded
+ // when this script runs as the onload handler - there should be two instances,
+ // initially the one loaded directly by this page itself, and the one loaded during
+ // test #4 above.
+ var p = document.getElementById('plugin1');
+ var if_1 = document.getElementById('if_1');
+ p.startWatchingInstanceCount();
+
+ if_1.src = 'file_iframe_sandbox_f_if1.html';
+}
+
+function if_1_load() {
+ var if_1 = document.getElementById('if_1');
+
+ if (if_1.src == "about:blank")
+ return;
+
+ // need to wait for plugin to load, if the test fails...
+ SimpleTest.executeSoon(if_1_continue);
+}
+
+function if_1_continue() {
+ // instance count should be 0 (tests #1 and #2 above)
+ var p = document.getElementById('plugin1');
+ is(p.getInstanceCount(), 0, "plugins should not be loaded via <object> or <embed> by a sandboxed iframe");
+
+ var if_2 = document.getElementById('if_2');
+ if_2.src = 'file_iframe_sandbox_f_if2.html';
+
+ SimpleTest.executeSoon(if_2_continue);
+}
+
+function if_2_continue() {
+ // instance count should be 0 (test #3 above)
+ var p = document.getElementById('plugin1');
+
+ is(p.getInstanceCount(), 0, "plugins should not be loaded via a document of a type that requires a plugin embedded in a sandboxed iframe");
+
+ SimpleTest.executeSoon(if_3_test);
+}
+
+function if_3_test() {
+ var if_3 = document.getElementById('if_3');
+ // add sandbox attribute
+ if_3.sandbox = '';
+ if_3.src = 'file_iframe_sandbox_f_if1.html';
+}
+
+function if_3_load() {
+ if (if_3.src == "about:blank")
+ return;
+
+ SimpleTest.executeSoon(if_3_continue);
+}
+
+function if_3_continue() {
+ var p = document.getElementById('plugin1');
+ is(p.getInstanceCount(), 0, "plugins should not be loaded when a sandbox attribute is added" +
+ "to an iframe and a document containing a plugin is then loaded into the iframe");
+
+ SimpleTest.executeSoon(if_4_test);
+}
+
+function if_4_test() {
+ var if_4 = document.getElementById('if_4');
+ // remove sandbox attribute
+ if_4.removeAttribute('sandbox');
+ if_4.src = 'file_iframe_sandbox_f_if1.html';
+}
+
+function if_4_load() {
+ if (if_4.src == "about:blank")
+ return;
+
+ SimpleTest.executeSoon(if_4_continue);
+}
+
+function if_4_continue() {
+ var p = document.getElementById('plugin1');
+ // there are 2 plugin instances in file_iframe_sandbox_if1.html loaded by
+ // if_1, they should successfully load.
+ is(p.getInstanceCount(), 2, "plugins should be loaded when a sandbox attribute is removed " +
+ "from an iframe and a document containing a plugin is then loaded into the iframe");
+
+ p.stopWatchingInstanceCount();
+ SimpleTest.executeSoon(finish_test);
+}
+
+function finish_test() {
+ SimpleTest.finish();
+}
+
+addLoadEvent(doTest);
+</script>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
+<p id="display"></p>
+<div id="content">
+<embed id="plugin1" type="application/x-test" width="200" height="200"></embed>
+<iframe id="if_1" sandbox='allow-same-origin' onLoad='if_1_load()' src="about:blank" height="400" width="400"></iframe>
+<iframe id="if_2" sandbox='allow-same-origin' src="about:blank" height="400" width="400"></iframe>
+<iframe id="if_3" src="about:blank" onload='if_3_load()' height="400" width="400"></iframe>
+<iframe id="if_4" sandbox='allow-same-origin' onload='if_4_load()' src="about:blank" height="400" width="400"></iframe>
+</div>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_popups.html b/dom/html/test/test_iframe_sandbox_popups.html
new file mode 100644
index 000000000..28094f2e6
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_popups.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=766282
+implement allow-popups directive for iframe sandbox
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 766282</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// a postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin' to communicate pass/fail back to this main page.
+// it expects to be called with an object like {ok: true/false, desc:
+// <description of the test> which it then forwards to ok()
+window.addEventListener("message", receiveMessage, false);
+
+function receiveMessage(event)
+{
+ ok_wrapper(event.data.ok, event.data.desc);
+}
+
+var completedTests = 0;
+var passedTests = 0;
+
+function ok_wrapper(result, desc) {
+ ok(result, desc);
+
+ completedTests++;
+
+ if (result) {
+ passedTests++;
+ }
+
+ if (completedTests == 3) {
+ is(passedTests, completedTests, "There are " + completedTests + " popups tests that should pass");
+ SimpleTest.finish();
+ }
+}
+
+function doTest() {
+ // passes if good
+ // 1) Test that a sandboxed iframe with "allow-popups" can open a new window using the target.attribute.
+ // This is done via file_iframe_sandbox_h_if1.html which is sandboxed with "allow-popups allow-scripts allow-same-origin".
+ // The window it attempts to open calls window.opener.ok(true, ...) and file_iframe_h_if1.html has an ok()
+ // function that calls window.parent.ok_wrapper.
+
+ // passes if good
+ // 2) Test that a sandboxed iframe with "allow-popups" can open a new window using window.open.
+ // This is done via file_iframe_sandbox_h_if1.html which is sandboxed with "allow-popups allow-scripts allow-same-origin".
+ // The window it attempts to open calls window.opener.ok(true, ...) and file_iframe_h_if1.html has an ok()
+ // function that calls window.parent.ok_wrapper.
+
+ // passes if good, fails if bad
+ // 3) Test that a sandboxed iframe with "allow-popups" can open a new window using the target.attribute
+ // for a non-existing browsing context (BC766282).
+ // This is done via file_iframe_sandbox_h_if1.html which is sandboxed with "allow-popups allow-scripts allow-same-origin".
+ // The window it attempts to open calls window.opener.ok(true, ...) and file_iframe_h_if1.html has an ok()
+ // function that calls window.parent.ok_wrapper.
+}
+
+addLoadEvent(doTest);
+
+</script>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=766282">Mozilla Bug 766282</a> - implement allow-popups directive for iframe sandbox
+<p id="display"></p>
+<div id="content">
+<iframe sandbox="allow-popups allow-same-origin allow-scripts" id="if1" src="file_iframe_sandbox_h_if1.html" height="10" width="10"></iframe>
+</div>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_popups_inheritance.html b/dom/html/test/test_iframe_sandbox_popups_inheritance.html
new file mode 100644
index 000000000..54afb56b2
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_popups_inheritance.html
@@ -0,0 +1,157 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=766282
+Implement HTML5 sandbox allow-popuos directive for IFRAMEs - inheritance tests
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 766282</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+
+<script type="application/javascript">
+
+SimpleTest.expectAssertions(0, 5);
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("untriaged");
+
+// A postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin' to communicate pass/fail back to this main page.
+window.addEventListener("message", receiveMessage, false);
+
+function receiveMessage(event) {
+ switch (event.data.type) {
+ case "attempted":
+ testAttempted();
+ break;
+ case "ok":
+ ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
+ break;
+ default:
+ // allow for old style message
+ if (event.data.ok != undefined) {
+ ok_wrapper(event.data.ok, event.data.desc, event.data.addToAttempted);
+ }
+ }
+}
+
+var iframesWithWindowsToClose = new Array();
+
+var attemptedTests = 0;
+var passedTests = 0;
+var totalTestsToPass = 15;
+var totalTestsToAttempt = 21;
+
+function ok_wrapper(result, desc, addToAttempted = true) {
+ ok(result, desc);
+
+ if (result) {
+ passedTests++;
+ }
+
+ if (addToAttempted) {
+ testAttempted();
+ }
+}
+
+// Added so that tests that don't register unless they fail,
+// can at least notify that they've attempted to run.
+function testAttempted() {
+ attemptedTests++;
+ if (attemptedTests == totalTestsToAttempt) {
+ // Make sure all tests have had a chance to complete.
+ setTimeout(function() {finish();}, 1000);
+ }
+}
+
+var finishCalled = false;
+
+function finish() {
+ if (!finishCalled) {
+ finishCalled = true;
+ is(passedTests, totalTestsToPass, "There are " + totalTestsToPass + " inheritance tests that should pass");
+
+ closeWindows();
+
+ SimpleTest.finish();
+ }
+}
+
+function checkTestsFinished() {
+ // If our own finish() has not been called, probably failed due to a timeout, so close remaining windows.
+ if (!finishCalled) {
+ closeWindows();
+ }
+}
+
+function closeWindows() {
+ for (var i = 0; i < iframesWithWindowsToClose.length; i++) {
+ document.getElementById(iframesWithWindowsToClose[i]).contentWindow.postMessage({type: "closeWindows"}, "*");
+ }
+}
+
+function doTest() {
+ // passes if good and fails if bad
+ // 1,2,3) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups
+ // allow-same-origin" should not have its origin sandbox flag set and be able to access document.cookie.
+ // (Done by file_iframe_sandbox_k_if5.html opened from file_iframe_sandbox_k_if4.html)
+ // This is repeated for 3 different ways of opening the window,
+ // see file_iframe_sandbox_k_if4.html for details.
+
+ // passes if good
+ // 4,5,6) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups
+ // allow-top-navigation" should not have its top-level navigation sandbox flag set and be able to
+ // navigate top. (Done by file_iframe_sandbox_k_if5.html (and if6) opened from
+ // file_iframe_sandbox_k_if4.html). This is repeated for 3 different ways of opening the window,
+ // see file_iframe_sandbox_k_if4.html for details.
+
+ // passes if good
+ // 7,8,9) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups
+ // all-forms" should not have its forms sandbox flag set and be able to submit forms.
+ // (Done by file_iframe_sandbox_k_if7.html opened from file_iframe_sandbox_k_if4.html)
+ // This is repeated for 3 different ways of opening the window,
+ // see file_iframe_sandbox_k_if4.html for details.
+
+ // passes if good
+ // 10,11,12) Make sure that the sandbox flags copied to a new browsing context are taken from the
+ // current active document not the browsing context (iframe / docShell).
+ // This is done by removing allow-same-origin and calling doSubOpens from file_iframe_sandbox_k_if8.html,
+ // which opens file_iframe_sandbox_k_if9.html in 3 different ways.
+ // It then navigates to file_iframe_sandbox_k_if1.html to run tests 13 - 21 below.
+ var if_8_1 = document.getElementById('if_8_1');
+ if_8_1.sandbox = 'allow-scripts allow-popups';
+ if_8_1.contentWindow.doSubOpens();
+
+ // passes if good and fails if bad
+ // 13,14,15) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups"
+ // should have its origin sandbox flag set and not be able to access document.cookie.
+ // This is done by file_iframe_sandbox_k_if8.html navigating to file_iframe_sandbox_k_if1.html
+ // after allow-same-origin has been removed from iframe if_8_1. file_iframe_sandbox_k_if1.html
+ // opens file_iframe_sandbox_k_if2.html in 3 different ways to perform the tests.
+ iframesWithWindowsToClose.push("if_8_1");
+
+ // fails if bad
+ // 16,17,18) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups"
+ // should have its forms sandbox flag set and not be able to submit forms.
+ // This is done by file_iframe_sandbox_k_if2.html, see test 10 for details of how this is opened.
+
+ // fails if bad
+ // 19,20,21) A window opened from inside an iframe that has sandbox = "allow-scripts allow-popups"
+ // should have its top-level navigation sandbox flag set and not be able to navigate top.
+ // This is done by file_iframe_sandbox_k_if2.html, see test 10 for details of how this is opened.
+}
+
+addLoadEvent(doTest);
+</script>
+
+<body onunload="checkTestsFinished()">
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=766282">Mozilla Bug 766282</a> - Implement HTML5 sandbox allow-popups directive for IFRAMEs
+<p id="display"></p>
+<div id="content">
+<iframe sandbox="allow-scripts allow-popups allow-same-origin allow-forms allow-top-navigation" id="if_4" src="file_iframe_sandbox_k_if4.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts allow-popups allow-same-origin" id="if_8_1" src="file_iframe_sandbox_k_if8.html" height="10" width="10"></iframe>
+</div>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_redirect.html b/dom/html/test/test_iframe_sandbox_redirect.html
new file mode 100644
index 000000000..5476a6d44
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_redirect.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=985135
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 985135</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 985135 **/
+ SimpleTest.waitForExplicitFinish();
+ addLoadEvent(function() {
+ try {
+ var doc = frames[0].document;
+ ok(false, "Should not be able to get the document");
+ isnot(doc.body.textContent.slice(0, -1), "I have been redirected",
+ "Should not happen");
+ SimpleTest.finish();
+ } catch (e) {
+ // Check that we got the right document
+ window.onmessage = function(event) {
+ is(event.data, "who are you? redirect target",
+ "Should get the message we expect");
+ SimpleTest.finish();
+ }
+
+ frames[0].postMessage("who are you?", "*");
+ }
+ });
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=985135">Mozilla Bug 985135</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+<iframe src="file_iframe_sandbox_redirect.html" sandbox="allow-scripts"></iframe>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_refresh.html b/dom/html/test/test_iframe_sandbox_refresh.html
new file mode 100644
index 000000000..770a4ba8f
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_refresh.html
@@ -0,0 +1,101 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1156059
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Tests for Bug 1156059</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ // Tests for Bug 1156059
+ // See ok messages in iframes for test cases.
+
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("We cannot detect when the sandbox blocks the META REFRESH, so we need to allow a reasonable amount of time for them to fail.");
+
+ var testCases = [
+ {
+ desc: "Meta refresh without allow-scripts should be ignored.",
+ numberOfLoads: 0,
+ numberOfLoadsExpected: 1
+ },
+ {
+ desc: "Meta refresh check should be case insensitive.",
+ numberOfLoads: 0,
+ numberOfLoadsExpected: 1
+ },
+ {
+ desc: "Meta refresh with allow-scripts should work.",
+ numberOfLoads: 0,
+ numberOfLoadsExpected: 2
+ },
+ {
+ desc: "Refresh HTTP headers should not be affected by sandbox.",
+ numberOfLoads: 0,
+ numberOfLoadsExpected: 2
+ }
+ ];
+
+ var totalLoads = 0;
+ var totalLoadsExpected = testCases.reduce(function(partialSum, testCase) {
+ return partialSum + testCase.numberOfLoadsExpected;
+ }, 0);
+
+ function processLoad(testCaseIndex) {
+ testCases[testCaseIndex].numberOfLoads++;
+
+ if (++totalLoads == totalLoadsExpected) {
+ // Give the tests that should block the refresh a bit of extra time to
+ // fail. The worst that could happen here is that we get a false pass.
+ window.setTimeout(processResults, 500);
+ }
+ }
+
+ function processResults() {
+ testCases.forEach(function(testCase, index) {
+ var msg = "Test Case " + index + ": " + testCase.desc;
+ is(testCase.numberOfLoads, testCase.numberOfLoadsExpected, msg);
+ });
+
+ SimpleTest.finish();
+ }
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1156059">Mozilla Bug 1156059</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+<iframe
+ onload="processLoad(0)"
+ srcdoc="<meta http-equiv='refresh' content='0; url=data:text/html,Refreshed'>"
+ sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-top-navigation"
+></iframe>
+
+<iframe
+ onload="processLoad(1)"
+ srcdoc="<meta http-equiv='rEfReSh' content='0; url=data:text/html,Refreshed'>"
+ sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-top-navigation"
+></iframe>
+
+<iframe
+ onload="processLoad(2)"
+ srcdoc="<meta http-equiv='refresh' content='0; url=data:text/html,Refreshed'>"
+ sandbox="allow-scripts"
+></iframe>
+
+<iframe
+ onload="processLoad(3)"
+ src="file_iframe_sandbox_refresh.html"
+ sandbox
+></iframe>
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_iframe_sandbox_same_origin.html b/dom/html/test/test_iframe_sandbox_same_origin.html
new file mode 100644
index 000000000..b924b9f20
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_same_origin.html
@@ -0,0 +1,108 @@
+\<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=341604
+Implement HTML5 sandbox attribute for IFRAMEs - same origin tests
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs **/
+/** Same Origin Tests **/
+
+SimpleTest.waitForExplicitFinish();
+
+var completedTests = 0;
+var passedTests = 0;
+
+function ok_wrapper(result, desc) {
+ ok(result, desc);
+
+ completedTests++;
+
+ if (result) {
+ passedTests++;
+ }
+
+ if (completedTests == 14) {
+ is(passedTests, completedTests, "There are " + completedTests + " same-origin tests that should pass");
+
+ SimpleTest.finish();
+ }
+}
+
+function receiveMessage(event)
+{
+ ok_wrapper(event.data.ok, event.data.desc);
+}
+
+// a postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin' to communicate pass/fail back to this main page.
+// it expects to be called with an object like {ok: true/false, desc:
+// <description of the test> which it then forwards to ok()
+window.addEventListener("message", receiveMessage, false);
+
+function doTest() {
+ // 1) test that we can't access an iframe sandboxed without "allow-same-origin"
+ var if_1 = document.getElementById("if_1");
+ try {
+ var b = if_1.contentDocument.body;
+ ok_wrapper(false, "accessing body of a sandboxed document should not be allowed");
+ } catch (err){
+ ok_wrapper(true, "accessing body of a sandboxed document should not be allowed");
+ }
+
+ // 2) test that we can access an iframe sandboxed with "allow-same-origin"
+ var if_2 = document.getElementById("if_2");
+
+ try {
+ var b = if_2.contentDocument.body;
+ ok_wrapper(true, "accessing body of a sandboxed document with allow-same-origin should be allowed");
+ } catch (err) {
+ ok_wrapper(false, "accessing body of a sandboxed document with allow-same-origin should be allowed");
+ }
+
+ // 3) test that a sandboxed iframe without 'allow-same-origin' cannot access its parent
+ // this is done by file_iframe_b_if3.html which has 'allow-scripts' but not 'allow-same-origin'
+
+ // 4) test that a sandboxed iframe with 'allow-same-origin' can access its parent
+ // this is done by file_iframe_b_if2.html which has 'allow-same-origin' and 'allow-scripts'
+
+ // 5) check that a sandboxed iframe with "allow-same-origin" can access document.cookie
+ // this is done by file_iframe_b_if2.html which has 'allow-same-origin' and 'allow-scripts'
+
+ // 6) check that a sandboxed iframe with "allow-same-origin" can access window.localStorage
+ // this is done by file_iframe_b_if2.html which has 'allow-same-origin' and 'allow-scripts'
+
+ // 7) check that a sandboxed iframe with "allow-same-origin" can access window.sessionStorage
+ // this is done by file_iframe_b_if2.html which has 'allow-same-origin' and 'allow-scripts'
+
+ // 8) check that a sandboxed iframe WITHOUT "allow-same-origin" can NOT access document.cookie
+ // this is done by file_iframe_b_if3.html which has 'allow-scripts' but not 'allow-same-origin'
+
+ // 9) check that a sandboxed iframe WITHOUT "allow-same-origin" can NOT access window.localStorage
+ // this is done by file_iframe_b_if3.html which has 'allow-scripts' but not 'allow-same-origin'
+
+ // 10) check that a sandboxed iframe WITHOUT "allow-same-origin" can NOT access window.sessionStorage
+ // this is done by file_iframe_b_if3.html which has 'allow-scripts' but not 'allow-same-origin'
+
+ // 11) check that XHR works normally in a sandboxed iframe with "allow-same-origin" and "allow-scripts"
+ // this is done by file_iframe_b_if2.html which has 'allow-same-origin' and 'allow-scripts'
+
+ // 12) check that XHR is blocked in a sandboxed iframe with "allow-scripts" but WITHOUT "allow-same-origin"
+ // this is done by file_iframe_b_if3.html which has 'allow-scripts' but not 'allow-same-origin'
+}
+addLoadEvent(doTest);
+</script>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
+<p id="display"></p>
+<div id="content">
+<iframe sandbox="" id="if_1" src="file_iframe_sandbox_b_if1.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-same-origin allow-scripts" id="if_2" src="file_iframe_sandbox_b_if2.html" height="10" width="10"></iframe>
+<iframe sandbox="allow-scripts" id="if_3" src="file_iframe_sandbox_b_if3.html" height="10" width="10"></iframe>
+</div>
diff --git a/dom/html/test/test_iframe_sandbox_workers.html b/dom/html/test/test_iframe_sandbox_workers.html
new file mode 100644
index 000000000..0737729da
--- /dev/null
+++ b/dom/html/test/test_iframe_sandbox_workers.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=341604
+Implement HTML5 sandbox attribute for IFRAMEs - tests for workers
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 341604</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+/** Test for Bug 341604 - Implement HTML5 sandbox attribute for IFRAMEs - test for workers **/
+
+SimpleTest.waitForExplicitFinish();
+
+// a postMessage handler that is used by sandboxed iframes without
+// 'allow-same-origin' to communicate pass/fail back to this main page.
+// it expects to be called with an object like {ok: true/false, desc:
+// <description of the test> which it then forwards to ok()
+window.addEventListener("message", receiveMessage, false);
+
+function receiveMessage(event)
+{
+ ok_wrapper(event.data.ok, event.data.desc);
+}
+
+var completedTests = 0;
+var passedTests = 0;
+
+function ok_wrapper(result, desc) {
+ ok(result, desc);
+
+ completedTests++;
+
+ if (result) {
+ passedTests++;
+ }
+
+ if (completedTests == 3) {
+ is(passedTests, 3, "There are 3 worker tests that should pass");
+ SimpleTest.finish();
+ }
+}
+
+function doTest() {
+ // passes if good
+ // 1) test that a worker in a sandboxed iframe with 'allow-scripts' can be loaded
+ // from a data: URI
+ // (done by file_iframe_sandbox_g_if1.html)
+
+ // passes if good
+ // 2) test that a worker in a sandboxed iframe with 'allow-scripts' can be loaded
+ // from a blob URI created by the sandboxed document itself
+ // (done by file_iframe_sandbox_g_if1.html)
+
+ // passes if good
+ // 3) test that a worker in a sandboxed iframe with 'allow-scripts' without
+ // 'allow-same-origin' cannot load a script via a relative URI
+ // (done by file_iframe_sandbox_g_if1.html)
+}
+
+addLoadEvent(doTest);
+</script>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=341604">Mozilla Bug 341604</a> - Implement HTML5 sandbox attribute for IFRAMEs
+<p id="display"></p>
+<div id="content">
+<iframe sandbox="allow-scripts" id="if_1" src="file_iframe_sandbox_g_if1.html" height="10" width="10"></iframe>
+</div>
+</body>
+</html>
diff --git a/dom/html/test/test_ignoreuserfocus.html b/dom/html/test/test_ignoreuserfocus.html
new file mode 100644
index 000000000..629790182
--- /dev/null
+++ b/dom/html/test/test_ignoreuserfocus.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML>
+<html>
+ <head>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ </head>
+ <body>
+ <script type="application/javascript;version=1.7">
+ "use strict";
+
+ SimpleTest.requestCompleteLog();
+ SimpleTest.waitForExplicitFinish();
+
+ // Copied from EventUtils.js, but we want *ToWindow methods.
+ function synthesizeMouseAtPoint(left, top, aEvent, aWindow) {
+ var utils = _getDOMWindowUtils(aWindow);
+ var defaultPrevented = false;
+ if (utils) {
+ var button = aEvent.button || 0;
+ var clickCount = aEvent.clickCount || 1;
+ var modifiers = _parseModifiers(aEvent);
+ var pressure = ("pressure" in aEvent) ? aEvent.pressure : 0;
+ var inputSource = ("inputSource" in aEvent) ? aEvent.inputSource : 0;
+
+ if (("type" in aEvent) && aEvent.type) {
+ defaultPrevented = utils.sendMouseEventToWindow(aEvent.type, left, top, button, clickCount, modifiers, false, pressure, inputSource);
+ }
+ else {
+ utils.sendMouseEventToWindow("mousedown", left, top, button, clickCount, modifiers, false, pressure, inputSource);
+ utils.sendMouseEventToWindow("mouseup", left, top, button, clickCount, modifiers, false, pressure, inputSource);
+ }
+ }
+ }
+
+ function runTest() {
+ var witness = document.createElement("input");
+ witness.setAttribute("type", "text");
+ var witness2 = document.createElement("input");
+ witness2.setAttribute("type", "text");
+
+ var iframe = document.createElement("iframe");
+ iframe.setAttribute("mozbrowser", "true");
+ iframe.setAttribute("ignoreuserfocus", "true");
+ iframe.setAttribute("height", "300px");
+
+ iframe.addEventListener('load', function (e) {
+ // Get privileged iframe because mozbrowser iframe is not same origin
+ // with the parent. We need to access its content through the wrapper.
+ var privilegedIframe = SpecialPowers.wrap(iframe);
+ privilegedIframe.contentWindow.addEventListener("MozAfterPaint", function afterPaint(e) {
+ privilegedIframe.contentWindow.removeEventListener("MozAfterPaint", afterPaint);
+
+ privilegedIframe.contentWindow.addEventListener("focus",
+ function(e) {
+ ok(!iframe.hasAttribute("ignoreuserfocus"), "Shouldn't get a focus event in ignoreuserfocus iframe!");
+ },
+ true);
+ privilegedIframe.contentWindow.addEventListener("blur",
+ function(e) {
+ ok(!iframe.hasAttribute("ignoreuserfocus"), "Shouldn't get a blur event in ignoreuserfocus iframe!");
+ },
+ true);
+
+ // Sanity check
+ witness.focus();
+ is(document.activeElement, witness, "witness should have the focus");
+
+ iframe.focus();
+ isnot(document.activeElement, iframe, "[explicit iframe.focus()] iframe should not get the focus");
+
+ iframe.removeAttribute("ignoreuserfocus");
+ iframe.focus();
+ is(document.activeElement, iframe, "[explicit iframe.focus()] iframe should get the focus");
+
+ iframe.setAttribute("ignoreuserfocus", "true");
+
+ // Test the case when iframe contains <input> and .focus()
+ // is called and explicit focus using mouse
+ witness.focus();
+
+ var innerInput = privilegedIframe.contentDocument.getElementsByTagName("input")[0];
+ innerInput.focus();
+ isnot(document.activeElement, iframe, "[explicit innerInput.focus()] iframe should not have the focus");
+
+ var iframeWindow = SpecialPowers.unwrap(privilegedIframe.contentWindow);
+ witness.focus();
+ synthesizeMouseAtCenter(innerInput, {}, iframeWindow);
+ is(document.activeElement, witness, "[synthesize mouse click] witness should have the focus");
+
+ // Test the case when iframe contains <iframe> and .focus()
+ // is called and explicit focus using mouse
+ witness.focus();
+
+ var innerIframe = privilegedIframe.contentDocument.getElementsByTagName("iframe")[0];
+ innerIframe.focus();
+ isnot(document.activeElement, iframe, "[explicit innerIframe.focus()] iframe should not have the focus");
+
+ witness.focus();
+ synthesizeMouseAtCenter(innerIframe, {}, iframeWindow);
+ is(document.activeElement, witness, "[synthesize mouse click inner iframe] witness should have the focus");
+
+ // Test the case when iframe contains <area> and .focus()
+ // is called and explicit focus using mouse
+
+ // Wait for paint to setup frame for area. Currently the area frame
+ // map is reset for each paint. If we are in the middle of a paint
+ // then the area will not be focusable.
+ privilegedIframe.contentWindow.addEventListener("MozAfterPaint", function afterPaintArea(e) {
+ privilegedIframe.contentWindow.removeEventListener("MozAfterPaint", afterPaintArea);
+ var innerArea = privilegedIframe.contentDocument.getElementsByTagName("area")[0];
+ innerArea.focus();
+ isnot(document.activeElement, iframe, "[explicit innerArea.focus()] iframe should not have the focus");
+
+ witness.focus();
+ synthesizeMouseAtCenter(innerArea, {}, iframeWindow);
+ is(document.activeElement, witness, "[synthesize mouse click] witness should have the focus");
+
+ // Test tabindex
+ witness.focus();
+ is(document.activeElement, witness, "witness should have the focus");
+ synthesizeKey("VK_TAB", {});
+ isnot(document.activeElement, iframe, "[synthesize tab key] iframe should not have the focus");
+ is(document.activeElement, witness2, "witness2 should have the focus");
+
+ SimpleTest.finish();
+ });
+ witness.focus();
+ // force reflow
+ iframe.setAttribute("height", "298px");
+ });
+ // force reflow
+ iframe.setAttribute("height", "299px");
+ });
+
+ document.body.appendChild(witness);
+ document.body.appendChild(iframe);
+ document.body.appendChild(witness2);
+
+ iframe.setAttribute("src", "file_ignoreuserfocus.html");
+ }
+ addEventListener("load", function() {
+ SpecialPowers.pushPermissions(
+ [{'type': 'browser', 'allow': true, 'context': document}],
+ function() {
+ SpecialPowers.pushPrefEnv({
+ "set": [
+ ["dom.mozBrowserFramesEnabled", true],
+ ["network.disable.ipc.security", true],
+ ]
+ }, function() {
+ SimpleTest.waitForFocus(runTest);
+ });
+ });
+ });
+ </script>
+ </body>
+</html>
diff --git a/dom/html/test/test_imageSrcSet.html b/dom/html/test/test_imageSrcSet.html
new file mode 100644
index 000000000..adbea1676
--- /dev/null
+++ b/dom/html/test/test_imageSrcSet.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=980243
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 980243</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 980243 **/
+ SimpleTest.waitForExplicitFinish();
+
+ addLoadEvent(function() {
+ var img = document.querySelector("img");
+ img.onload = function() {
+ ok(true, "Reached here");
+ SimpleTest.finish();
+ }
+ // If ths spec ever changes to treat .src sets differently from
+ // setAttribute("src"), we'll need some sort of canonicalization step
+ // earlier to make the attr value an absolute URI.
+ img.setAttribute("src", img.getAttribute("src"));
+ });
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=980243">Mozilla Bug 980243</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <img src="file_formSubmission_img.jpg">
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_image_clone_load.html b/dom/html/test/test_image_clone_load.html
new file mode 100644
index 000000000..e808c80a5
--- /dev/null
+++ b/dom/html/test/test_image_clone_load.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Test for image clones doing their load</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+var t = async_test("The clone of an image should do the load of the same image, and do it synchronously");
+t.step(function() {
+ var img = new Image();
+ img.onload = t.step_func(function() {
+ var clone = img.cloneNode();
+ assert_not_equals(img.naturalWidth, 0, "Should have a width");
+ assert_equals(clone.naturalWidth, img.naturalWidth,
+ "Clone should have a width too");
+ // And make sure the clone fires onload too, which happens async.
+ clone.onload = function() { t.done() }
+ });
+ img.src = "image.png";
+});
+</script>
diff --git a/dom/html/test/test_img_attributes_reflection.html b/dom/html/test/test_img_attributes_reflection.html
new file mode 100644
index 000000000..c40865a86
--- /dev/null
+++ b/dom/html/test/test_img_attributes_reflection.html
@@ -0,0 +1,103 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLImageElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+/** Test for HTMLImageElement attributes reflection **/
+
+reflectString({
+ element: document.createElement("img"),
+ attribute: "alt",
+})
+
+reflectURL({
+ element: document.createElement("img"),
+ attribute: "src",
+})
+
+reflectString({
+ element: document.createElement("img"),
+ attribute: "srcset",
+})
+
+reflectLimitedEnumerated({
+ element: document.createElement("img"),
+ attribute: "crossOrigin",
+ // "" is a valid value per spec, but gets mapped to the "anonymous" state,
+ // just like invalid values, so just list it under invalidValues
+ validValues: [ "anonymous", "use-credentials" ],
+ invalidValues: [
+ "", " aNOnYmous ", " UsE-CreDEntIALS ", "foobar", "FOOBAR", " fOoBaR "
+ ],
+ defaultValue: { invalid: "anonymous", missing: null },
+ nullable: true,
+})
+
+reflectString({
+ element: document.createElement("img"),
+ attribute: "useMap",
+})
+
+reflectBoolean({
+ element: document.createElement("img"),
+ attribute: "isMap",
+})
+
+ok("width" in document.createElement("img"), "img.width is present")
+ok("height" in document.createElement("img"), "img.height is present")
+ok("naturalWidth" in document.createElement("img"), "img.naturalWidth is present")
+ok("naturalHeight" in document.createElement("img"), "img.naturalHeight is present")
+ok("complete" in document.createElement("img"), "img.complete is present")
+
+reflectString({
+ element: document.createElement("img"),
+ attribute: "name",
+})
+
+reflectString({
+ element: document.createElement("img"),
+ attribute: "align",
+})
+
+reflectUnsignedInt({
+ element: document.createElement("img"),
+ attribute: "hspace",
+})
+
+reflectUnsignedInt({
+ element: document.createElement("img"),
+ attribute: "vspace",
+})
+
+reflectURL({
+ element: document.createElement("img"),
+ attribute: "longDesc",
+})
+
+reflectString({
+ element: document.createElement("img"),
+ attribute: "border",
+ extendedAttributes: { TreatNullAs: "EmptyString" },
+})
+
+reflectURL({
+ element: document.createElement("img"),
+ attribute: "lowsrc",
+})
+
+ok("x" in document.createElement("img"), "img.x is present")
+ok("y" in document.createElement("img"), "img.y is present")
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_imports_basics.html b/dom/html/test/test_imports_basics.html
new file mode 100644
index 000000000..3bdd96152
--- /dev/null
+++ b/dom/html/test/test_imports_basics.html
@@ -0,0 +1,68 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=877072
+-->
+<head>
+ <title>Test for Bug 877072</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=877072">Mozilla Bug 877072</a>
+
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var loadEventFired = false;
+ var errorEventFired = false;
+ var counter = 0;
+ function loaded() {
+ loadEventFired = true;
+ }
+ function failed() {
+ errorEventFired = true;
+ }
+ </script>
+
+ <link rel="import" href="file_imports_basics.html" id="import1" onload="loaded()" onerror="failed()"></link>
+
+ <script type="text/javascript">
+ ok(importDone, "Script of the imported document runned before this script");
+ ok(loadEventFired, "Load eventhandler works");
+ ok(!errorEventFired, "There were no error event fired");
+
+ var import1 = document.getElementById("import1").import;
+ is(import1.getElementById("foo").textContent, "bar",
+ "import property of link import works");
+
+ try{
+ import1.open();
+ import1.write("<h1>This should not show up!</h1>");
+ import1.close();
+ } catch (e) {
+ ok(true, "import.open/write should throw");
+ }
+
+ // Let's add dynamically a new link import with the same URI
+ var link = document.createElement("link");
+ link.setAttribute("id", "inserted");
+ link.setAttribute("rel", "import");
+ link.setAttribute("href", "file_imports_basics.html");
+ function loaded2() {
+ ok(true, "Load event is fired for link import that refers to an already loaded import");
+ is(counter, 1, "Adding another link referring to the same import, does not load it twice");
+ is(document.getElementById("inserted").import.getElementById("foo").textContent, "bar",
+ "import property of dynamic link import works");
+ SimpleTest.finish();
+ };
+ link.setAttribute("onload", "loaded2()");
+ function failed2() {
+ ok(false, "You should not reach this code");
+ SimpleTest.finish();
+ };
+ link.setAttribute("onerror", "failed2()");
+ document.body.appendChild(link);
+ </script>
+</body>
+</html> \ No newline at end of file
diff --git a/dom/html/test/test_imports_nested.html b/dom/html/test/test_imports_nested.html
new file mode 100644
index 000000000..518e5b741
--- /dev/null
+++ b/dom/html/test/test_imports_nested.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=877072
+-->
+<head>
+ <title>Test for Bug 877072</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=877072">Mozilla Bug 877072</a>
+
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var counter = 0;
+ var fcounter = 0;
+ var order = [];
+ function loaded() {
+ counter++;
+ }
+ function failed() {
+ fcounter++;
+ }
+ </script>
+
+ <link rel="import" href="imports/file_importA1.html" id="A1" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="imports/file_importB1.html" id="B1" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="imports/file_importB2.html" id="B2_2" onload="loaded()" onerror="failed()"></link>
+
+ <script type="text/javascript">
+ is(counter, 5, "Imports are loaded");
+ is(fcounter, 0, "No error in imports");
+ var expected = ["A2", "A1", "B2", "B1"];
+ for (i in expected)
+ is(order[i], expected[i], "import " + i + " should be " + expected[i]);
+ SimpleTest.finish();
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/test_imports_nested_2.html b/dom/html/test/test_imports_nested_2.html
new file mode 100644
index 000000000..8e8e57d68
--- /dev/null
+++ b/dom/html/test/test_imports_nested_2.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=877072
+-->
+<head>
+ <title>Test for Bug 877072</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=877072">Mozilla Bug 877072</a>
+
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var counter = 0;
+ var fcounter = 0;
+ var order = [];
+ function loaded() {
+ counter++;
+ }
+ function failed() {
+ fcounter++;
+ }
+ </script>
+
+<!--
+
+Master -> c1 -> ... -> C10
+| | |
+| - - -> D |
+| ^ |
+| | |
+ - - - -> E < - - - - - -
+
+This test is for testing ImportLoader::UpdateDependants.Because of the long
+chain to C10, it's very likely that C10->E will be the last edge the ImportLoaders
+find. At that point it won't only have to update E but also its subimport D.
+
+-->
+
+ <link rel="import" href="imports/file_importC1.html" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="imports/file_importD.html" onload="loaded()" onerror="failed()"></link>
+ <link rel="import" href="imports/file_importE.html" onload="loaded()" onerror="failed()"></link>
+
+ <script type="text/javascript">
+ is(counter, 14, "Imports are loaded"); // 12 imports but 14 link imports...
+ is(fcounter, 0, "No error in imports");
+ var expected = ["D", "E", "C10", "C9", "C8", "C7", "C6", "C5", "C4", "C3", "C2", "C1"];
+ for (i in expected)
+ is(order[i], expected[i], "import " + i + " should be " + expected[i]);
+ SimpleTest.finish();
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/test_imports_nonhttp.html b/dom/html/test/test_imports_nonhttp.html
new file mode 100644
index 000000000..7a5620599
--- /dev/null
+++ b/dom/html/test/test_imports_nonhttp.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1016875
+-->
+<head>
+ <title>Test for Bug 1016875</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1016875">Mozilla Bug 1016875</a>
+
+ <script type="text/javascript">
+ //<![CDATA[
+ SimpleTest.waitForExplicitFinish();
+ var counter = 0;
+ function loaded() {
+ if ( counter++ == 1 ) {
+ ok(document.getElementById("import1").import.getElementById("div1"),
+ "import document was loaded");
+ ok(document.getElementById("import2").import.getElementById("div1"),
+ "import document was loaded");
+ SimpleTest.finish();
+ }
+ }
+ function failed() {
+ ok(false, "Import should not have failed")
+ SimpleTest.finish();
+ }
+ var link = document.createElement("link");
+ link.setAttribute("id", "import1");
+ link.setAttribute("rel", "import");
+ var stringDoc = "<!DOCTYPE html><html><body><div id='div1'></div></body></html>";
+ var encoded = btoa(stringDoc);
+ var dataurl = "data:text/html;base64," + encoded;
+ link.setAttribute("href", dataurl);
+ link.onload = loaded;
+ link.onerror = failed;
+ document.body.appendChild(link);
+
+ var link = document.createElement("link");
+ link.setAttribute("id", "import2");
+ link.setAttribute("rel", "import");
+ var blob = new Blob([stringDoc], {type : 'text/html'});
+ var objectURL = URL.createObjectURL(blob);
+ link.setAttribute("href", objectURL);
+ link.onload = loaded;
+ link.onerror = failed;
+ document.body.appendChild(link);
+ //]]>
+ </script>
+
+</body>
+</html>
diff --git a/dom/html/test/test_imports_redirect.html b/dom/html/test/test_imports_redirect.html
new file mode 100644
index 000000000..d780476cf
--- /dev/null
+++ b/dom/html/test/test_imports_redirect.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1016875
+-->
+<head>
+ <title>Test for Bug 1016875</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
+</head>
+<body>
+ <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1016875">Mozilla Bug 1016875</a>
+
+ <script type="text/javascript">
+ SimpleTest.waitForExplicitFinish();
+ var loadEventFired = false;
+ var errorEventFired = false;
+ var counter = 0;
+ function loaded() {
+ loadEventFired = true;
+ }
+ function failed() {
+ errorEventFired = true;
+ }
+ </script>
+
+ <link rel="import" href="http://mochi.test:8888/tests/dom/html/test/file_imports_redirect.html" id="import" onload="loaded()" onerror="failed()"></link>
+
+ <script type="text/javascript">
+ ok(loadEventFired, "Load event was fired");
+ ok(!errorEventFired, "Error event was not fired, redirection worked");
+ ok(redirected, "Script of the target of redirection was executed");
+
+ SimpleTest.finish();
+ </script>
+
+</body>
+</html>
diff --git a/dom/html/test/test_input_files_not_nsIFile.html b/dom/html/test/test_input_files_not_nsIFile.html
new file mode 100644
index 000000000..a52afac7c
--- /dev/null
+++ b/dom/html/test/test_input_files_not_nsIFile.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for &lt;input type='file'&gt; handling when its "files" do not implement nsIFile</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<div id="content">
+ <input id='a' type='file'>
+</div>
+<button id='b' onclick="document.getElementById('a').click();">Show Filepicker</button>
+
+<input type="file" id="file" />
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+var MockFilePicker = SpecialPowers.MockFilePicker;
+MockFilePicker.init(window);
+
+SimpleTest.waitForFocus(function() {
+ MockFilePicker.useBlobFile();
+ MockFilePicker.returnValue = MockFilePicker.returnOK;
+
+ var b = document.getElementById('b');
+ b.focus(); // Be sure the element is visible.
+
+ document.getElementById('a').addEventListener("change", function(aEvent) {
+ ok(true, "change event correctly sent");
+
+ SimpleTest.executeSoon(function() {
+ MockFilePicker.cleanup();
+ SimpleTest.finish();
+ });
+ }, false);
+
+ b.click();
+});
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/html/test/test_li_attributes_reflection.html b/dom/html/test/test_li_attributes_reflection.html
new file mode 100644
index 000000000..b6fcd7581
--- /dev/null
+++ b/dom/html/test/test_li_attributes_reflection.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLLIElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLLIElement attributes reflection **/
+
+// .value
+reflectInt({
+ element: document.createElement("li"),
+ attribute: "value",
+ nonNegative: false,
+});
+
+// .type
+reflectString({
+ element: document.createElement("li"),
+ attribute: "type"
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_link_attributes_reflection.html b/dom/html/test/test_link_attributes_reflection.html
new file mode 100644
index 000000000..db092f0ef
--- /dev/null
+++ b/dom/html/test/test_link_attributes_reflection.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLLinkElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLLinkElement attributes reflection **/
+
+// .href (URL)
+reflectURL({
+ element: document.createElement("link"),
+ attribute: "href",
+});
+
+// .crossOrigin (String or null)
+reflectLimitedEnumerated({
+ element: document.createElement("link"),
+ attribute: "crossOrigin",
+ // "" is a valid value per spec, but gets mapped to the "anonymous" state,
+ // just like invalid values, so just list it under invalidValues
+ validValues: [ "anonymous", "use-credentials" ],
+ invalidValues: [
+ "", " aNOnYmous ", " UsE-CreDEntIALS ", "foobar", "FOOBAR", " fOoBaR "
+ ],
+ defaultValue: { invalid: "anonymous", missing: null },
+ nullable: true,
+})
+
+// .rel (String)
+reflectString({
+ element: document.createElement("link"),
+ attribute: "rel",
+});
+
+// .media (String)
+reflectString({
+ element: document.createElement("link"),
+ attribute: "media",
+});
+
+// .hreflang (String)
+reflectString({
+ element: document.createElement("link"),
+ attribute: "hreflang",
+});
+
+// .type (String)
+reflectString({
+ element: document.createElement("link"),
+ attribute: "type",
+});
+
+
+// .charset (String)
+reflectString({
+ element: document.createElement("link"),
+ attribute: "charset",
+});
+
+// .rev (String)
+reflectString({
+ element: document.createElement("link"),
+ attribute: "rev",
+});
+
+// .target (String)
+reflectString({
+ element: document.createElement("link"),
+ attribute: "target",
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_link_sizes.html b/dom/html/test/test_link_sizes.html
new file mode 100644
index 000000000..b24274888
--- /dev/null
+++ b/dom/html/test/test_link_sizes.html
@@ -0,0 +1,35 @@
+<!doctype html>
+<html>
+<head>
+<title>Test link.sizes attribute</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" sizes="16x16 24x24 32x32 48x48">
+</head>
+<body>
+
+<pre id="test">
+<script>
+
+ var links = document.getElementsByTagName('link');
+ for (var i = 0; i < links.length; ++i) {
+ var link = links[i];
+ ok("sizes" in link, "link.sizes exists");
+
+ if (link.rel == 'shortcut icon') {
+ is(link.sizes.value, "16x16 24x24 32x32 48x48", 'link.sizes.value correct value');
+ is(link.sizes.length, 4, 'link.sizes.length correct value');
+ ok(link.sizes.contains('32x32'), 'link.sizes.contains() works');
+ link.sizes.add('64x64');
+ is(link.sizes.length, 5, 'link.sizes.length correct value');
+ link.sizes.remove('64x64');
+ is(link.sizes.length, 4, 'link.sizes.length correct value');
+ is(link.sizes + "", "16x16 24x24 32x32 48x48", 'link.sizes stringify correct value');
+ } else {
+ is(link.sizes.value, "", 'link.sizes correct value');
+ }
+ }
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_map_attributes_reflection.html b/dom/html/test/test_map_attributes_reflection.html
new file mode 100644
index 000000000..710dce669
--- /dev/null
+++ b/dom/html/test/test_map_attributes_reflection.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLMapElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLMapElement attributes reflection **/
+
+// .name (String)
+reflectString({
+ element: document.createElement("map"),
+ attribute: "name",
+})
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_meta_attributes_reflection.html b/dom/html/test/test_meta_attributes_reflection.html
new file mode 100644
index 000000000..c21d53587
--- /dev/null
+++ b/dom/html/test/test_meta_attributes_reflection.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLMetaElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLMetaElement attributes reflection **/
+
+// .name (String)
+reflectString({
+ element: document.createElement("meta"),
+ attribute: "name",
+})
+
+// .httpEquiv (String)
+reflectString({
+ element: document.createElement("meta"),
+ attribute: { content: "http-equiv", idl: "httpEquiv" },
+})
+
+// .content (String)
+reflectString({
+ element: document.createElement("meta"),
+ attribute: "content",
+})
+
+// .scheme (String)
+reflectString({
+ element: document.createElement("meta"),
+ attribute: "scheme",
+})
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_mod_attributes_reflection.html b/dom/html/test/test_mod_attributes_reflection.html
new file mode 100644
index 000000000..94313bc63
--- /dev/null
+++ b/dom/html/test/test_mod_attributes_reflection.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLModElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLModElement attributes reflection **/
+
+// .cite (URL)
+reflectURL({
+ element: document.createElement("ins"),
+ attribute: "cite",
+})
+reflectURL({
+ element: document.createElement("del"),
+ attribute: "cite",
+})
+
+// .dateTime (String)
+reflectString({
+ element: document.createElement("ins"),
+ attribute: "dateTime",
+})
+reflectString({
+ element: document.createElement("del"),
+ attribute: "dateTime",
+})
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_mozaudiochannel.html b/dom/html/test/test_mozaudiochannel.html
new file mode 100644
index 000000000..722e181bf
--- /dev/null
+++ b/dom/html/test/test_mozaudiochannel.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for mozaudiochannel</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+
+<pre id="test">
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["media.useAudioChannelAPI", true]]}, function() {
+ var ifr = document.createElement('iframe');
+ ifr.src = 'file_mozaudiochannel.html';
+ onmessage = function(e) {
+ if ("finish" in e.data) {
+ SimpleTest.finish();
+ } else {
+ ok(e.data.status, e.data.msg);
+ }
+ }
+
+ document.body.appendChild(ifr);
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_named_options.html b/dom/html/test/test_named_options.html
new file mode 100644
index 000000000..b6e84a9f2
--- /dev/null
+++ b/dom/html/test/test_named_options.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=772869
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 772869</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772869">Mozilla Bug 772869</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <select id="s">
+ <option name="x"></option>
+ <option name="y" id="z"></option>
+ <option name="z" id="x"></option>
+ <option id="w"></option>
+ </select>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 772869 **/
+var opt = $("s").options;
+opt.loopy = "something"
+var names = Object.getOwnPropertyNames(opt);
+is(names.length, 9, "Should have nine entries");
+is(names[0], "0", "Entry 1")
+is(names[1], "1", "Entry 2")
+is(names[2], "2", "Entry 3")
+is(names[3], "3", "Entry 4")
+is(names[4], "x", "Entry 5")
+is(names[5], "y", "Entry 6")
+is(names[6], "z", "Entry 7")
+is(names[7], "w", "Entry 8")
+is(names[8], "loopy", "Entry 9")
+
+var names2 = [];
+for (var name in opt) {
+ names2.push(name);
+}
+is(names2.length, 11, "Should have eleven enumerated names");
+is(names2[0], "0", "Enum entry 1")
+is(names2[1], "1", "Enum entry 2")
+is(names2[2], "2", "Enum entry 3")
+is(names2[3], "3", "Enum entry 4")
+is(names2[4], "loopy", "Enum entry 5")
+is(names2[5], "add", "Enum entrry 6")
+is(names2[6], "remove", "Enum entry 7")
+is(names2[7], "length", "Enum entry 8")
+is(names2[8], "selectedIndex", "Enum entry 9")
+is(names2[9], "item", "Enum entry 10")
+is(names2[10], "namedItem", "Enum entry 11")
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_nested_invalid_fieldsets.html b/dom/html/test/test_nested_invalid_fieldsets.html
new file mode 100644
index 000000000..42413baa9
--- /dev/null
+++ b/dom/html/test/test_nested_invalid_fieldsets.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=914029
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 914029</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+ <script type="application/javascript">
+
+ /** Test for Bug 914029 **/
+
+ var innerFieldset = document.createElement("fieldset");
+ var outerFieldset = document.createElement("fieldset");
+ var textarea = document.createElement("textarea");
+ textarea.setAttribute("required", "");
+ innerFieldset.appendChild(textarea);
+ outerFieldset.appendChild(innerFieldset);
+ SpecialPowers.forceGC();
+ ok(true, "This page did not crash - dynamically added nested invalid fieldsets" +
+ " work correctly.");
+ var innerFieldset = document.createElement("fieldset");
+ var outerFieldset = document.createElement("fieldset");
+ var textarea = document.createElement("textarea");
+ var textarea2 = document.createElement("textarea");
+ textarea.setAttribute("required", "");
+ innerFieldset.appendChild(textarea);
+ innerFieldset.appendChild(textarea2);
+ outerFieldset.appendChild(innerFieldset);
+ SpecialPowers.forceGC();
+ ok(true, "This page did not crash - dynamically added nested invalid fieldsets" +
+ " work correctly.");
+
+ </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=914029">Mozilla Bug 914029</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_non-ascii-cookie.html b/dom/html/test/test_non-ascii-cookie.html
new file mode 100644
index 000000000..ab96ac07c
--- /dev/null
+++ b/dom/html/test/test_non-ascii-cookie.html
@@ -0,0 +1,60 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=784367
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for non-ASCII cookie values</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=784367">Mozilla Bug 784367</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for non-ASCII cookie values **/
+
+SimpleTest.waitForExplicitFinish();
+
+var gScript = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL("file_cookiemanager.js"));
+
+function getCookieFromManager() {
+ return new Promise(resolve => {
+ gScript.addMessageListener("getCookieFromManager:return", function gcfm({ cookie }) {
+ gScript.removeMessageListener("getCookieFromManager:return", gcfm);
+ resolve(cookie);
+ });
+ gScript.sendAsyncMessage("getCookieFromManager", { host: location.hostname, path: location.pathname });
+ });
+}
+
+var c = document.cookie;
+is(document.cookie, 'abc=012©ABC\ufffdDEF', "document.cookie should be decoded as UTF-8");
+
+var newCookie;
+
+getCookieFromManager().then((cookie) => {
+ is(cookie, document.cookie, "nsICookieManager should be consistent with document.cookie");
+ newCookie = 'def=∼≩≭≧∯≳≲≣∽≸≸∺≸∠≯≮≥≲≲≯≲∽≡≬≥≲≴∨∱∩∾';
+ document.cookie = newCookie;
+ is(document.cookie, c + '; ' + newCookie, "document.cookie should be encoded as UTF-8");
+
+ return getCookieFromManager();
+}).then((cookie) => {
+ is(cookie, document.cookie, "nsICookieManager should be consistent with document.cookie");
+ var date1 = new Date();
+ date1.setTime(0);
+ document.cookie = newCookie + 'def=;expires=' + date1.toGMTString();
+ gScript.destroy();
+ SimpleTest.finish();
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_non-ascii-cookie.html^headers^ b/dom/html/test/test_non-ascii-cookie.html^headers^
new file mode 100644
index 000000000..54aa6c3e7
--- /dev/null
+++ b/dom/html/test/test_non-ascii-cookie.html^headers^
@@ -0,0 +1 @@
+Set-Cookie: abc=012©ABC©DEF
diff --git a/dom/html/test/test_object_attributes_reflection.html b/dom/html/test/test_object_attributes_reflection.html
new file mode 100644
index 000000000..40978e582
--- /dev/null
+++ b/dom/html/test/test_object_attributes_reflection.html
@@ -0,0 +1,117 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLObjectElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLObjectElement attributes reflection **/
+
+// .data (URL)
+reflectURL({
+ element: document.createElement("object"),
+ attribute: "data",
+});
+
+// .type (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "type",
+});
+
+// .name (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "name",
+});
+
+// .useMap (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "useMap",
+});
+
+// .width (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "width",
+});
+
+// .height (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "height",
+});
+
+// .align (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "align",
+});
+
+// .archive (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "archive",
+});
+
+// .code (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "code",
+});
+
+// .declare (String)
+reflectBoolean({
+ element: document.createElement("object"),
+ attribute: "declare",
+});
+
+// .hspace (unsigned int)
+reflectUnsignedInt({
+ element: document.createElement("object"),
+ attribute: "hspace",
+});
+
+// .standby (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "standby",
+});
+
+// .vspace (unsigned int)
+reflectUnsignedInt({
+ element: document.createElement("object"),
+ attribute: "vspace",
+});
+
+// .codeBase (URL)
+reflectURL({
+ element: document.createElement("object"),
+ attribute: "codeBase",
+});
+
+// .codeType (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "codeType",
+});
+
+// .border (String)
+reflectString({
+ element: document.createElement("object"),
+ attribute: "border",
+ extendedAttributes: { TreatNullAs: "EmptyString" },
+});
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_object_plugin_nav.html b/dom/html/test/test_object_plugin_nav.html
new file mode 100644
index 000000000..91590e51a
--- /dev/null
+++ b/dom/html/test/test_object_plugin_nav.html
@@ -0,0 +1,99 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=720130
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 720130</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <script type="application/javascript" src="plugin-utils.js"></script>
+ <script type="application/javascript">
+ setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED);
+ </script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=720130">Mozilla Bug 720130</a>
+<p id="display"></p>
+<div id="content">
+ <input>
+ <object type="application/x-test"></object>
+ <button>foo</button>
+ <object tabindex='0' type="application/x-test"></object>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 720130 **/
+
+var gFocusCount = 0;
+var gFocusNb = 4;
+
+/**
+ * Check the focus navigation.
+ */
+function checkFocus() {
+ switch (gFocusCount) {
+ case 0:
+ is(document.activeElement, document.getElementsByTagName('a')[0],
+ "first focused element should be the link");
+ break;
+ case 1:
+ is(document.activeElement, document.getElementsByTagName('input')[0],
+ "second focused element should be the text field");
+ break;
+ case 2:
+ is(document.activeElement, document.getElementsByTagName('button')[0],
+ "third focused element should be the button");
+ break;
+ case 3:
+ is(document.activeElement, document.getElementsByTagName('object')[1],
+ "fourth focused element should be the object");
+ break;
+ }
+
+ gFocusCount++;
+}
+
+SimpleTest.waitForExplicitFinish();
+
+function doTest() {
+ is(document.activeElement, document.body);
+
+ // Preliminary check: tabindex should be -1 on the object.
+ is(document.getElementsByTagName('object')[0].tabIndex, -1,
+ "the plugin shouldn't get focus while navigating in the document");
+
+ document.addEventListener("focus", function() {
+ checkFocus();
+
+ if (gFocusCount != gFocusNb) {
+ synthesizeKey("VK_TAB", {});
+ return;
+ }
+
+ document.removeEventListener("focus", arguments.callee, true);
+
+ // Just make sure that .focus() still works.
+ var o = document.getElementsByTagName('object')[0];
+ o.onfocus = function() {
+ SimpleTest.finish();
+ o.onfocus = null;
+ };
+ o.focus();
+ }, true);
+
+ synthesizeKey("VK_TAB", {});
+}
+
+SimpleTest.waitForFocus(function () {
+ // Set the focus model so that links are focusable by the tab key even on Mac
+ SpecialPowers.pushPrefEnv({'set': [['accessibility.tabfocus', 7]]}, doTest);
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_ol_attributes_reflection.html b/dom/html/test/test_ol_attributes_reflection.html
new file mode 100644
index 000000000..819ef60e4
--- /dev/null
+++ b/dom/html/test/test_ol_attributes_reflection.html
@@ -0,0 +1,65 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLOLElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLOLElement attributes reflection **/
+
+// .reversed (boolean)
+reflectBoolean({
+ element: document.createElement("ol"),
+ attribute: "reversed",
+})
+
+// .start
+reflectInt({
+ element: document.createElement("ol"),
+ attribute: "start",
+ nonNegative: false,
+ defaultValue: 1,
+});
+
+// .type
+reflectString({
+ element: document.createElement("ol"),
+ attribute: "type"
+});
+
+// .compact
+reflectBoolean({
+ element: document.createElement("ol"),
+ attribute: "compact",
+})
+
+// Additional tests for ol.start behavior when li elements are added
+var ol = document.createElement("ol");
+var li = document.createElement("li");
+li.value = 42;
+ol.appendChild(li);
+is(ol.start, 1, "ol.start with one li child, li.value = 42:");
+li.value = -42;
+is(ol.start, 1, "ol.start with one li child, li.value = 42:");
+ol.removeAttribute("start");
+li.removeAttribute("value");
+ol.appendChild(document.createElement("li"));
+ol.reversed = true;
+todo_is(ol.start, 2, "ol.start with two li children, ol.reversed == true:");
+li.value = 42;
+todo_is(ol.start, 2, "ol.start with two li childern, ol.reversed == true:");
+ol.start = 42;
+is(ol.start, 42, "ol.start = 42:");
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_option_defaultSelected.html b/dom/html/test/test_option_defaultSelected.html
new file mode 100644
index 000000000..f3994e784
--- /dev/null
+++ b/dom/html/test/test_option_defaultSelected.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=927796
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 927796</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=927796">Mozilla Bug 927796</a>
+<p id="display">
+<select id="s1">
+ <option selected>one</option>
+ <option>two</option>
+</select>
+<select id="s2" size="5">
+ <option selected>one</option>
+ <option>two</option>
+</select>
+</p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+ <script type="application/javascript">
+
+ /** Test for Bug 927796 **/
+ var s1 = $("s1");
+ s1.options[0].defaultSelected = false;
+ is(s1.options[0].selected, true,
+ "First option in combobox should still be selected");
+ is(s1.options[1].selected, false,
+ "Second option in combobox should not be selected");
+
+ var s2 = $("s2");
+ s2.options[0].defaultSelected = false;
+ is(s2.options[0].selected, false,
+ "First option in listbox should not be selected");
+ is(s2.options[1].selected, false,
+ "Second option in listbox should not be selected");
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/test_option_selected_state.html b/dom/html/test/test_option_selected_state.html
new file mode 100644
index 000000000..ba4a1a330
--- /dev/null
+++ b/dom/html/test/test_option_selected_state.html
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=942648
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 942648</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=942648">Mozilla Bug 942648</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+ <select>
+ <option value="1">1</option>
+ <option id="e1" value="2">2</option>
+ </select>
+ <select>
+ <option value="1">1</option>
+ <option id="e2" selected value="2">2</option>
+ </select>
+ <select>
+ <option value="1">1</option>
+ <option id="e3" selected="" value="2">2</option>
+ </select>
+ <select>
+ <option value="1">1</option>
+ <option id="e4" selected="selected" value="2">2</option>
+ </select>
+</pre>
+ <script type="application/javascript">
+
+ /** Test for Bug 942648 **/
+SimpleTest.waitForExplicitFinish();
+ window.onload = function() {
+ var e1 = document.getElementById('e1');
+ var e2 = document.getElementById('e2');
+ var e3 = document.getElementById('e3');
+ var e4 = document.getElementById('e4');
+ ok(!e1.selected, "e1 should not be selected");
+ ok(e2.selected, "e2 should be selected");
+ ok(e3.selected, "e3 should be selected");
+ ok(e4.selected, "e4 should be selected");
+ e1.setAttribute('selected', 'selected');
+ e2.setAttribute('selected', 'selected');
+ e3.setAttribute('selected', 'selected');
+ e4.setAttribute('selected', 'selected');
+ ok(e1.selected, "e1 should now be selected");
+ ok(e2.selected, "e2 should still be selected");
+ ok(e3.selected, "e3 should still be selected");
+ ok(e4.selected, "e4 should still be selected");
+ SimpleTest.finish();
+ };
+ </script>
+</body>
+</html>
diff --git a/dom/html/test/test_param_attributes_reflection.html b/dom/html/test/test_param_attributes_reflection.html
new file mode 100644
index 000000000..05d7949d5
--- /dev/null
+++ b/dom/html/test/test_param_attributes_reflection.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLParamElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLParamElement attributes reflection **/
+
+// .name
+reflectString({
+ element: document.createElement("param"),
+ attribute: "name",
+});
+
+// .value
+reflectString({
+ element: document.createElement("param"),
+ attribute: "value"
+});
+
+// .type
+reflectString({
+ element: document.createElement("param"),
+ attribute: "type"
+});
+
+// .valueType
+reflectString({
+ element: document.createElement("param"),
+ attribute: "valueType"
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_plugin.tst b/dom/html/test/test_plugin.tst
new file mode 100644
index 000000000..323fae03f
--- /dev/null
+++ b/dom/html/test/test_plugin.tst
@@ -0,0 +1 @@
+foobar
diff --git a/dom/html/test/test_q_attributes_reflection.html b/dom/html/test/test_q_attributes_reflection.html
new file mode 100644
index 000000000..ddb6c77d9
--- /dev/null
+++ b/dom/html/test/test_q_attributes_reflection.html
@@ -0,0 +1,32 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLQuoteElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLQuoteElement attributes reflection **/
+
+// .cite
+reflectURL({
+ element: document.createElement("q"),
+ attribute: "cite",
+});
+
+reflectURL({
+ element: document.createElement("blockquote"),
+ attribute: "cite",
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_restore_from_parser_fragment.html b/dom/html/test/test_restore_from_parser_fragment.html
new file mode 100644
index 000000000..119ee2102
--- /dev/null
+++ b/dom/html/test/test_restore_from_parser_fragment.html
@@ -0,0 +1,59 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=644959
+-->
+<head>
+ <title>Test for Bug 644959</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=644959">Mozilla Bug 644959</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 644959 **/
+
+var content = document.getElementById('content');
+
+function appendHTML(aParent, aElementString)
+{
+ aParent.innerHTML = "<form>" + aElementString + "</form>";
+}
+
+function clearHTML(aParent)
+{
+ aParent.innerHTML = "";
+}
+
+var tests = [
+ [ "button", "<button></button>" ],
+ [ "input", "<input>" ],
+ [ "textarea", "<textarea></textarea>" ],
+ [ "select", "<select></select>" ],
+];
+
+var element = null;
+
+for (var test of tests) {
+ appendHTML(content, test[1]);
+ element = content.getElementsByTagName(test[0])[0];
+ is(element.disabled, false, "element shouldn't be disabled");
+ element.disabled = true;
+ is(element.disabled, true, "element should be disabled");
+
+ clearHTML(content);
+
+ appendHTML(content, test[1]);
+ element = content.getElementsByTagName(test[0])[0];
+ is(element.disabled, false, "element shouldn't be disabled");
+}
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_rowscollection.html b/dom/html/test/test_rowscollection.html
new file mode 100644
index 000000000..7a726b8a8
--- /dev/null
+++ b/dom/html/test/test_rowscollection.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=772869
+-->
+<head>
+ <meta charset="utf-8">
+ <title>Test for Bug 772869</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=772869">Mozilla Bug 772869</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+ <table id="f">
+ <thead>
+ <tr id="x"></tr>
+ </thead>
+ <tfoot>
+ <tr id="z"></tr>
+ <tr id="w"></tr>
+ </tfoot>
+ <tr id="x"></tr>
+ <tr id="y"></tr>
+ <tbody>
+ <tr id="z"></tr>
+ </tbody>
+ </table>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 772869 **/
+var x = $("f").rows;
+x.something = "another";
+var names = [];
+for (var name in x) {
+ names.push(name);
+}
+is(names.length, 10, "Should have 10 enumerated names");
+is(names[0], "0", "Enum entry 1")
+is(names[1], "1", "Enum entry 2")
+is(names[2], "2", "Enum entry 3")
+is(names[3], "3", "Enum entry 4")
+is(names[4], "4", "Enum entry 5")
+is(names[5], "5", "Enum entry 6")
+is(names[6], "something", "Enum entry 7")
+is(names[7], "item", "Enum entry 8")
+is(names[8], "namedItem", "Enum entry 9")
+is(names[9], "length", "Enum entry 10");
+
+names = Object.getOwnPropertyNames(x);
+is(names.length, 11, "Should have 11 items");
+is(names[0], "0", "Entry 1")
+is(names[1], "1", "Entry 2")
+is(names[2], "2", "Entry 3")
+is(names[3], "3", "Entry 4")
+is(names[4], "4", "Entry 5")
+is(names[5], "5", "Entry 6")
+is(names[6], "x", "Entry 7")
+is(names[7], "y", "Entry 8")
+is(names[8], "z", "Entry 9")
+is(names[9], "w", "Entry 10")
+is(names[10], "something", "Entry 11")
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_srcdoc-2.html b/dom/html/test/test_srcdoc-2.html
new file mode 100644
index 000000000..4e273473b
--- /dev/null
+++ b/dom/html/test/test_srcdoc-2.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=802895
+-->
+ <head>
+<title>Test session history for srcdoc iframes introduced in bug 802895</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=802895">Mozilla Bug 802895</a>
+
+<iframe id="pframe" name="pframe" src="file_srcdoc-2.html"></iframe>
+<pre id="test">
+<script>
+
+ SimpleTest.waitForExplicitFinish();
+ var pframe = $("pframe");
+
+ //disable bfcache
+ pframe.contentWindow.addEventListener("unload", function () { }, false);
+
+ var loadState = 0;
+ pframe.onload = function () {
+ SimpleTest.executeSoon(function () {
+
+ var pDoc = pframe.contentDocument;
+
+ if (loadState == 0) {
+ var div = pDoc.createElement("div");
+ div.id = "modifyCheck";
+ div.innerHTML = "hello again";
+ pDoc.body.appendChild(div);
+ ok(pDoc.getElementById("modifyCheck"), "Child element not created");
+ pframe.src = "about:blank";
+ loadState = 1;
+ }
+ else if (loadState == 1) {
+ loadState = 2;
+ window.history.back();
+ }
+ else if (loadState == 2) {
+ ok(!pDoc.getElementById("modifyCheck"), "modifyCheck element shouldn't be present");
+ is(pDoc.getElementById("iframe").contentDocument.body.innerHTML,
+ "Hello World", "srcdoc iframe not present");
+ SimpleTest.finish();
+ }
+
+ })
+ };
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_srcdoc.html b/dom/html/test/test_srcdoc.html
new file mode 100644
index 000000000..f7e48fde9
--- /dev/null
+++ b/dom/html/test/test_srcdoc.html
@@ -0,0 +1,118 @@
+<!doctype html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=802895
+-->
+ <head>
+<title>Tests for srcdoc iframes introduced in bug 802895</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=802895">Mozilla Bug 802895</a>
+
+<iframe id="pframe" src="file_srcdoc.html"></iframe>
+
+<pre id="test">
+<script>
+
+ SimpleTest.waitForExplicitFinish();
+ SimpleTest.requestFlakyTimeout("untriaged");
+ var pframe = $("pframe");
+
+ var loadState = 0;
+ pframe.contentWindow.addEventListener("load", function () {
+
+ var pframeDoc = pframe.contentDocument;
+
+ var iframe = pframeDoc.getElementById("iframe");
+ var innerDoc = iframe.contentDocument;
+ var iframe1 = pframeDoc.getElementById("iframe1");
+ var innerDoc1 = iframe1.contentDocument;
+
+ var finish = false;
+ var finish1 = false;
+ var finish3 = false;
+
+
+
+ is(iframe.srcdoc, "Hello World", "Bad srcdoc attribute contents")
+
+ is(innerDoc.domain, document.domain, "Wrong domain");
+ is(innerDoc.referrer, pframeDoc.referrer, "Wrong referrer");
+ is(innerDoc.body.innerHTML, "Hello World", "Wrong body");
+ is(innerDoc.compatMode, "CSS1Compat", "Not standards compliant");
+
+ is(innerDoc1.domain, document.domain, "Wrong domain with src attribute");
+ is(innerDoc1.referrer, pframeDoc.referrer, "Wrong referrer with src attribute");
+ is(innerDoc1.body.innerHTML, "Goodbye World", "Wrong body with src attribute")
+ is(innerDoc1.compatMode, "CSS1Compat", "Not standards compliant with src attribute");
+
+ var iframe2 = pframeDoc.getElementById("iframe2");
+ var innerDoc2 = iframe2.contentDocument;
+ try {
+ innerDoc2.domain;
+ foundError = false;
+ }
+ catch (error) {
+ foundError = true;
+ }
+ ok(foundError, "srcdoc iframe not sandboxed");
+
+ //Test changed srcdoc attribute
+ iframe.onload = function () {
+
+ iframe = pframeDoc.getElementById("iframe");
+ innerDoc = iframe.contentDocument;
+
+ is(iframe.srcdoc, "Hello again", "Bad srcdoc attribute contents with srcdoc attribute changed");
+ is(innerDoc.domain, document.domain, "Wrong domain with srcdoc attribute changed");
+ is(innerDoc.referrer, pframeDoc.referrer, "Wrong referrer with srcdoc attribute changed");
+ is(innerDoc.body.innerHTML, "Hello again", "Wrong body with srcdoc attribute changed");
+ is(innerDoc.compatMode, "CSS1Compat", "Not standards compliant with srcdoc attribute changed");
+
+ finish = true;
+ if (finish && finish1 && finish3) {
+ SimpleTest.finish();
+ }
+ };
+
+ iframe.srcdoc = "Hello again";
+
+ var iframe3 = pframeDoc.getElementById("iframe3");
+
+ // Test srcdoc attribute removal
+ iframe3.onload = function () {
+ var innerDoc3 = iframe3.contentDocument;
+ is(innerDoc3.body.innerHTML, "Gone", "Bad srcdoc attribute removal");
+ finish3 = true;
+ if (finish && finish1 && finish3) {
+ SimpleTest.finish();
+ }
+ }
+
+ iframe3.removeAttribute("srcdoc");
+
+
+ var iframe1load = false;
+ iframe1.onload = function () {
+ iframe1load = true;
+ }
+
+ iframe1.src = "data:text/plain;charset=US-ASCII,Goodbyeeee";
+
+ // Need to test that changing the src doesn't change the iframe.
+ setTimeout(function () {
+ ok(!iframe1load, "Changing src attribute shouldn't cause a load when srcdoc is set");
+ finish1 = true;
+ if (finish && finish1 && finish3) {
+ SimpleTest.finish();
+ }
+ }, 2000);
+
+ }, false);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_style_attributes_reflection.html b/dom/html/test/test_style_attributes_reflection.html
new file mode 100644
index 000000000..c97bc8767
--- /dev/null
+++ b/dom/html/test/test_style_attributes_reflection.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Test for HTMLStyleElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLStyleElement attributes reflection **/
+
+var e = document.createElement("style");
+
+// .media
+reflectString({
+ element: e,
+ attribute: "media"
+});
+
+// .type
+reflectString({
+ element: e,
+ attribute: "type"
+});
+
+// .scoped
+reflectBoolean({
+ element: e,
+ attribute: "scoped"
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_track.html b/dom/html/test/test_track.html
new file mode 100644
index 000000000..bc23e4dae
--- /dev/null
+++ b/dom/html/test/test_track.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=833386
+-->
+<head>
+ <meta charset='utf-8'>
+ <title>Test for Bug 833386 - HTMLTrackElement</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/dom/html/test/reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+reflectLimitedEnumerated({
+ element: document.createElement("track"),
+ attribute: "kind",
+ validValues: ["subtitles", "captions", "descriptions", "chapters",
+ "metadata"],
+ invalidValues: ["foo", "bar", "\u0000", "null", "", "subtitle", "caption",
+ "description", "chapter", "meta"],
+ defaultValue: { missing: "subtitles", invalid: "metadata" },
+});
+
+// Default attribute
+reflectBoolean({
+ element: document.createElement("track"),
+ attribute: "default"
+});
+
+// Label attribute
+reflectString({
+ element: document.createElement("track"),
+ attribute: "label",
+ otherValues: [ "foo", "BAR", "_FoO", "\u0000", "null", "white space" ]
+});
+
+// Source attribute
+reflectURL({
+ element: document.createElement("track"),
+ attribute: "src",
+ otherValues: ["foo", "bar", "\u0000", "null", ""]
+});
+
+// Source Language attribute
+reflectString({
+ element: document.createElement("track"),
+ attribute: "srclang",
+ otherValues: ["foo", "bar", "\u0000", "null", ""]
+});
+
+var track = document.createElement("track");
+is(track.readyState, 0, "Default ready state should be 0 (NONE).");
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_ul_attributes_reflection.html b/dom/html/test/test_ul_attributes_reflection.html
new file mode 100644
index 000000000..7696a4f9f
--- /dev/null
+++ b/dom/html/test/test_ul_attributes_reflection.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for HTMLUListElement attributes reflection</title>
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="reflect.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for HTMLUListElement attributes reflection **/
+
+// .compact
+reflectBoolean({
+ element: document.createElement("ul"),
+ attribute: "compact"
+});
+
+// .type
+reflectString({
+ element: document.createElement("ul"),
+ attribute: "type"
+});
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_video_wakelock.html b/dom/html/test/test_video_wakelock.html
new file mode 100644
index 000000000..52b05cda4
--- /dev/null
+++ b/dom/html/test/test_video_wakelock.html
@@ -0,0 +1,198 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=868943
+-->
+<head>
+ <title>Test for Bug 868943</title>
+ <script type="application/javascript" src="/MochiKit/packed.js"></script>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=868943">Mozilla Bug 868943</a>
+<p id="display"></p>
+<div id="content">
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 868943 **/
+
+function testVideoPlayPause() {
+ info("#1 testVideoPlayPause");
+
+ var lockState_cpu = true;
+ var lockState_screen = true;
+ var count_cpu = 0;
+ var count_screen = 0;
+
+ var content = document.getElementById('content');
+
+ var video = document.createElement('video');
+ ok(video.mozUseScreenWakeLock, "#1 Video element uses screen wake lock by default");
+ video.src = "wakelock.ogv";
+ content.appendChild(video);
+
+ var startDate;
+ function testVideoPlayPauseListener(topic, state) {
+ info("#1 topic=" + topic + ", state=" + state);
+
+ var locked = state == "locked-foreground" ||
+ state == "locked-background";
+
+ if (topic == "cpu") {
+ is(locked, lockState_cpu, "#1 Video element locked the cpu");
+ count_cpu++;
+ } else if (topic == "screen") {
+ is(locked, lockState_screen, "#1 Video element locked the screen");
+ count_screen++;
+ }
+
+ if (count_cpu == 1 && count_screen == 1) {
+ info("#1 Both cpu and screen are locked");
+ // The next step is to unlock the resource.
+ lockState_cpu = false;
+ lockState_screen = false;
+ video.pause();
+ startDate = new Date();
+ }
+
+ if (count_cpu == 2 && count_screen == 2) {
+ var diffDate = (new Date() - startDate);
+ ok(diffDate > 200, "#1 There was at least 200 milliseconds between the stop and the wakelock release");
+
+ content.removeChild(video);
+ navigator.mozPower.removeWakeLockListener(testVideoPlayPauseListener);
+ runTests();
+ }
+ }
+
+ navigator.mozPower.addWakeLockListener(testVideoPlayPauseListener);
+ video.play();
+}
+
+function testVideoPlay() {
+ info("#2 testVideoPlay");
+
+ var lockState_cpu = true;
+ var lockState_screen = true;
+ var count_cpu = 0;
+ var count_screen = 0;
+
+ var content = document.getElementById('content');
+
+ var video = document.createElement('video');
+ ok(video.mozUseScreenWakeLock, "#2 Video element uses screen wake lock by default");
+ video.src = "wakelock.ogv";
+ content.appendChild(video);
+
+ var startDate;
+ video.addEventListener('progress', function() {
+ startDate = new Date();
+ });
+
+ function testVideoPlayListener(topic, state) {
+ info("#2 topic=" + topic + ", state=" + state);
+
+ var locked = state == "locked-foreground" ||
+ state == "locked-background";
+
+ if (topic == "cpu") {
+ is(locked, lockState_cpu, "#2 Video element locked the cpu");
+ count_cpu++;
+ } else if (topic == "screen") {
+ is(locked, lockState_screen, "#2 Video element locked the screen");
+ count_screen++;
+ }
+
+ if (count_cpu == 1 && count_screen == 1) {
+ info("#2 Both cpu and screen are locked");
+ // The next step is to unlock the resource.
+ lockState_cpu = false;
+ lockState_screen = false;
+ } else if (count_cpu == 2 && count_screen == 2) {
+ var diffDate = (new Date() - startDate);
+ ok(diffDate > 200, "#2 There was at least milliseconds between the stop and the wakelock release");
+
+ content.removeChild(video);
+ navigator.mozPower.removeWakeLockListener(testVideoPlayListener);
+ runTests();
+ }
+ }
+
+ navigator.mozPower.addWakeLockListener(testVideoPlayListener);
+ video.play();
+}
+
+function testVideoNoScreenWakeLock() {
+ info("#3 testVideoNoScreenWakeLock");
+
+ var lockState_cpu = true;
+ var lockState_screen = false;
+ var count_cpu = 0;
+
+ var content = document.getElementById('content');
+
+ var video = document.createElement('video');
+ video.mozUseScreenWakeLock = false;
+ video.src = "wakelock.ogv";
+ content.appendChild(video);
+
+ var startDate;
+ function testVideoNoScreenWakeLockListener(topic, state) {
+ info("#3 topic=" + topic + ", state=" + state);
+
+ var locked = state == "locked-foreground" ||
+ state == "locked-background";
+
+ if (topic == "cpu") {
+ is(locked, lockState_cpu, "#3 Video element locked the cpu");
+ count_cpu++;
+ } else if (topic == "screen") {
+ is(locked, lockState_screen, "#3 Video element locked the screen");
+ }
+
+ if (count_cpu == 1) {
+ info("#3 Cpu is locked");
+ // The next step is to unlock the resource.
+ lockState_cpu = false;
+ video.pause();
+ startDate = new Date();
+ }
+
+ if (count_cpu == 2) {
+ var diffDate = (new Date() - startDate);
+ ok(diffDate > 200, "#3 There was at least 200 milliseconds between the stop and the wakelock release");
+
+ content.removeChild(video);
+ navigator.mozPower.removeWakeLockListener(testVideoNoScreenWakeLockListener);
+ runTests();
+ }
+ }
+
+ navigator.mozPower.addWakeLockListener(testVideoNoScreenWakeLockListener);
+ video.play();
+}
+
+var tests = [ testVideoPlayPause, testVideoPlay, testVideoNoScreenWakeLock ];
+function runTests() {
+ if (!tests.length) {
+ SimpleTest.finish();
+ return;
+ }
+
+ var test = tests.pop();
+ test();
+};
+
+SpecialPowers.pushPrefEnv({"set": [["media.wakelock_timeout", 500],
+ ["dom.wakelock.enabled", true]]}, runTests);
+
+SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_viewport.html b/dom/html/test/test_viewport.html
new file mode 100644
index 000000000..2299bef3d
--- /dev/null
+++ b/dom/html/test/test_viewport.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=436083
+-->
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <meta name="viewport" content="height=398, width=4224, minimum-scale=0.1,
+ initial-scale=2.3, maximum-scale=45.2, user-scalable=no">
+ <title>Test for Viewport META Tag Parsing</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank"
+href="https://bugzilla.mozilla.org/show_bug.cgi?id=436083">Mozilla Bug 436083</a>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Viewport META Tag **/
+
+SimpleTest.waitForExplicitFinish();
+
+function testViewport() {
+
+ /* We need to access the document headers, which are chrome-only. */
+
+ /* Grab Viewport Metadata from the document header. */
+ var windowUtils = SpecialPowers.getDOMWindowUtils(window);
+ var vpWidth =
+ parseInt(windowUtils.getDocumentMetadata("viewport-width"));
+ var vpHeight =
+ parseInt(windowUtils.getDocumentMetadata("viewport-height"));
+ var vpInitialScale =
+ parseFloat(windowUtils.getDocumentMetadata("viewport-initial-scale"));
+ var vpMaxScale =
+ parseFloat(windowUtils.getDocumentMetadata("viewport-maximum-scale"));
+ var vpMinScale =
+ parseFloat(windowUtils.getDocumentMetadata("viewport-minimum-scale"));
+ var vpUserScalable =
+ windowUtils.getDocumentMetadata("viewport-user-scalable");
+
+ is(vpWidth, 4224, "Should get proper width");
+ is(vpHeight, 398, "Should get proper height");
+ is(vpInitialScale, 2.3, "Should get proper initial scale");
+ is(vpMaxScale, 45.2, "Should get proper max scale");
+ is(vpMinScale, 0.1, "Should get proper min scale");
+ is(vpUserScalable, "no", "Should get proper user scalable parameter");
+}
+
+addLoadEvent(testViewport);
+addLoadEvent(SimpleTest.finish);
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_viewport_resize.html b/dom/html/test/test_viewport_resize.html
new file mode 100644
index 000000000..711d2afa0
--- /dev/null
+++ b/dom/html/test/test_viewport_resize.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1135812
+-->
+<head>
+ <title>Test for Bug 1135812</title>
+ <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1135812">Mozilla Bug 1135812</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+
+<iframe style="width: 50px;"
+ srcdoc='<picture><source srcset="data:,a" media="(min-width: 150px)" /><source srcset="data:,b" media="(min-width: 100px)" /><img src="data:,c" /></picture>'></iframe>
+<script>
+ SimpleTest.waitForExplicitFinish();
+ addEventListener('load', function() {
+ var iframe = document.querySelector('iframe');
+ var img = iframe.contentDocument.querySelector('img');
+ is(img.currentSrc, 'data:,c');
+
+ img.onload = function() {
+ is(img.currentSrc, 'data:,a');
+ img.onload = function() {
+ is(img.currentSrc, 'data:,b');
+ SimpleTest.finish();
+ }
+ img.onerror = img.onload;
+ iframe.style.width = '120px';
+ };
+ img.onerror = img.onload;
+
+ iframe.style.width = '200px';
+ }, true);
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/html/test/test_window_open_close.html b/dom/html/test/test_window_open_close.html
new file mode 100644
index 000000000..c7e3b96f5
--- /dev/null
+++ b/dom/html/test/test_window_open_close.html
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
+ <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<script type="application/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+// Opens a popup. Link should load in main browser window. Popup should be closed when link clicked.
+function openWindow1() {
+ return window.open('file_window_open_close_outer.html','','width=300,height=200');
+}
+
+// Opens a new tab T1. Link opens in another new tab T2. T1 should close when link clicked.
+function openWindow2() {
+ return window.open('file_window_open_close_outer.html');
+}
+
+// Opens a new window. Link should open in a new tab of that window, but then both windows should close.
+function openWindow3() {
+ return window.open('file_window_open_close_outer.html', '', 'toolbar=1');
+}
+
+var TESTS = [openWindow1, openWindow2, openWindow3];
+
+function popupLoad(win)
+{
+ info("Sending click");
+ sendMouseEvent({type: "click"}, "link", win);
+ ok(true, "Didn't crash");
+
+ next();
+}
+
+function next()
+{
+ if (TESTS.length == 0) {
+ SimpleTest.finish();
+ } else {
+ var test = TESTS.shift();
+ var w = test();
+ w.addEventListener("load", (e) => popupLoad(w));
+ }
+}
+</script>
+
+<body onload="next()">
+</body>
+</html>
diff --git a/dom/html/test/wakelock.ogg b/dom/html/test/wakelock.ogg
new file mode 100644
index 000000000..d7f6a0ccf
--- /dev/null
+++ b/dom/html/test/wakelock.ogg
Binary files differ
diff --git a/dom/html/test/wakelock.ogv b/dom/html/test/wakelock.ogv
new file mode 100644
index 000000000..093158432
--- /dev/null
+++ b/dom/html/test/wakelock.ogv
Binary files differ