mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 21:42:43 +00:00 
			
		
		
		
	LibWeb: Add input element valueAsDate property
This commit is contained in:
		
							parent
							
								
									be511fdcf7
								
							
						
					
					
						commit
						cf69fd0a09
					
				
					 10 changed files with 314 additions and 9 deletions
				
			
		|  | @ -630,7 +630,13 @@ static void generate_to_cpp(SourceGenerator& generator, ParameterType& parameter | |||
|     auto @cpp_name@ = JS::make_handle(&static_cast<JS::Promise&>(@js_name@@js_suffix@.as_object())); | ||||
| )~~~"); | ||||
|     } else if (parameter.type->name() == "object") { | ||||
|         if (optional) { | ||||
|         if (parameter.type->is_nullable()) { | ||||
|             scoped_generator.append(R"~~~( | ||||
|     Optional<JS::Handle<JS::Object>> @cpp_name@; | ||||
|     if (!@js_name@@js_suffix@.is_null() && !@js_name@@js_suffix@.is_undefined()) | ||||
|         @cpp_name@ = JS::make_handle(TRY(@js_name@@js_suffix@.to_object(vm))); | ||||
| )~~~"); | ||||
|         } else if (optional) { | ||||
|             scoped_generator.append(R"~~~( | ||||
|     Optional<JS::Handle<JS::Object>> @cpp_name@; | ||||
|     if (!@js_name@@js_suffix@.is_undefined()) | ||||
|  |  | |||
							
								
								
									
										14
									
								
								Tests/LibWeb/Text/expected/input-date.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								Tests/LibWeb/Text/expected/input-date.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| 1. "2023-12-11T00:00:00.000Z" | ||||
| 2. null | ||||
| 3. "1970-01-01T19:46:00.000Z" | ||||
| 4. "1970-01-01T19:46:19.000Z" | ||||
| 5. null | ||||
| 6. "1970-01-01" | ||||
| 7. "2023-12-11" | ||||
| 8. Exception: TypeError | ||||
| 9. "" | ||||
| 10. "18:47:37" | ||||
| 11. "18:47:37.100" | ||||
| 12. "18:47:37.864" | ||||
| 13. Exception: TypeError | ||||
| 14. "" | ||||
							
								
								
									
										126
									
								
								Tests/LibWeb/Text/input/input-date.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								Tests/LibWeb/Text/input/input-date.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,126 @@ | |||
| <script src="./include.js"></script> | ||||
| <script> | ||||
|     test(() => { | ||||
|         let testCounter = 1; | ||||
|         function testPart(part) { | ||||
|             try { | ||||
|                 println(`${testCounter}. ${JSON.stringify(part())}`); | ||||
|             } catch (e) { | ||||
|                 println(`${testCounter}. Exception: ${e.name}`); | ||||
|             } | ||||
|             testCounter++; | ||||
|         } | ||||
| 
 | ||||
|         // 1. Input date get value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'date'; | ||||
|             input.value = '2023-12-11'; | ||||
|             return input.valueAsDate; | ||||
|         }); | ||||
| 
 | ||||
|         // 2. Input date invalid get value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'date'; | ||||
|             input.value = 'invalid'; | ||||
|             return input.valueAsDate; | ||||
|         }); | ||||
| 
 | ||||
|         // 3. Input time get value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'time'; | ||||
|             input.value = '19:46'; | ||||
|             return input.valueAsDate; | ||||
|         }); | ||||
| 
 | ||||
|         // 4. Input time get value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'time'; | ||||
|             input.value = '19:46:19'; | ||||
|             return input.valueAsDate; | ||||
|         }); | ||||
| 
 | ||||
|         // 5. Input time invalid get value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'time'; | ||||
|             input.value = 'invalid'; | ||||
|             return input.valueAsDate; | ||||
|         }); | ||||
| 
 | ||||
|         // 6. Input date set value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'date'; | ||||
|             input.valueAsDate = new Date(0); | ||||
|             return input.value; | ||||
|         }); | ||||
| 
 | ||||
|         // 7. Input date set value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'date'; | ||||
|             input.valueAsDate = new Date(1702320457860); | ||||
|             return input.value; | ||||
|         }); | ||||
| 
 | ||||
|         // 8. Input date invalid set value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'date'; | ||||
|             input.valueAsDate = {}; | ||||
|             return input.value; | ||||
|         }); | ||||
| 
 | ||||
|         // 9. Input date null set value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'date'; | ||||
|             input.valueAsDate = null; | ||||
|             return input.value; | ||||
|         }); | ||||
| 
 | ||||
|         // 10. Input time set value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'time'; | ||||
|             input.valueAsDate = new Date(1702320457000); | ||||
|             return input.value; | ||||
|         }); | ||||
| 
 | ||||
|         // 11. Input time set value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'time'; | ||||
|             input.valueAsDate = new Date(1702320457100); | ||||
|             return input.value; | ||||
|         }); | ||||
| 
 | ||||
|         // 12. Input time set value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'time'; | ||||
|             input.valueAsDate = new Date(1702320457864.5); | ||||
|             return input.value; | ||||
|         }); | ||||
| 
 | ||||
|         // 13. Input time invalid set value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'time'; | ||||
|             input.valueAsDate = {}; | ||||
|             return input.value; | ||||
|         }); | ||||
| 
 | ||||
|         // 14. Input time null set value as date | ||||
|         testPart(() => { | ||||
|             const input = document.createElement('input'); | ||||
|             input.type = 'time'; | ||||
|             input.valueAsDate = null; | ||||
|             return input.value; | ||||
|         }); | ||||
|     }); | ||||
| </script> | ||||
|  | @ -20,7 +20,7 @@ JS::NonnullGCPtr<KeyframeEffect> KeyframeEffect::create(JS::Realm& realm) | |||
| WebIDL::ExceptionOr<JS::NonnullGCPtr<KeyframeEffect>> KeyframeEffect::construct_impl( | ||||
|     JS::Realm& realm, | ||||
|     JS::Handle<DOM::Element> const& target, | ||||
|     JS::Handle<JS::Object> const& keyframes, | ||||
|     Optional<JS::Handle<JS::Object>> const& keyframes, | ||||
|     Variant<double, KeyframeEffectOptions> options) | ||||
| { | ||||
|     auto& vm = realm.vm(); | ||||
|  | @ -163,10 +163,9 @@ WebIDL::ExceptionOr<Vector<JS::Object*>> KeyframeEffect::get_keyframes() const | |||
| } | ||||
| 
 | ||||
| // https://www.w3.org/TR/web-animations-1/#dom-keyframeeffect-setkeyframes
 | ||||
