Commit 8a2eb6b0 authored by antti's avatar antti

LayoutTests:

        Reviewed by Adele.
        
        Test for http://bugs.webkit.org/show_bug.cgi?id=12595
        REGRESSION: Can't add item to cart at lnt.com (JS type error)
        <rdar://problem/4722863>
        
        Expanded version of Darin's test case. 

        * fast/forms/old-names-expected.txt: Added.
        * fast/forms/old-names.html: Added.

WebCore:

        Reviewed by Adele.

        Fix http://bugs.webkit.org/show_bug.cgi?id=12595
        REGRESSION: Can't add item to cart at lnt.com (JS type error)
        <rdar://problem/4722863>
        
        Emulate Firefox behavior where form elements accessed by a name
        can be accessed with that name later even if the name changes or
        even if element is removed from the document.
        
        This is loosely based on Darin's earlier patch for the same problem but
        is much less expansive. It takes somewhat different approach to more closely
        mimic Firefox behavior. Includes expanded test case.

        * bindings/js/JSHTMLFormElementCustom.cpp:
        (WebCore::JSHTMLFormElement::canGetItemsForName):
            Use new the HTMLFormElement::getNamedElements() method
        (WebCore::JSHTMLFormElement::nameGetter):
            Use new the HTMLFormElement::getNamedElements() method
        * html/HTMLFormElement.cpp:
        (WebCore::HTMLFormElement::HTMLFormElement):
        (WebCore::HTMLFormElement::~HTMLFormElement):
        (WebCore::HTMLFormElement::elementForAlias):
        (WebCore::HTMLFormElement::addElementAlias):
            Maintain a map of known element aliases
        (WebCore::HTMLFormElement::getNamedElements):
            Get a list of elements matching the name, based both their
            current names and known aliases (earlier names).
            Keep the alias list in sync.
        * html/HTMLFormElement.h:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@20260 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 31872c80
