Like bug#28966 for type=color, implement the following types as a text field and add support for type checking.
- date
- datetime
- datetime-local
- month
- time
- week
Comment on attachment 39136[details]
Proposed patch
This is a big patch to review. :( Do you know about CaseInsentiveHash? Might be the right thing to use instead of:
336 else if (equalIgnoringCase(t, "date"))
337 newType = DATE;
(In reply to comment #2)
> This is a big patch to review. :( Do you know about CaseInsentiveHash? Might
> be the right thing to use instead of:
I haven't known it. Thanks.
Maybe I should move DateTime class to separated .h and .cpp. The class is going to have more methods in the near future.
(In reply to comment #2)
I'll split the patch into 3.
Part 1: Implement date&time types as text fields without type validation
Part 2: ISO 8601 parser
Part 3: ValidityState.typeCheck for date&time types, and tests
Created attachment 39532[details]
39344: Patch part 3: support for ValidityState.typeMismatch and layout tests (rev.2)
Resolved a patch conflict by r48318
Comment on attachment 39342[details]
Patch part 1: recognize date&time types as text fields
Explicit String construction isn't needed:
String("button")
the compiler will find String(char*) anyway.
Why two lookups?
333 if (!t.isNull() && typeMap->contains(t)) // contains() with a null string makes crash.
334 newType = typeMap->get(t);
just do one get instead of two lookups.
Lets make a hash for these too:
@@ const AtomicString& HTMLInputElement::formControlType() const
Then you don't have a zillion DEFINE_STATIC_LOCAL calls, because the Hash can be TYPE -> AtomicString
(That doesn't have to be part of this patch, but if you're in there cleaning stuff up, you should consider it. I think it will be much less code. Heck, it could even be a Vector instead of a Hash if you like.)
Default is bad with switches over enums:
default:
1048 return false;
it's breaks the compiler's ability to tell you when you're missing cases. In this function 1028 bool HTMLInputElement::isTextField() const it seems we don't even want a switch. We just want a single if, or? Or at least we want an explicit list of the false cases if you're going to use a switch.
Comment on attachment 39343[details]
Patch part2: ISO 8601 parser
You wrote the parser by yourself I assume? It's no code from any other license?
Also, we need tests for this parser.
I think we should consider splitting it off into its own file which DateMath can use. ISO8601DateParser or some other nicer name?
r- for the lack of tests.
Comment on attachment 39857[details]
Patch part 3: ValidityState.typeMismatch and layout tests (rev.3)
OK, here are the tests. or at least some tests. So my r- above was perhaps premature. I guess I'll still leave it r- awaiting your response to the other questions raised. I've not looked at your parser close enough to see if I had security or performance concerns, but I can look again.
Comment on attachment 39857[details]
Patch part 3: ValidityState.typeMismatch and layout tests (rev.3)
I think I would have used two separate methods:
shoudlBeInvalid
shoudlBeValid
instead of check true/false.
But it looks fine as is.
Created attachment 40036[details]
Patch part 1: recognize date&time types as text fields (rev.2)
> Explicit String construction isn't needed:
> String("button")
Fixed.
> Why two lookups?
Fixed.
> Lets make a hash for these too:
> @@ const AtomicString& HTMLInputElement::formControlType() const
Done. I used Vector.
> Default is bad with switches over enums:
> default:
Removed the default label and expanded the rest of types.
(In reply to comment #11)
> (From update of attachment 39343[details])
> You wrote the parser by yourself I assume? It's no code from any other
> license?
Yes, it's my code written for WebKit.
> I think we should consider splitting it off into its own file which DateMath
> can use. ISO8601DateParser or some other nicer name?
Do you think the new file should be in JavaScriptCore/wtf/ ?
I assume so. The parser might be used by JSON.parse(), not only html/HTMLInputElement.cpp
(In reply to comment #15)
> Do you think the new file should be in JavaScriptCore/wtf/ ?
> I assume so. The parser might be used by JSON.parse(), not only
> html/HTMLInputElement.cpp
I'm OK w/ either location.
Created attachment 40219[details]
Patch part 2: ISO 8601 parser (rev.2)
- Move ISO 8601 parser code to wtf/ISODateParser.{cpp.h}
This patch doesn't depend on Part 1. Part 1 and Part2 can be committed independently.
Created attachment 40221[details]
Patch part 3: ValidityState.typeMismatch and layout tests (rev.4)
Update for the Part 2 change.
This patch depends on both of Part 1 and 2.
(In reply to comment #19)
> Created an attachment (id=40221) [details]
> Patch part 1: recognize date&time types as text fields (rev.4)
The attachment title was wrong. I corrected it to:
Patch part 3: ValidityState.typeMismatch and layout tests (rev.4)
Created attachment 40488[details]
Patch part 1: recognize date&time types as text fields (rev.4)
Resolved a build failure with new "switch (inputType())" introduced by r48959.
Comment on attachment 40488[details]
Patch part 1: recognize date&time types as text fields (rev.4)
366 // get() with unregistered names returns HTMLInputElement::TEXT.
Wild.
// get() with a null string makes crash.
// get() with a null string causes a crash.
would be better.
I would probably have written:
75 if (!t.isNull()) // get() with a null string makes crash.
376 newType = typeMap->get(t);
357377 else
358378 newType = TEXT;
as:
if (typeMap.contains(t))
newType = typeMap.get();
else
newType = TEXT;
Then you don't need any fancy emptyValue either.
You could do:
448 static const Vector<AtomicString>* createFormControlTypes()
as just an accessor and use a static Vector<AtomicString> w/o a pointer if you like. It's OK as is, but:
452 (*types)[HTMLInputElement::BUTTON] = "button";
is slightly harder to read wiht a pointer. I think at this point, I wouldn't bother changing it though.
43 TEXT = 0, // TEXT must be 0 because it's the default type.
is not needed if you change the way the hash lookup works, no?
68 static const int MAX_INPUT_TYPES = DATETIMELOCAL + 1;
Could be easier as a LAST_INPUT_TYPE a the end of the enum, no?
This looks great, but I think we shoudl go one more round. Thanks again!
(In reply to comment #24)
> // get() with a null string causes a crash.
> would be better.
Done.
> I would probably have written:
> 75 if (!t.isNull()) // get() with a null string makes crash.
> 376 newType = typeMap->get(t);
> 357377 else
> 358378 newType = TEXT;
>
> as:
>
> if (typeMap.contains(t))
> newType = typeMap.get();
> else
> newType = TEXT;
>
> Then you don't need any fancy emptyValue either.
Right. We don't need to assume TEXT=0 if we use contains().
I changed to contains(), but we still need t.isNull() because contains() with a null string also crashes.
> You could do:
> 448 static const Vector<AtomicString>* createFormControlTypes()
I changed the type to HashMap<InputType, AtomicString>. As for Vector<>, we need to ensure the minimum value of InputType is 0, need to know the maximum value of InputType, InputType values must not have gaps.
> 43 TEXT = 0, // TEXT must be 0 because it's the default type.
> 68 static const int MAX_INPUT_TYPES = DATETIMELOCAL + 1;
Removed them by the Vector -> HashMap change above.
Created attachment 42740[details]
Patch part 2: ISO 8601 parser (rev.4)
Move the code from JavaScritpCore/wtf to WebCore/html because GregorianDateTime became a JSC-specific class.
Comment on attachment 41478[details]
Patch part 1: recognize date&time types as text fields (rev.5)
It seems your test case only needs to test the casing once. once it's confirmed that button and BUTTON both map to BUTTON, you don't really need to check CHECKBOX, COLOR, EMail, etc. Just the lowercase versions should be enough and might make the test less confusing.
Cleanup of these mthods could have been done as a separate first patch, but this is OK too.
I suspect the dom spec says nothing about the implementation, but it does say that input.type has to be lowercase, right? Would be more clear to say something like:
// input.type must return a lower case value according to DOM3.
I dont understand this comment:
// We don't use formControlTypes->get(inputType()) because this function
542 // tries to return a reference to a temporary AtomicString object in that
543 // case.
This comment isn't clear:
509 // Needs to be lowercase according to DOM spec
Excellent cleanup!
794 if (inputType() == HIDDEN)
795 return false;
796 return HTMLFormControlElementWithState::rendererIsNeeded(style);
This patch looks fine. The comments could/should be adjusted before landing.
I'm torn. I would like to r+ this, but I would also like to understand the formControlTypes->get(inputType()) issue before I do. I guess we should go one more round. Ping me as soon as you post a new patch or respond to the formControlTypes->get(inputType()) issue and I'll be happy to r+ this.
Comment on attachment 42740[details]
Patch part 2: ISO 8601 parser (rev.4)
This patch desperately needs c++ unit test support. So sad that we don't have any in WebKit.
Created attachment 42918[details]
Patch part 1: recognize date&time types as text fields (rev.6)
(In reply to comment #31)
> It seems your test case only needs to test the casing once. once it's
> confirmed that button and BUTTON both map to BUTTON, you don't really need to
> check CHECKBOX, COLOR, EMail, etc. Just the lowercase versions should be
> enough and might make the test less confusing.
Done.
> I suspect the dom spec says nothing about the implementation, but it does say
> that input.type has to be lowercase, right? Would be more clear to say
> something like:
> // input.type must return a lower case value according to DOM3.
Done.
> I dont understand this comment:
> // We don't use formControlTypes->get(inputType()) because this function
> 542 // tries to return a reference to a temporary AtomicString object in
> that
> 543 // case.
I updated that comment. I hope it get clearer.
If we write "return formControlTypes->get(inputType());", gcc in Xcode warns it:
WebKit/WebCore/html/HTMLInputElement.cpp:547: warning: returning reference to temporary
> This comment isn't clear:
> 509 // Needs to be lowercase according to DOM spec
Improved.
Comment on attachment 42942[details]
Recognize date&time types as text fields (rev.7)
> + // get() or contains() with a null string causes a crash.
> + if (!t.isNull() && typeMap->contains(t))
> + newType = typeMap->get(t);
> else
> newType = TEXT;
It's not a good idiom for performance to do a contains followed by a separate get. Those are two completely separate hash table lookups. There are two alternatives:
1) Just call get without first checking contains. The result will be the default value, 0, which is TEXT.
2) Use find instead of contains/get.
I think "causes a crash" is also not the perfect way to explain the issue. Callers are not allowed to call get or contains with a null string. It's not guaranteed to cause a crash, though!
I also think the comment is a little strange because there are tons of call sites for this and I don't think we want to add a comment like this at every one.
> + // The values in the map must be lowercased because they will be the
> + // return values of input.type and it must be lowercase according to DOM Level 2.
> + types->add(HTMLInputElement::BUTTON, "button");
> + types->add(HTMLInputElement::CHECKBOX, "checkbox");
> + types->add(HTMLInputElement::COLOR, "color");
> + types->add(HTMLInputElement::DATE, "date");
> + types->add(HTMLInputElement::DATETIME, "datetime");
> + types->add(HTMLInputElement::DATETIMELOCAL, "datetime-local");
> + types->add(HTMLInputElement::EMAIL, "email");
> + types->add(HTMLInputElement::FILE, "file");
> + types->add(HTMLInputElement::HIDDEN, "hidden");
> + types->add(HTMLInputElement::IMAGE, "image");
> + types->add(HTMLInputElement::ISINDEX, emptyAtom);
> + types->add(HTMLInputElement::MONTH, "month");
> + types->add(HTMLInputElement::NUMBER, "number");
> + types->add(HTMLInputElement::PASSWORD, "password");
> + types->add(HTMLInputElement::RADIO, "radio");
> + types->add(HTMLInputElement::RANGE, "range");
> + types->add(HTMLInputElement::RESET, "reset");
> + types->add(HTMLInputElement::SEARCH, "search");
> + types->add(HTMLInputElement::SUBMIT, "submit");
> + types->add(HTMLInputElement::TELEPHONE, "tel");
> + types->add(HTMLInputElement::TEXT, "text");
> + types->add(HTMLInputElement::TIME, "time");
> + types->add(HTMLInputElement::URL, "url");
> + types->add(HTMLInputElement::WEEK, "week");
These values are enum values, consecutive integers. This should be done with an array, not a HashMap.
> + static const FormControlMap* formControlTypes = createFormControlTypes();
> + ASSERT(formControlTypes->contains(inputType()));
> + // Don't do "return formControlTypes->get(inputType())" here.
> + // In that case, compilers generate code like:
> + // AtomicString str = formControlTypes->get(inputType());
> + // return &str;
> + return formControlTypes->find(inputType())->second;
I don’t really like the comment above but it will be gone if you switch to an array anyway.
> bool HTMLInputElement::rendererIsNeeded(RenderStyle *style)
> {
> - switch (inputType()) {
> - case BUTTON:
> - case CHECKBOX:
> - case COLOR:
> - case EMAIL:
> - case FILE:
> - case IMAGE:
> - case ISINDEX:
> - case NUMBER:
> - case PASSWORD:
> - case RADIO:
> - case RANGE:
> - case RESET:
> - case SEARCH:
> - case SUBMIT:
> - case TELEPHONE:
> - case TEXT:
> - case URL:
> - return HTMLFormControlElementWithState::rendererIsNeeded(style);
> - case HIDDEN:
> - return false;
> - }
> - ASSERT(false);
> - return false;
> + if (inputType() == HIDDEN)
> + return false;
> + return HTMLFormControlElementWithState::rendererIsNeeded(style);
This change is fine assuming that no future type will be like "hidden". I guess that's a reasonable assumption.
The patch otherwise seems OK.
Created attachment 43216[details]
Recognize date&time types as text fields (rev.8)
Thank you for reviewing!
(In reply to comment #38)
> > + if (!t.isNull() && typeMap->contains(t))
> > + newType = typeMap->get(t);
> > else
> > newType = TEXT;
>
> It's not a good idiom for performance to do a contains followed by a separate
> get. Those are two completely separate hash table lookups. There are two
> alternatives:
>
> 1) Just call get without first checking contains. The result will be the
> default value, 0, which is TEXT
Done.
> I also think the comment is a little strange because there are tons of call
> sites for this and I don't think we want to add a comment like this at every
> one.
Removed the comment.
> > + types->add(HTMLInputElement::URL, "url");
> > + types->add(HTMLInputElement::WEEK, "week");
>
> These values are enum values, consecutive integers. This should be done with an
> array, not a HashMap.
Changed it to AtomicString[].
Comment on attachment 43216[details]
Recognize date&time types as text fields (rev.8)
Rejecting patch 43216 from commit-queue.
Failed to run "['WebKitTools/Scripts/run-webkit-tests', '--no-launch-safari', '--quiet', '--exit-after-n-failures=1']" exit_code: 1
Running build-dumprendertree
Running tests from /Users/eseidel/Projects/CommitQueue/LayoutTests
Testing 11624 test cases.
http/tests/xmlhttprequest/abort-crash.html -> crashed
Exiting early after 1 failures. 9148 tests run.
346.71s total testing time
9147 test cases (99%) succeeded
1 test case (<1%) crashed
5 test cases (<1%) had stderr output
Comment on attachment 43216[details]
Recognize date&time types as text fields (rev.8)
I may just need to turn off the commit-queue until bug 31461 is solved. :(
2009-09-07 02:06 PDT, Kent Tamura
2009-09-10 05:14 PDT, Kent Tamura
2009-09-10 05:15 PDT, Kent Tamura
2009-09-10 05:16 PDT, Kent Tamura
2009-09-13 18:50 PDT, Kent Tamura
2009-09-21 09:53 PDT, Kent Tamura
2009-09-23 19:43 PDT, Kent Tamura
2009-09-27 18:54 PDT, Kent Tamura
2009-09-28 00:36 PDT, Kent Tamura
2009-09-28 01:20 PDT, Kent Tamura
2009-10-01 18:18 PDT, Kent Tamura
2009-10-13 19:34 PDT, Kent Tamura
tkent: commit-queue-
2009-10-13 19:38 PDT, Kent Tamura
tkent: commit-queue-
2009-10-19 21:13 PDT, Kent Tamura
2009-11-09 01:36 PST, Kent Tamura
2009-11-09 01:38 PST, Kent Tamura
2009-11-10 19:54 PST, Kent Tamura
2009-11-11 02:10 PST, Kent Tamura
2009-11-13 17:30 PST, Kent Tamura