| WebIDL::ExceptionOr<void> KeyframeEffect::set_keyframes(JS::Object* keyframe_object) | ||||
| WebIDL::ExceptionOr<void> KeyframeEffect::set_keyframes(Optional<JS::Handle<JS::Object>> const&) | ||||
| { | ||||
|     // FIXME: Implement this
 | ||||
|     (void)keyframe_object; | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -47,7 +47,7 @@ public: | |||
|     static WebIDL::ExceptionOr<JS::NonnullGCPtr<KeyframeEffect>> construct_impl( | ||||
|         JS::Realm&, | ||||
|         JS::Handle<DOM::Element> const& target, | ||||
|         JS::Handle<JS::Object> const& keyframes, | ||||
|         Optional<JS::Handle<JS::Object>> const& keyframes, | ||||
|         Variant<double, KeyframeEffectOptions> options = KeyframeEffectOptions {}); | ||||
| 
 | ||||
|     static WebIDL::ExceptionOr<JS::NonnullGCPtr<KeyframeEffect>> construct_impl(JS::Realm&, JS::NonnullGCPtr<KeyframeEffect> source); | ||||
|  | @ -62,7 +62,7 @@ public: | |||
|     void set_composite(Bindings::CompositeOperation value) { m_composite = value; } | ||||
| 
 | ||||
|     WebIDL::ExceptionOr<Vector<JS::Object*>> get_keyframes() const; | ||||
|     WebIDL::ExceptionOr<void> set_keyframes(JS::Object*); | ||||
|     WebIDL::ExceptionOr<void> set_keyframes(Optional<JS::Handle<JS::Object>> const&); | ||||
| 
 | ||||
| private: | ||||
|     KeyframeEffect(JS::Realm&); | ||||
|  |  | |||
|  | @ -128,6 +128,22 @@ bool is_valid_date_string(StringView value) | |||
|     return day >= 1 && day <= AK::days_in_month(year, month); | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#parse-a-date-string
 | ||||
| WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Date>> parse_date_string(JS::Realm& realm, StringView value) | ||||
| { | ||||
|     // FIXME: Implement spec compliant date string parsing
 | ||||
|     auto parts = value.split_view('-'); | ||||
|     if (parts.size() >= 3) { | ||||
|         if (auto year = parts.at(0).to_uint(); year.has_value()) { | ||||
|             if (auto month = parts.at(1).to_uint(); month.has_value()) { | ||||
|                 if (auto day_of_month = parts.at(2).to_uint(); day_of_month.has_value()) | ||||
|                     return JS::Date::create(realm, JS::make_date(JS::make_day(*year, *month - 1, *day_of_month), 0)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Can't parse date string"sv }; | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-local-date-and-time-string
 | ||||
| bool is_valid_local_date_and_time_string(StringView value) | ||||
| { | ||||
|  | @ -197,4 +213,23 @@ bool is_valid_time_string(StringView value) | |||
|     return true; | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#parse-a-time-string
 | ||||
| WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Date>> parse_time_string(JS::Realm& realm, StringView value) | ||||
| { | ||||
|     // FIXME: Implement spec compliant time string parsing
 | ||||
|     auto parts = value.split_view(':'); | ||||
|     if (parts.size() >= 2) { | ||||
|         if (auto hours = parts.at(0).to_uint(); hours.has_value()) { | ||||
|             if (auto minutes = parts.at(1).to_uint(); minutes.has_value()) { | ||||
|                 if (parts.size() >= 3) { | ||||
|                     if (auto seconds = parts.at(2).to_uint(); seconds.has_value()) | ||||
|                         return JS::Date::create(realm, JS::make_time(*hours, *minutes, *seconds, 0)); | ||||
|                 } | ||||
|                 return JS::Date::create(realm, JS::make_date(0, JS::make_time(*hours, *minutes, 0, 0))); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "Can't parse time string"sv }; | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -8,6 +8,8 @@ | |||
| 
 | ||||
| #include <AK/Forward.h> | ||||
| #include <AK/String.h> | ||||
| #include <LibJS/Runtime/Date.h> | ||||
| #include <LibWeb/WebIDL/ExceptionOr.h> | ||||
| 
 | ||||
| namespace Web::HTML { | ||||
| 
 | ||||
|  | @ -15,8 +17,10 @@ u32 week_number_of_the_last_day(u64 year); | |||
| bool is_valid_week_string(StringView value); | ||||
| bool is_valid_month_string(StringView value); | ||||
| bool is_valid_date_string(StringView value); | ||||
| WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Date>> parse_date_string(JS::Realm& realm, StringView value); | ||||
| bool is_valid_local_date_and_time_string(StringView value); | ||||
| String normalize_local_date_and_time_string(String const& value); | ||||
| bool is_valid_time_string(StringView value); | ||||
| WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::Date>> parse_time_string(JS::Realm& realm, StringView value); | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ | |||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #include <LibJS/Runtime/Date.h> | ||||
| #include <LibJS/Runtime/NativeFunction.h> | ||||
| #include <LibWeb/CSS/StyleValues/DisplayStyleValue.h> | ||||
| #include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h> | ||||
|  | @ -1117,6 +1118,63 @@ String HTMLInputElement::covert_number_to_string(double input) const | |||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/input.html#concept-input-value-string-date
 | ||||
| WebIDL::ExceptionOr<JS::GCPtr<JS::Date>> HTMLInputElement::convert_string_to_date(StringView input) const | ||||
| { | ||||
|     // https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):concept-input-value-string-date
 | ||||
|     if (type_state() == TypeAttributeState::Date) { | ||||
|         // If parsing a date from input results in an error, then return an error;
 | ||||
|         auto maybe_date = parse_date_string(realm(), input); | ||||
|         if (maybe_date.is_exception()) | ||||
|             return maybe_date.exception(); | ||||
| 
 | ||||
|         // otherwise, return a new Date object representing midnight UTC on the morning of the parsed date.
 | ||||
|         return maybe_date.value(); | ||||
|     } | ||||
| 
 | ||||
|     // https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time):concept-input-value-string-date
 | ||||
|     if (type_state() == TypeAttributeState::Time) { | ||||
|         // If parsing a time from input results in an error, then return an error;
 | ||||
|         auto maybe_time = parse_time_string(realm(), input); | ||||
|         if (maybe_time.is_exception()) | ||||
|             return maybe_time.exception(); | ||||
| 
 | ||||
|         // otherwise, return a new Date object representing the parsed time in UTC on 1970-01-01.
 | ||||
|         return maybe_time.value(); | ||||
|     } | ||||
| 
 | ||||
|     dbgln("HTMLInputElement::convert_string_to_date() not implemented for input type {}", type()); | ||||
|     return nullptr; | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/input.html#concept-input-value-date-string
 | ||||
| String HTMLInputElement::covert_date_to_string(JS::NonnullGCPtr<JS::Date> input) const | ||||
| { | ||||
|     // https://html.spec.whatwg.org/multipage/input.html#date-state-(type=date):concept-input-value-date-string
 | ||||
|     if (type_state() == TypeAttributeState::Date) { | ||||
|         // Return a valid date string that represents the date current at the time represented by input in the UTC time zone.
 | ||||
|         // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-date-string
 | ||||
|         return MUST(String::formatted("{:04d}-{:02d}-{:02d}", JS::year_from_time(input->date_value()), JS::month_from_time(input->date_value()) + 1, JS::date_from_time(input->date_value()))); | ||||
|     } | ||||
| 
 | ||||
|     // https://html.spec.whatwg.org/multipage/input.html#time-state-(type=time):concept-input-value-string-date
 | ||||
|     if (type_state() == TypeAttributeState::Time) { | ||||
|         // Return a valid time string that represents the UTC time component that is represented by input.
 | ||||
|         // https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#valid-time-string
 | ||||
|         auto seconds = JS::sec_from_time(input->date_value()); | ||||
|         auto milliseconds = JS::ms_from_time(input->date_value()); | ||||
|         if (seconds > 0) { | ||||
|             if (milliseconds > 0) | ||||
|                 return MUST(String::formatted("{:02d}:{:02d}:{:02d}.{:3d}", JS::hour_from_time(input->date_value()), JS::min_from_time(input->date_value()), seconds, milliseconds)); | ||||
|             return MUST(String::formatted("{:02d}:{:02d}:{:02d}", JS::hour_from_time(input->date_value()), JS::min_from_time(input->date_value()), seconds)); | ||||
|         } | ||||
|         return MUST(String::formatted("{:02d}:{:02d}", JS::hour_from_time(input->date_value()), JS::min_from_time(input->date_value()))); | ||||
|     } | ||||
| 
 | ||||
|     dbgln("HTMLInputElement::covert_date_to_string() not implemented for input type {}", type()); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/input.html#attr-input-min
 | ||||
| Optional<double> HTMLInputElement::min() const | ||||
| { | ||||
|  | @ -1234,8 +1292,50 @@ double HTMLInputElement::step_base() const | |||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/input.html#dom-input-valueasdate
 | ||||
| JS::Object* HTMLInputElement::value_as_date() const | ||||
| { | ||||
|     // On getting, if the valueAsDate attribute does not apply, as defined for the input element's type attribute's current state, then return null.
 | ||||
|     if (!value_as_date_applies()) | ||||
|         return nullptr; | ||||
| 
 | ||||
|     // Otherwise, run the algorithm to convert a string to a Date object defined for that state to the element's value;
 | ||||
|     // if the algorithm returned a Date object, then return it, otherwise, return null.
 | ||||
|     auto maybe_date = convert_string_to_date(value()); | ||||
|     if (!maybe_date.is_exception()) | ||||
|         return maybe_date.value().ptr(); | ||||
|     return nullptr; | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/input.html#dom-input-valueasdate
 | ||||
| WebIDL::ExceptionOr<void> HTMLInputElement::set_value_as_date(Optional<JS::Handle<JS::Object>> const& value) | ||||
| { | ||||
|     // On setting, if the valueAsDate attribute does not apply, as defined for the input element's type attribute's current state, then throw an "InvalidStateError" DOMException;
 | ||||
|     if (!value_as_date_applies()) | ||||
|         return WebIDL::InvalidStateError::create(realm(), "valueAsDate: Invalid input type used"_fly_string); | ||||
| 
 | ||||
|     // otherwise, if the new value is not null and not a Date object throw a TypeError exception;
 | ||||
|     if (value.has_value() && !is<JS::Date>(**value)) | ||||
|         return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "valueAsDate: input is not a Date"sv }; | ||||
| 
 | ||||
|     // otherwise if the new value is null or a Date object representing the NaN time value, then set the value of the element to the empty string;
 | ||||
|     if (!value.has_value()) { | ||||
|         TRY(set_value(String {})); | ||||
|         return {}; | ||||
|     } | ||||
|     auto& date = static_cast<JS::Date&>(**value); | ||||
|     if (!isfinite(date.date_value())) { | ||||
|         TRY(set_value(String {})); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     // otherwise, run the algorithm to convert a Date object to a string, as defined for that state, on the new value, and set the value of the element to the resulting string.
 | ||||
|     TRY(set_value(covert_date_to_string(date))); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/input.html#dom-input-valueasnumber
 | ||||
| WebIDL::ExceptionOr<double> HTMLInputElement::value_as_number() const | ||||
| double HTMLInputElement::value_as_number() const | ||||
| { | ||||
|     // On getting, if the valueAsNumber attribute does not apply, as defined for the input element's type attribute's current state, then return a Not-a-Number (NaN) value.
 | ||||
|     if (!value_as_number_applies()) | ||||
|  | @ -1537,6 +1637,20 @@ bool HTMLInputElement::change_event_applies() const | |||
|     } | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/input.html#the-input-element:dom-input-valueasdate-3
 | ||||
| bool HTMLInputElement::value_as_date_applies() const | ||||
| { | ||||
|     switch (type_state()) { | ||||
|     case TypeAttributeState::Date: | ||||
|     case TypeAttributeState::Month: | ||||
|     case TypeAttributeState::Week: | ||||
|     case TypeAttributeState::Time: | ||||
|         return true; | ||||
|     default: | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // https://html.spec.whatwg.org/multipage/input.html#the-input-element:dom-input-valueasnumber-3
 | ||||
| bool HTMLInputElement::value_as_number_applies() const | ||||
| { | ||||
|  |  | |||
|  | @ -102,7 +102,10 @@ public: | |||
|     unsigned size() const; | ||||
|     WebIDL::ExceptionOr<void> set_size(unsigned value); | ||||
| 
 | ||||
|     WebIDL::ExceptionOr<double> value_as_number() const; | ||||
|     JS::Object* value_as_date() const; | ||||
|     WebIDL::ExceptionOr<void> set_value_as_date(Optional<JS::Handle<JS::Object>> const&); | ||||
| 
 | ||||
|     double value_as_number() const; | ||||
|     WebIDL::ExceptionOr<void> set_value_as_number(double value); | ||||
| 
 | ||||
|     WebIDL::ExceptionOr<void> step_up(long n = 1); | ||||
|  | @ -165,6 +168,7 @@ public: | |||
| 
 | ||||
|     bool has_input_activation_behavior() const; | ||||
|     bool change_event_applies() const; | ||||
|     bool value_as_date_applies() const; | ||||
|     bool value_as_number_applies() const; | ||||
|     bool step_applies() const; | ||||
|     bool step_up_or_down_applies() const; | ||||
|  | @ -191,6 +195,9 @@ private: | |||
|     Optional<double> convert_string_to_number(StringView input) const; | ||||
|     String covert_number_to_string(double input) const; | ||||
| 
 | ||||
|     WebIDL::ExceptionOr<JS::GCPtr<JS::Date>> convert_string_to_date(StringView input) const; | ||||
|     String covert_date_to_string(JS::NonnullGCPtr<JS::Date> input) const; | ||||
| 
 | ||||
|     Optional<double> min() const; | ||||
|     Optional<double> max() const; | ||||
|     double default_step() const; | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ interface HTMLInputElement : HTMLElement { | |||
|     [CEReactions] attribute DOMString type; | ||||
|     [CEReactions, Reflect=value] attribute DOMString defaultValue; | ||||
|     [CEReactions, LegacyNullToEmptyString] attribute DOMString value; | ||||
|     // FIXME: attribute object? valueAsDate; | ||||
|     attribute object? valueAsDate; | ||||
|     attribute unrestricted double valueAsNumber; | ||||
|     // FIXME: [CEReactions] attribute unsigned long width; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Bastiaan van der Plaat
						Bastiaan van der Plaat