2007-03-17 Antti Koivisto <antti@apple.com>
Reviewed by Adele.
Test for http://bugs.webkit.org/show_bug.cgi?id=12595
REGRESSION: Can't add item to cart at lnt.com (JS type error)
<rdar://problem/4722863>
Expanded version of Darin's test case.
* fast/forms/old-names-expected.txt: Added.
* fast/forms/old-names.html: Added.
2007-03-16 Adele Peterson <adele@apple.com>
Reviewed by Hyatt.
This tests accessing form elements by name. IE only lets you look up names under the first name the element had and does not respond to name changes. Firefox remembers every name item has been accessed with, but forgets items that have not been accessed. This test has been written to expect the Firefox behavior.
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS form.length is 2
PASS form.original is a
PASS form.originalB is b
PASS form.second is undefined
PASS form.third is undefined
PASS form.elements.original is a
PASS form.elements.originalB is b
PASS form.elements.second is undefined
PASS form.elements.third is undefined
change the form item a's name to thisWillBeRemembered
get the variable value through form element
PASS form.thisWillBeRemembered is a
now change the form item a's name to thisWillBeRememberedToo
access it in boolean context
accessed form.thisWillBeRememberedToo
now change the form item a's name to thisWillBeForgotten
get the variable value through collection
PASS form.elements.thisWillBeForgotten is a
now change the form item a's name to thisWillBeForgottenToo, but don't access it afterwards
now change the form item a's name to second
PASS form.length is 2
PASS form.original is a
PASS form.originalB is b
PASS form.second is a
PASS form.third is undefined
PASS form.elements.original is undefined
PASS form.elements.originalB is b
PASS form.elements.second is a
PASS form.elements.third is undefined
now change the form item a's name to third
PASS form.length is 2
PASS form.original is a
PASS form.originalB is b
PASS form.second is a
PASS form.third is a
PASS form.elements.original is undefined
PASS form.elements.originalB is b
PASS form.elements.second is undefined
PASS form.elements.third is a
now change form item b's name to second
PASS form.length is 2
PASS form.original is a
PASS form.originalB is b
PASS form.second is b
PASS form.elements.original is undefined
PASS form.elements.originalB is undefined
PASS form.elements.second is b
now change a form item b's name to third
PASS form.length is 2
PASS form.original is a
PASS form.originalB is b
PASS form.second is b
PASS form.third.length is 2
PASS form.third[0] is a
PASS form.third[1] is b
PASS form.elements.original is undefined
PASS form.elements.originalB is undefined
PASS form.elements.second is undefined
PASS form.elements.third.length is 2
PASS form.elements.third[0] is a
PASS form.elements.third[1] is b
now change a form item b's name to fourth
PASS form.third is a
PASS form.third.length is undefined
PASS form.elements.third is a
PASS form.elements.third.length is undefined
now remove element a
PASS form.length is 1
PASS form.original is a
PASS form.originalB is b
PASS form.second is b
PASS form.third is a
PASS form.fourth is b
PASS form.elements.original is undefined
PASS form.elements.originalB is undefined
PASS form.elements.second is undefined
PASS form.elements.third is undefined
PASS form.elements.fourth is b
check we still remember names we should
PASS form.thisWillBeForgotten is undefined
PASS form.thisWillBeForgottenToo is undefined
PASS form.thisWillBeRemembered is a
PASS form.thisWillBeRememberedToo is a
PASS successfullyParsed is true
TEST COMPLETE
<html>
<head>
<link rel="stylesheet" type="text/css" href="../js/resources/js-test-style.css">
<script src="../js/resources/js-test-pre.js"></script>
<script>
function runTest()
{
description("This tests accessing form elements by name. "
+ "IE only lets you look up names under the first name the element had and "
+ "does not respond to name changes. Firefox remembers every name item has been "
+ "accessed with, but forgets items that have not been accessed. "
+ "This test has been written to expect the Firefox behavior.");
form = document.getElementById('form');
a = document.getElementById('a');
b = document.getElementById('b');
shouldBe('form.length', '2');
shouldBe('form.original', 'a');
shouldBe('form.originalB', 'b');
shouldBe('form.second', 'undefined');
shouldBe('form.third', 'undefined');
shouldBe('form.elements.original', 'a');
shouldBe('form.elements.originalB', 'b');
shouldBe('form.elements.second', 'undefined');
shouldBe('form.elements.third', 'undefined');
debug('');
debug("change the form item a's name to thisWillBeRemembered");
debug('');
a.name="thisWillBeRemembered";
debug("get the variable value through form element");
shouldBe('form.thisWillBeRemembered', 'a');
debug('');
debug("now change the form item a's name to thisWillBeRememberedToo");
debug("access it in boolean context");
a.name="thisWillBeRememberedToo";
debug('');
if (form.thisWillBeRememberedToo)
debug('accessed form.thisWillBeRememberedToo');
debug('');
debug("now change the form item a's name to thisWillBeForgotten");
debug('');
a.name="thisWillBeForgotten";
debug("get the variable value through collection");
shouldBe('form.elements.thisWillBeForgotten', 'a');
debug('');
debug("now change the form item a's name to thisWillBeForgottenToo, but don't access it afterwards");
a.name="thisWillBeForgottenToo";
debug('');
debug("now change the form item a's name to second");
debug('');
a.name="second";
shouldBe('form.length', '2');
shouldBe('form.original', 'a');
shouldBe('form.originalB', 'b');
shouldBe('form.second', 'a');
shouldBe('form.third', 'undefined');
shouldBe('form.elements.original', 'undefined');
shouldBe('form.elements.originalB', 'b');
shouldBe('form.elements.second', 'a');
shouldBe('form.elements.third', 'undefined');
debug('');
debug("now change the form item a's name to third");
debug('');
a.name="third";
shouldBe('form.length', '2');
shouldBe('form.original', 'a');
shouldBe('form.originalB', 'b');
shouldBe('form.second', 'a');
shouldBe('form.third', 'a');
shouldBe('form.elements.original', 'undefined');
shouldBe('form.elements.originalB', 'b');
shouldBe('form.elements.second', 'undefined');
shouldBe('form.elements.third', 'a');
debug('');
debug("now change form item b's name to second");
debug('');
b.name="second";
shouldBe('form.length', '2');
shouldBe('form.original', 'a');
shouldBe('form.originalB', 'b');
shouldBe('form.second', 'b');
shouldBe('form.elements.original', 'undefined');
shouldBe('form.elements.originalB', 'undefined');
shouldBe('form.elements.second', 'b');
debug('');
debug("now change a form item b's name to third");
debug('');
form.originalB.name="third";
shouldBe('form.length', '2');
shouldBe('form.original', 'a');
shouldBe('form.originalB', 'b');
shouldBe('form.second', 'b');
shouldBe('form.third.length', '2');
shouldBe('form.third[0]', 'a');
shouldBe('form.third[1]', 'b');
shouldBe('form.elements.original', 'undefined');
shouldBe('form.elements.originalB', 'undefined');
shouldBe('form.elements.second', 'undefined');
shouldBe('form.elements.third.length', '2');
shouldBe('form.elements.third[0]', 'a');
shouldBe('form.elements.third[1]', 'b');
debug('');
debug("now change a form item b's name to fourth");
debug('');
form.originalB.name="fourth";
shouldBe('form.third', 'a');
shouldBe('form.third.length', 'undefined');
shouldBe('form.elements.third', 'a');
shouldBe('form.elements.third.length', 'undefined');
debug('');
debug("now remove element a");
debug('');
form.removeChild(a);
shouldBe('form.length', '1');
shouldBe('form.original', 'a');
shouldBe('form.originalB', 'b');
shouldBe('form.second', 'b');
shouldBe('form.third', 'a');
shouldBe('form.fourth', 'b');
shouldBe('form.elements.original', 'undefined');
shouldBe('form.elements.originalB', 'undefined');
shouldBe('form.elements.second', 'undefined');
shouldBe('form.elements.third', 'undefined');
shouldBe('form.elements.fourth', 'b');
debug('');
debug("check we still remember names we should");
debug('');
shouldBe('form.thisWillBeForgotten', 'undefined');
shouldBe('form.thisWillBeForgottenToo', 'undefined');
shouldBe('form.thisWillBeRemembered', 'a');
shouldBe('form.thisWillBeRememberedToo', 'a');
debug('');
successfullyParsed = true;
}
</script>
</head>
<body>
<form id='form'>
<input type='hidden' id='a' name='original'>
<input type='hidden' id='b' name='originalB'>
</form>
<p id="description"></p>
<div id="console"></div>
<script>runTest();</script>
<script src="../js/resources/js-test-post.js"></script>
</body>
</html>
2007-03-17 Antti Koivisto <antti@apple.com>
Reviewed by Adele.
Fix http://bugs.webkit.org/show_bug.cgi?id=12595
REGRESSION: Can't add item to cart at lnt.com (JS type error)
<rdar://problem/4722863>
Emulate Firefox behavior where form elements accessed by a name
can be accessed with that name later even if the name changes or
even if element is removed from the document.
This is loosely based on Darin's earlier patch for the same problem but
is much less expansive. It takes somewhat different approach to more closely
mimic Firefox behavior. Includes expanded test case.
* bindings/js/JSHTMLFormElementCustom.cpp:
(WebCore::JSHTMLFormElement::canGetItemsForName):
Use new the HTMLFormElement::getNamedElements() method
(WebCore::JSHTMLFormElement::nameGetter):
Use new the HTMLFormElement::getNamedElements() method
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::HTMLFormElement):
(WebCore::HTMLFormElement::~HTMLFormElement):
(WebCore::HTMLFormElement::elementForAlias):
(WebCore::HTMLFormElement::addElementAlias):
Maintain a map of known element aliases
(WebCore::HTMLFormElement::getNamedElements):
Get a list of elements matching the name, based both their
current names and known aliases (earlier names).
Keep the alias list in sync.
* html/HTMLFormElement.h:
2007-03-17 Adele Peterson <adele@apple.com>
Reviewed by Hyatt.
......
......@@ -35,17 +35,23 @@ namespace WebCore {
bool JSHTMLFormElement::canGetItemsForName(ExecState* exec, HTMLFormElement* form, const AtomicString& propertyName)
{
// FIXME: ideally there should be a lighter-weight way of doing this
JSValue* namedItems = JSHTMLCollection(exec, form->elements().get()).getNamedItems(exec, propertyName);
return !namedItems->isUndefined();
Vector<RefPtr<Node> > namedItems;
form->getNamedElements(propertyName, namedItems);
return namedItems.size();
}
JSValue* JSHTMLFormElement::nameGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
{
JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase());
HTMLFormElement* form = static_cast<HTMLFormElement*>(thisObj->impl());
HTMLFormElement* form = static_cast<HTMLFormElement*>(static_cast<JSHTMLElement*>(slot.slotBase())->impl());
return JSHTMLCollection(exec, form->elements().get()).getNamedItems(exec, propertyName);
Vector<RefPtr<Node> > namedItems;
form->getNamedElements(propertyName, namedItems);
if (namedItems.size() == 1)
return toJS(exec, namedItems[0].get());
if (namedItems.size() > 1)
return new DOMNamedNodesCollection(exec, namedItems);
return jsUndefined();
}
}
......@@ -49,21 +49,23 @@ using namespace HTMLNames;
HTMLFormElement::HTMLFormElement(Document* doc)
: HTMLElement(formTag, doc)
, m_elementAliases(0)
, collectionInfo(0)
, m_enctype("application/x-www-form-urlencoded")
, m_post(false)
, m_multipart(false)
, m_autocomplete(true)
, m_insubmit(false)
, m_doingsubmit(false)
, m_inreset(false)
, m_malformed(false)
, m_preserveAcrossRemove(false)
{
collectionInfo = 0;
m_post = false;
m_multipart = false;
m_autocomplete = true;
m_insubmit = false;
m_doingsubmit = false;
m_inreset = false;
m_enctype = "application/x-www-form-urlencoded";
m_malformed = false;
m_preserveAcrossRemove = false;
}
HTMLFormElement::~HTMLFormElement()
{
delete m_elementAliases;
delete collectionInfo;
for (unsigned i = 0; i < formElements.size(); ++i)
......@@ -638,5 +640,44 @@ void HTMLFormElement::setTarget(const String &value)
{
setAttribute(targetAttr, value);
}
PassRefPtr<HTMLGenericFormElement> HTMLFormElement::elementForAlias(const AtomicString& alias)
{
if (alias.isEmpty() || !m_elementAliases)
return 0;
return m_elementAliases->get(alias.impl());
}
void HTMLFormElement::addElementAlias(HTMLGenericFormElement* element, const AtomicString& alias)
{
if (alias.isEmpty())
return;
if (!m_elementAliases)
m_elementAliases = new AliasMap;
m_elementAliases->set(alias.impl(), element);
}
void HTMLFormElement::getNamedElements(const AtomicString& name, Vector<RefPtr<Node> >& namedItems)
{
elements()->namedItems(name, namedItems);
// see if we have seen something with this name before
RefPtr<HTMLGenericFormElement> aliasElem;
if (aliasElem = elementForAlias(name)) {
bool found = false;
for (unsigned n = 0; n < namedItems.size(); n++) {
if (namedItems[n] == aliasElem.get()) {
found = true;
break;
}
}
if (!found)
// we have seen it before but it is gone now. still, we need to return it.
namedItems.append(aliasElem.get());
}
// name has been accessed, remember it
if (namedItems.size() && aliasElem != namedItems.first())
addElementAlias(static_cast<HTMLGenericFormElement*>(namedItems.first().get()), name);
}
} // namespace
......@@ -50,6 +50,8 @@ public:
virtual void handleLocalEvents(Event*, bool useCapture);
PassRefPtr<HTMLCollection> elements();
void getNamedElements(const AtomicString&, Vector<RefPtr<Node> >&);
unsigned length() const;
Node* item(unsigned index);
......@@ -98,6 +100,9 @@ public:
virtual String target() const;
void setTarget(const String&);
PassRefPtr<HTMLGenericFormElement> elementForAlias(const AtomicString&);
void addElementAlias(HTMLGenericFormElement*, const AtomicString& alias);
// FIXME: Change this to be private after getting rid of all the clients.
Vector<HTMLGenericFormElement*> formElements;
......@@ -109,13 +114,15 @@ private:
friend class HTMLFormCollection;
typedef HashMap<RefPtr<AtomicStringImpl>, RefPtr<HTMLGenericFormElement> > AliasMap;
AliasMap* m_elementAliases;
HTMLCollection::CollectionInfo* collectionInfo;
Vector<HTMLImageElement*> imgElements;
String m_url;
String m_target;
String m_enctype;
String m_boundary;
String m_acceptcharset;
bool m_post : 1;
bool m_multipart : 1;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment