1 /*
2 * Copyright (c) 2002-2026 Gargoyle Software Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 * https://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 package org.htmlunit;
16
17 import static org.htmlunit.javascript.configuration.SupportedBrowser.CHROME;
18 import static org.htmlunit.javascript.configuration.SupportedBrowser.EDGE;
19 import static org.htmlunit.javascript.configuration.SupportedBrowser.FF;
20 import static org.htmlunit.javascript.configuration.SupportedBrowser.FF_ESR;
21
22 import org.htmlunit.javascript.configuration.BrowserFeature;
23
24 /**
25 * Constants of various features of each {@link BrowserVersion}.
26 *
27 * @author Ahmed Ashour
28 * @author Marc Guillemot
29 * @author Sudhan Moghe
30 * @author Ronald Brill
31 * @author Frank Danek
32 * @author Carsten Steul
33 * @author Anton Demydenko
34 */
35 public enum BrowserVersionFeatures {
36
37 /** Ignore target when {@code href} is a javascript snippet. */
38 @BrowserFeature({CHROME, EDGE})
39 ANCHOR_SEND_PING_REQUEST,
40
41 /** Background image is 'initial'. */
42 @BrowserFeature({CHROME, EDGE})
43 CSS_BACKGROUND_INITIAL,
44
45 /** Background image is 'rgba(0, 0, 0, 0)'. */
46 @BrowserFeature({FF, FF_ESR})
47 CSS_BACKGROUND_RGBA,
48
49 /** Is display style 'block'. */
50 @BrowserFeature({FF, FF_ESR})
51 CSS_DISPLAY_BLOCK,
52
53 /** The default value of the display property for the 'noscript' tag is 'inline' instead of the default one. */
54 @BrowserFeature({CHROME, EDGE})
55 CSS_NOSCRIPT_DISPLAY_INLINE,
56
57 /** The default value of the display property for the 'rp' tag is 'none'. */
58 @BrowserFeature({FF, FF_ESR})
59 CSS_RP_DISPLAY_NONE,
60
61 /** The default value of the display property for the 'rt' tag is always 'ruby-text'. */
62 @BrowserFeature({FF, FF_ESR})
63 CSS_RT_DISPLAY_RUBY_TEXT_ALWAYS,
64
65 /** The context menu MouseEvent has a detail of 1. */
66 @BrowserFeature({FF, FF_ESR})
67 EVENT_CONTEXT_MENU_HAS_DETAIL_1,
68
69 /** Triggers the onfocus event when focusing the body on load. */
70 @BrowserFeature({FF, FF_ESR})
71 EVENT_FOCUS_ON_LOAD,
72
73 /** Scroll events are of type 'UIEvent'. */
74 @BrowserFeature({FF, FF_ESR})
75 EVENT_SCROLL_UIEVENT,
76
77 /** Form elements are able to refer to the for by using the form attribute. */
78 @BrowserFeature({CHROME, EDGE})
79 FORM_IGNORE_REL_NOREFERRER,
80
81 /** Form submit includes the Cache-Control: max-age=0 header. */
82 @BrowserFeature({CHROME, EDGE})
83 FORM_SUBMISSION_HEADER_CACHE_CONTROL_MAX_AGE,
84
85 /** Should org.htmlunit.javascript.host.html.HTMLBaseFontElement#isEndTagForbidden(). */
86 @BrowserFeature({FF, FF_ESR})
87 HTMLBASEFONT_END_TAG_FORBIDDEN,
88
89 /** HtmlCollection.namedItem searches by id first. */
90 @BrowserFeature({CHROME, EDGE})
91 HTMLCOLLECTION_NAMED_ITEM_ID_FIRST,
92
93 /**
94 /** {@code document.getElementsByName} returns an empty list if called with the empty string.
95 */
96 @BrowserFeature({FF, FF_ESR})
97 HTMLDOCUMENT_ELEMENTS_BY_NAME_EMPTY,
98
99 /** Removing the active element from the dom tree triggers the onblur event. */
100 @BrowserFeature({CHROME, EDGE})
101 HTMLELEMENT_REMOVE_ACTIVE_TRIGGERS_BLUR_EVENT,
102
103 /** Handle blank source like empty. */
104 @BrowserFeature({CHROME, EDGE})
105 HTMLIMAGE_BLANK_SRC_AS_EMPTY,
106
107 /** Empty src attribute sets display to false. */
108 @BrowserFeature({FF, FF_ESR})
109 HTMLIMAGE_EMPTY_SRC_DISPLAY_FALSE,
110
111 /** Is document.cretaeElement('image') an HTMLElement. */
112 @BrowserFeature({FF, FF_ESR})
113 HTMLIMAGE_HTMLELEMENT,
114
115 /** Is document.cretaeElement('image') an HTMLUnknownElement. */
116 @BrowserFeature({CHROME, EDGE})
117 HTMLIMAGE_HTMLUNKNOWNELEMENT,
118
119 /** HTMLInputElement image type is not supported. */
120 @BrowserFeature({CHROME, EDGE})
121 HTMLINPUT_TYPE_IMAGE_IGNORES_CUSTOM_VALIDITY,
122
123 /** HTMLInputElement month type is supported. */
124 @BrowserFeature({CHROME, EDGE})
125 HTMLINPUT_TYPE_MONTH_SUPPORTED,
126
127 /** HTMLInputElement week type is supported. */
128 @BrowserFeature({CHROME, EDGE})
129 HTMLINPUT_TYPE_WEEK_SUPPORTED,
130
131 /** For a stylesheet link report an error if the response type is not text/css. */
132 @BrowserFeature({FF, FF_ESR})
133 HTMLLINK_CHECK_RESPONSE_TYPE_FOR_STYLESHEET,
134
135 /** If the type is present for a link only use if type is text/css. */
136 @BrowserFeature({CHROME, EDGE})
137 HTMLLINK_CHECK_TYPE_FOR_STYLESHEET,
138
139 /** Should org.htmlunit.javascript.host.html.HTMLTrackElement#isEndTagForbidden(). */
140 @BrowserFeature({FF, FF_ESR})
141 HTMLTRACK_END_TAG_FORBIDDEN,
142
143 /** HTML parser supports the 'layer' tag. */
144 @BrowserFeature({CHROME, EDGE})
145 HTML_LAYER_TAG,
146
147 /** Additionally support dates in format "d/M/yyyy". */
148 @BrowserFeature({FF, FF_ESR})
149 HTTP_COOKIE_EXTENDED_DATE_PATTERNS_1,
150
151 /** Dates format pattern 2. */
152 @BrowserFeature({CHROME, EDGE})
153 HTTP_COOKIE_EXTENDED_DATE_PATTERNS_2,
154
155 /** domain '.org' is handled as 'org'. */
156 @BrowserFeature({FF, FF_ESR})
157 HTTP_COOKIE_REMOVE_DOT_FROM_ROOT_DOMAINS,
158
159 /** Browser sends Sec-ch headers. */
160 @BrowserFeature({CHROME, EDGE})
161 HTTP_HEADER_CH_UA,
162
163 /** Browser sends Priority headers. */
164 @BrowserFeature({FF, FF_ESR})
165 HTTP_HEADER_PRIORITY,
166
167 /**
168 * The anchor pathname detects url's starting with one letter as file url's
169 * and replaces them with the file protocol. */
170 @BrowserFeature({CHROME, EDGE})
171 JS_ANCHOR_PATHNAME_DETECT_WIN_DRIVES_URL_REPLACE,
172
173 /** The anchor pathname prefixes file url's with '/'. */
174 @BrowserFeature({CHROME, EDGE})
175 JS_ANCHOR_PATHNAME_PREFIX_WIN_DRIVES_URL,
176
177 /** The anchor protocol property converts drive letters to uppercase. */
178 @BrowserFeature({CHROME, EDGE})
179 JS_ANCHOR_PROTOCOL_COLON_UPPER_CASE_DRIVE_LETTERS,
180
181 /** An area element without a href attribute is focusable. */
182 @BrowserFeature({FF, FF_ESR})
183 JS_AREA_WITHOUT_HREF_FOCUSABLE,
184
185 /** Sorting an array using a user defined comperator accepts inconsistent iterators. */
186 @BrowserFeature({FF, FF_ESR})
187 JS_ARRAY_SORT_ACCEPTS_INCONSISTENT_COMPERATOR,
188
189 /** AudioProcessingEvent ctor is callable. */
190 @BrowserFeature({CHROME, EDGE})
191 JS_AUDIO_PROCESSING_EVENT_CTOR,
192
193 /** toDataURL for canvas returns the CHROME version of the PNG. */
194 @BrowserFeature({CHROME, EDGE})
195 JS_CANVAS_DATA_URL_CHROME_PNG,
196
197 /** ClientHeight for input is 17. */
198 @BrowserFeature({CHROME, EDGE})
199 JS_CLIENTHEIGHT_INPUT_17,
200
201 /** ClientHeight for input is 18. */
202 @BrowserFeature({FF, FF_ESR})
203 JS_CLIENTHEIGHT_INPUT_18,
204
205 /** ClientHeight for radio button and checkbox is 14. */
206 @BrowserFeature({FF, FF_ESR})
207 JS_CLIENTHEIGHT_RADIO_CHECKBOX_14,
208
209 /** ClientHeight for rb is 17. */
210 @BrowserFeature({FF, FF_ESR})
211 JS_CLIENTHEIGHT_RB_17,
212
213 /** ClientHeight for rt is 9. */
214 @BrowserFeature({FF, FF_ESR})
215 JS_CLIENTHEIGHT_RT_9,
216
217 /** ClientHeight for ruby is 17. */
218 @BrowserFeature({FF, FF_ESR})
219 JS_CLIENTHEIGHT_RUBY_17,
220
221 /** ClientWidth for text/password input is 173. */
222 @BrowserFeature({CHROME, EDGE})
223 JS_CLIENTWIDTH_INPUT_TEXT_173,
224
225 /** ClientWidth for radio button and checkbox is 14. */
226 @BrowserFeature({FF, FF_ESR})
227 JS_CLIENTWIDTH_RADIO_CHECKBOX_14,
228
229 /** item is enumerated before length property of CSSRuleList. */
230 @BrowserFeature({FF, FF_ESR})
231 JS_CSSRULELIST_ENUM_ITEM_LENGTH,
232
233 /** Javascript document.evaluate() creates a new result object even if provided as param. */
234 @BrowserFeature({CHROME, EDGE})
235 JS_DOCUMENT_EVALUATE_RECREATES_RESULT,
236
237 /** The browser has selection {@code rangeCount}. */
238 @BrowserFeature({FF, FF_ESR})
239 JS_DOCUMENT_SELECTION_RANGE_COUNT,
240
241 /** Javascript {@code Error.stackTraceLimit}. */
242 @BrowserFeature({CHROME, EDGE})
243 JS_ERROR_STACK_TRACE_LIMIT,
244
245 /** Javascript {@code Error.stackTraceLimit}. */
246 @BrowserFeature({FF, FF_ESR})
247 JS_ERROR_STACK_TRACE_LIMIT_128,
248
249 /** Javascript InputEvent reads the inputType property from data. */
250 @BrowserFeature({FF, FF_ESR})
251 JS_EVENT_INPUT_CTOR_INPUTTYPE,
252
253 /** Javascript KeyboardEvent reads the which property from data. */
254 @BrowserFeature({FF, FF_ESR})
255 JS_EVENT_KEYBOARD_CTOR_WHICH,
256
257 /** form.dispatchEvent(e) submits the form if the event is of type 'submit'. */
258 @BrowserFeature({FF, FF_ESR})
259 JS_FORM_DISPATCHEVENT_SUBMITS,
260
261 /** Executes the {@code onload} handler, regardless of the element was already attached to the page. */
262 @BrowserFeature({FF, FF_ESR})
263 JS_IFRAME_ALWAYS_EXECUTE_ONLOAD,
264
265 /**
266 * Getting the width and height of an image tag without a source returns 16x16;
267 * for invalid values returns 0.
268 */
269 @BrowserFeature({CHROME, EDGE})
270 JS_IMAGE_WIDTH_HEIGHT_RETURNS_16x16_0x0,
271
272 /**
273 * Getting the width and height of an image tag without a source returns 24x24;
274 * for invalid values returns 0x0.
275 */
276 @BrowserFeature({FF, FF_ESR})
277 JS_IMAGE_WIDTH_HEIGHT_RETURNS_24x24_0x0,
278
279 /** Indicates that the HTML serialization of a processing instruction ends with '>' instead of '?>'. */
280 @BrowserFeature({FF, FF_ESR})
281 JS_INNER_HTML_PROCESSING_INSTRUCTION_NO_QUESTION_MARK,
282
283 /** Indicates that innerHTML returns an empty string for empty elements. */
284 @BrowserFeature({CHROME, EDGE})
285 JS_INNER_HTML_VOID_ELEMENT_EMPTY,
286
287 /**
288 * Indicates that the XML serialization writes boolean attributes of XHTML elements
289 * with an empty value as name="name" (e.g. disabled="disabled").
290 */
291 @BrowserFeature({FF, FF_ESR})
292 JS_INNER_HTML_XHTML_BOOLEAN_ATTRIBUTE_VALUE,
293
294 /** Indicates that the XML serialization escapes line breaks in attribute values as hex references (
). */
295 @BrowserFeature({FF, FF_ESR})
296 JS_INNER_HTML_XHTML_HEX_LINE_BREAK,
297
298 /** Indicates that the XML serialization writes the namespace declaration of an attribute after the attribute. */
299 @BrowserFeature({FF, FF_ESR})
300 JS_INNER_HTML_XHTML_NS_DECLARATION_AFTER_ATTRIBUTE,
301
302 /** Indicates that innerHTML of a script or style element in an XHTML document returns the text as is. */
303 @BrowserFeature({FF, FF_ESR})
304 JS_INNER_HTML_XHTML_RAW_SCRIPT_STYLE,
305
306 /** Indicates that innerText add a nl when reaching svg element. */
307 @BrowserFeature({FF, FF_ESR})
308 JS_INNER_TEXT_SELECT_EMPTY,
309
310 /** Indicates that innerText add a nl when reaching svg element. */
311 @BrowserFeature({CHROME, EDGE})
312 JS_INNER_TEXT_SVG_NL,
313
314 /** The value is ignored when the type of the week/month input is changed. */
315 @BrowserFeature({CHROME, EDGE})
316 JS_INPUT_CHANGE_TYPE_DROPS_VALUE_WEEK_MONTH,
317
318 /** FF accepts all chars. */
319 @BrowserFeature({FF, FF_ESR})
320 JS_INPUT_NUMBER_ACCEPT_ALL,
321
322 /** FF comma at end is not an integer. */
323 @BrowserFeature({FF, FF_ESR})
324 JS_INPUT_NUMBER_DOT_AT_END_IS_DOUBLE,
325
326 /** Indicates that Intl.v8BreakIterator is supported. */
327 @BrowserFeature({CHROME, EDGE})
328 JS_INTL_V8_BREAK_ITERATOR,
329
330 /** Reload sends a referrer header. */
331 @BrowserFeature({CHROME, EDGE})
332 JS_LOCATION_RELOAD_REFERRER,
333
334 /** Type property of menu returns the current (maybe invalid) value. */
335 @BrowserFeature({FF, FF_ESR})
336 JS_MENU_TYPE_PASS,
337
338 /** Indicates if the String representation of a native function is without newline. */
339 @BrowserFeature({CHROME, EDGE})
340 JS_NATIVE_FUNCTION_TOSTRING_COMPACT,
341
342 /** Indicates if the String representation of a native function has a newline for empty parameter list. */
343 @BrowserFeature({FF, FF_ESR})
344 JS_NATIVE_FUNCTION_TOSTRING_NL,
345
346 /** Navigator.doNotTrack returns unspecified if not set. */
347 @BrowserFeature({FF, FF_ESR})
348 JS_NAVIGATOR_DO_NOT_TRACK_UNSPECIFIED,
349
350 /** PerformanceObserver.supportedEntryTypes returns only the entry types supported by Firefox. */
351 @BrowserFeature({FF, FF_ESR})
352 JS_PERFORMANCE_OBSERVER_ENTRY_TYPES_FF,
353
354 /** PerformanceObserver.supportedEntryTypes returns a frozen array. */
355 @BrowserFeature({CHROME, EDGE})
356 JS_PERFORMANCE_OBSERVER_ENTRY_TYPES_FROZEN,
357
358 /** Indicates that the {@code Object.getOwnPropertyDescriptor.get} contains name. */
359 @BrowserFeature({FF, FF_ESR})
360 JS_PROPERTY_DESCRIPTOR_NAME,
361
362 /** script tags created from js as child of templates is processed if added to the dom. */
363 @BrowserFeature({CHROME, EDGE})
364 JS_SCRIPT_IN_TEMPLATE_EXECUTED_ON_ATTACH,
365
366 /** Javascript selectorText property returns selectors in lower case. */
367 @BrowserFeature({CHROME, EDGE})
368 JS_SELECTOR_TEXT_LOWERCASE,
369
370 /** Indicates that select.options.remove ignores the call if index is too large. */
371 @BrowserFeature({FF, FF_ESR})
372 JS_SELECT_REMOVE_IGNORE_IF_INDEX_OUTSIDE,
373
374 /** Whether to add to the storage even preserved words. */
375 @BrowserFeature({FF, FF_ESR})
376 JS_STORAGE_PRESERVED_INCLUDED,
377
378 /** window.getComputedStyle works with pseudo selectors without colon in front. */
379 @BrowserFeature({CHROME, EDGE})
380 JS_WINDOW_COMPUTED_STYLE_PSEUDO_ACCEPT_WITHOUT_COLON,
381
382 /** Javascript InstallTrigger property set to null. */
383 @BrowserFeature({FF, FF_ESR})
384 JS_WINDOW_INSTALL_TRIGGER_NULL,
385
386 /**
387 * Difference of window.outer/inner height is 138.
388 */
389 @BrowserFeature(EDGE)
390 JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_138,
391
392 /**
393 * Difference of window.outer/inner height is 147.
394 */
395 @BrowserFeature(CHROME)
396 JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_147,
397
398 /**
399 * Difference of window.outer/inner height is 94.
400 */
401 @BrowserFeature({FF, FF_ESR})
402 JS_WINDOW_OUTER_INNER_HEIGHT_DIFF_94,
403
404 /** Window.getSelection returns null, if the window is not visible. */
405 @BrowserFeature({FF, FF_ESR})
406 JS_WINDOW_SELECTION_NULL_IF_INVISIBLE,
407
408 /** Take care of the response charset when reading a worker script. */
409 @BrowserFeature({CHROME, EDGE})
410 JS_WORKER_SCRIPT_HONORS_CHARSET_HEADER,
411
412 /** {@code XSLTProcessor.transformToDocument} supports output indent attribute. */
413 @BrowserFeature({CHROME, EDGE})
414 JS_XSLT_TRANSFORM_INDENT,
415
416 /** With special keys [in .type(int)], should we trigger onkeypress event or not. */
417 @BrowserFeature({FF, FF_ESR})
418 KEYBOARD_EVENT_SPECIAL_KEYPRESS,
419
420 /**
421 * Indicates that the Browser handles async and sync network errors the same way.
422 */
423 @BrowserFeature({FF, FF_ESR})
424 XHR_HANDLE_SYNC_NETWORK_ERRORS,
425
426 /** XMLHttpRequest triggers the load events also if the abort was signaled. */
427 @BrowserFeature({FF, FF_ESR})
428 XHR_LOAD_ALWAYS_AFTER_DONE,
429
430 /** Indicates if the XMLHttpRequest preflight request includes the 'Sec-Fetch-Mode=cors' header. */
431 @BrowserFeature({CHROME, EDGE})
432 XHR_PREFLIGHT_CORS,
433
434 /** If state unsent the response text is empty even if the response type is wrong. */
435 @BrowserFeature({FF, FF_ESR})
436 XHR_RESPONSE_TEXT_EMPTY_UNSENT,
437
438 /** Indicates if the XMLHttpRequest.send() method will throw if aborted. */
439 @BrowserFeature({CHROME, EDGE})
440 XHR_SEND_NETWORK_ERROR_IF_ABORTED,
441 }