Commit 2f06e491 authored by bdakin's avatar bdakin
Browse files

Rubber-stamped by Adele.

        Rolling out http://trac.webkit.org/projects/webkit/changeset/20148 
        (which is a fix for http://bugs.webkit.org/show_bug.cgi?id=12595 
        and rdar://4722863) because it causes a horrible memory-trasher.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@20214 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 16e4c706
2007-03-15 Beth Dakin <bdakin@apple.com>
Rubber-stamped by Adele.
Rolling out http://trac.webkit.org/projects/webkit/changeset/20148
(which is a fix for http://bugs.webkit.org/show_bug.cgi?id=12595
and rdar://4722863) because it causes a horrible memory-trasher.
* fast/forms/old-names-expected.txt: Removed.
* fast/forms/old-names.html: Removed.
2007-03-14 Oliver Hunt <oliver@apple.com>
 
Reviewed by Adele.
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 will let each element be looked up under its original name as long as no actual element has that name. This test has been written to expect the Firefox behavior. This original name quirk applies only to the syntax form.name and not to the form.elements collection.
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
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.item(0) is a
PASS form.third.item(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.item(0) is a
PASS form.elements.third.item(1) is b
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 b
PASS form.elements.original is undefined
PASS form.elements.originalB is undefined
PASS form.elements.second is undefined
PASS form.elements.third is b
<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 will let each element be looked "
+ "up under its original name as long as no actual element has that name. "
+ "This test has been written to expect the Firefox behavior. "
+ "This original name quirk applies only to the syntax form.name and not to "
+ "the form.elements collection.");
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("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.item(0)', 'a');
shouldBe('form.third.item(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.item(0)', 'a');
shouldBe('form.elements.third.item(1)', 'b');
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', 'b');
shouldBe('form.elements.original', 'undefined');
shouldBe('form.elements.originalB', 'undefined');
shouldBe('form.elements.second', 'undefined');
shouldBe('form.elements.third', 'b');
}
</script>
</head>
<body onload="runTest()">
<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>
</body>
</html>
2007-03-15 Beth Dakin <bdakin@apple.com>
Rubber-stamped by Adele.
Rolling out http://trac.webkit.org/projects/webkit/changeset/20148
(which is a fix for http://bugs.webkit.org/show_bug.cgi?id=12595
and rdar://4722863) because it causes a horrible memory-trasher.
* bindings/js/JSHTMLFormElementCustom.cpp:
(WebCore::JSHTMLFormElement::canGetItemsForName):
(WebCore::JSHTMLFormElement::nameGetter):
* bindings/js/kjs_dom.cpp:
(KJS::):
(KJS::DOMNamedNodesCollection::DOMNamedNodesCollection):
(KJS::DOMNamedNodesCollection::lengthGetter):
(KJS::DOMNamedNodesCollection::indexGetter):
(KJS::DOMNamedNodesCollection::getOwnPropertySlot):
* bindings/js/kjs_dom.h:
(KJS::DOMNamedNodesCollection::classInfo):
* bindings/js/kjs_html.cpp:
(KJS::JSHTMLCollection::getNamedItems):
* dom/ChildNodeList.cpp:
(WebCore::ChildNodeList::ChildNodeList):
(WebCore::ChildNodeList::length):
(WebCore::ChildNodeList::item):
(WebCore::ChildNodeList::nodeMatches):
* dom/ChildNodeList.h:
* dom/NameNodeList.cpp:
(WebCore::NameNodeList::NameNodeList):
(WebCore::NameNodeList::item):
(WebCore::NameNodeList::nodeMatches):
* dom/NameNodeList.h:
(WebCore::NameNodeList::rootNodeAttributeChanged):
* dom/Node.cpp:
(WebCore::TagNodeList::TagNodeList):
(WebCore::TagNodeList::nodeMatches):
(WebCore::Node::registerNodeList):
(WebCore::Node::unregisterNodeList):
* dom/Node.h:
* dom/NodeList.cpp:
(WebCore::NodeList::NodeList):
(WebCore::NodeList::~NodeList):
(WebCore::NodeList::recursiveLength):
(WebCore::NodeList::itemForwardsFromCurrent):
(WebCore::NodeList::itemBackwardsFromCurrent):
(WebCore::NodeList::recursiveItem):
(WebCore::NodeList::itemWithName):
(WebCore::NodeList::rootNodeChildrenChanged):
* dom/NodeList.h:
(WebCore::NodeList::rootNodeAttributeChanged):
* html/HTMLFormElement.cpp:
(WebCore::HTMLFormElement::HTMLFormElement):
(WebCore::HTMLFormElement::~HTMLFormElement):
(WebCore::HTMLFormElement::formData):
(WebCore::HTMLFormElement::parseMappedAttribute):
(WebCore::HTMLFormElement::removeFormElement):
* html/HTMLFormElement.h:
* html/HTMLGenericFormElement.cpp:
(WebCore::HTMLGenericFormElement::parseMappedAttribute):
(WebCore::HTMLGenericFormElement::insertedIntoTree):
* html/HTMLGenericFormElement.h:
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::parseMappedAttribute):
2007-03-15 Geoffrey Garen <ggaren@apple.com>
 
Added an assert to help catch a bug. Hopefully someone will hit it!
......
/*
* Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
......@@ -26,9 +26,8 @@
#include "config.h"
#include "JSHTMLFormElement.h"
#include "HTMLCollection.h"
#include "HTMLGenericFormElement.h"
#include "HTMLFormElement.h"
#include "HTMLCollection.h"
using namespace KJS;
......@@ -36,18 +35,17 @@ namespace WebCore {
bool JSHTMLFormElement::canGetItemsForName(ExecState* exec, HTMLFormElement* form, const AtomicString& propertyName)
{
if (!JSHTMLCollection(exec, form->elements().get()).getNamedItems(exec, propertyName)->isUndefined())
return true;
return !!form->oldNamedElement(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();
}
JSValue* JSHTMLFormElement::nameGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
{
HTMLFormElement* form = static_cast<HTMLFormElement*>(static_cast<JSHTMLElement*>(slot.slotBase())->impl());
JSValue* items = JSHTMLCollection(exec, form->elements().get()).getNamedItems(exec, propertyName);
if (!items->isUndefined())
return items;
return toJS(exec, form->oldNamedElement(propertyName));
JSHTMLElement* thisObj = static_cast<JSHTMLElement*>(slot.slotBase());
HTMLFormElement* form = static_cast<HTMLFormElement*>(thisObj->impl());
return JSHTMLCollection(exec, form->elements().get()).getNamedItems(exec, propertyName);
}
}
......@@ -1121,4 +1121,59 @@ JSObject* getDOMExceptionConstructor(ExecState* exec)
return cacheGlobalObject<DOMExceptionConstructor>(exec, "[[DOMException.constructor]]");
}
// -------------------------------------------------------------------------
const ClassInfo DOMNamedNodesCollection::info = { "Collection", 0, 0, 0 };
// Such a collection is usually very short-lived, it only exists
// for constructs like document.forms.<name>[1],
// so it shouldn't be a problem that it's storing all the nodes (with the same name). (David)
DOMNamedNodesCollection::DOMNamedNodesCollection(ExecState* exec, const Vector<RefPtr<Node> >& nodes)
: m_nodes(nodes)
{
setPrototype(exec->lexicalInterpreter()->builtinObjectPrototype());
}
JSValue* DOMNamedNodesCollection::lengthGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection*>(slot.slotBase());
return jsNumber(thisObj->m_nodes.size());
}
JSValue* DOMNamedNodesCollection::indexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
{
DOMNamedNodesCollection *thisObj = static_cast<DOMNamedNodesCollection*>(slot.slotBase());
return toJS(exec, thisObj->m_nodes[slot.index()].get());
}
bool DOMNamedNodesCollection::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
{
if (propertyName == lengthPropertyName) {
slot.setCustom(this, lengthGetter);
return true;
}
// array index ?
bool ok;
unsigned idx = propertyName.toUInt32(&ok);
if (ok && idx < m_nodes.size()) {
slot.setCustomIndex(this, idx, indexGetter);
return true;
}
// For IE compatibility, we need to be able to look up elements in a
// document.formName.name result by id as well as be index.
AtomicString atomicPropertyName = propertyName;
for (unsigned i = 0; i < m_nodes.size(); i++) {
Node* node = m_nodes[i].get();
if (node->hasAttributes() && node->attributes()->id() == atomicPropertyName) {
slot.setCustomIndex(this, i, indexGetter);
return true;
}
}
return DOMObject::getOwnPropertySlot(exec, propertyName, slot);
}
} // namespace
......@@ -142,6 +142,21 @@ namespace KJS {
JSObject* getNodeConstructor(ExecState*);
JSObject* getDOMExceptionConstructor(ExecState*);
// Internal class, used for the collection return by e.g. document.forms.myinput
// when multiple nodes have the same name.
class DOMNamedNodesCollection : public DOMObject {
public:
DOMNamedNodesCollection(ExecState *exec, const Vector<RefPtr<WebCore::Node> >& nodes);
virtual bool getOwnPropertySlot(ExecState *, const Identifier&, PropertySlot&);
virtual const ClassInfo* classInfo() const { return &info; }
static const ClassInfo info;
private:
static JSValue *lengthGetter(ExecState* exec, JSObject *, const Identifier&, const PropertySlot& slot);
static JSValue *indexGetter(ExecState* exec, JSObject *, const Identifier&, const PropertySlot& slot);
Vector<RefPtr<WebCore::Node> > m_nodes;
};
} // namespace
#endif
// -*- c-basic-offset: 4 -*-
/*
* This file is part of the KDE libraries
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
* Copyright (C) 2004, 2005, 2006 Apple Computer, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
......@@ -68,17 +69,6 @@ using namespace EventNames;
namespace KJS {
class VectorNodeList : public NodeList {
public:
VectorNodeList(const Vector<RefPtr<Node> >& nodes) : m_nodes(nodes) { }
virtual unsigned length() const { return m_nodes.size(); }
virtual Node* item(unsigned index) const { return index < m_nodes.size() ? m_nodes[index].get() : 0; }
private:
Vector<RefPtr<Node> > m_nodes;
};
class HTMLElementFunction : public InternalFunctionImp {
public:
HTMLElementFunction(ExecState* exec, int i, int len, const Identifier& name);
......@@ -1560,7 +1550,7 @@ JSValue *JSHTMLCollection::getNamedItems(ExecState* exec, const Identifier &prop
if (namedItems.size() == 1)
return toJS(exec, namedItems[0].get());
return toJS(exec, new VectorNodeList(namedItems));
return new DOMNamedNodesCollection(exec, namedItems);
}
JSValue* JSHTMLCollectionPrototypeFunction::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
......
......@@ -24,15 +24,14 @@
#include "config.h"
#include "ChildNodeList.h"
#include "Element.h"
#include "Node.h"
using namespace WebCore;
namespace WebCore {
ChildNodeList::ChildNodeList(Node* n)
: TreeNodeList(n)
ChildNodeList::ChildNodeList( Node *n )
: NodeList(n)
{
}
......@@ -42,7 +41,8 @@ unsigned ChildNodeList::length() const
return cachedLength;
unsigned len = 0;
for (Node* n = rootNode->firstChild(); n; n = n->nextSibling())
Node *n;
for(n = rootNode->firstChild(); n != 0; n = n->nextSibling())
len++;
cachedLength = len;
......@@ -51,10 +51,10 @@ unsigned ChildNodeList::length() const
return len;
}
Node *ChildNodeList::item(unsigned index) const
Node *ChildNodeList::item ( unsigned index ) const
{
unsigned int pos = 0;
Node* n = rootNode->firstChild();
Node *n = rootNode->firstChild();
if (isItemCacheValid) {
if (index == lastItemOffset) {
......@@ -80,9 +80,9 @@ Node *ChildNodeList::item(unsigned index) const
return 0;
}
bool ChildNodeList::elementMatches(Element* element) const
bool ChildNodeList::nodeMatches(Node *testNode) const
{
return element->parentNode() == rootNode;
return testNode->parentNode() == rootNode;
}
}
......@@ -29,7 +29,7 @@
namespace WebCore {
class ChildNodeList : public TreeNodeList {
class ChildNodeList : public NodeList {
public:
ChildNodeList(Node*);
......@@ -37,7 +37,7 @@ public:
virtual Node* item(unsigned index) const;
protected:
virtual bool elementMatches(Element*) const;
virtual bool nodeMatches(Node* testNode) const;
};
} // namespace WebCore
......
......@@ -28,13 +28,14 @@
#include "Element.h"
#include "HTMLNames.h"
using namespace WebCore;
namespace WebCore {
using namespace HTMLNames;
NameNodeList::NameNodeList(Node* n, const String &t)
: TreeNodeList(n)
, nodeName(t)
NameNodeList::NameNodeList(Node *n, const String &t)
: NodeList(n), nodeName(t)
{
}
......@@ -43,14 +44,14 @@ unsigned NameNodeList::length() const
return recursiveLength();
}
Node *NameNodeList::item(unsigned index) const
Node *NameNodeList::item (unsigned index) const
{
return recursiveItem(index);
}
bool NameNodeList::elementMatches(Element* element) const
bool NameNodeList::nodeMatches(Node *testNode) const
{
return element->getAttribute(nameAttr) == nodeName;
return static_cast<Element*>(testNode)->getAttribute(nameAttr) == nodeName;
}
}
......@@ -33,7 +33,7 @@ namespace WebCore {
/**
* NodeList which lists all Nodes in a Element with a given "name=" tag
*/
class NameNodeList : public TreeNodeList {
class NameNodeList : public NodeList {
public:
NameNodeList(Node* doc, const String& name);
......@@ -44,10 +44,10 @@ public:
// Other methods (not part of DOM)
virtual void rootNodeChildrenChanged() { }
virtual void rootNodeAttributeChanged() { TreeNodeList::rootNodeChildrenChanged(); }
virtual void rootNodeAttributeChanged() { NodeList::rootNodeChildrenChanged(); }
protected:
virtual bool elementMatches(Element*) const;
virtual bool nodeMatches(Node* testNode) const;
String nodeName;
};
......
......@@ -50,22 +50,26 @@ using namespace HTMLNames;
/**
* NodeList which lists all Nodes in a document with a given tag name
*/
class TagNodeList : public TreeNodeList {
class TagNodeList : public NodeList
{
public:
TagNodeList(Node*, const AtomicString& namespaceURI, const AtomicString& localName);
TagNodeList(Node *n, const AtomicString& namespaceURI, const AtomicString& localName);
// DOM methods overridden from parent classes
virtual unsigned length() const;
virtual Node *item(unsigned index) const;
virtual Node *item (unsigned index) const;
// Other methods (not part of DOM)
protected:
virtual bool elementMatches(Element*) const;
virtual bool nodeMatches(Node *testNode) const;
AtomicString m_namespaceURI;
AtomicString m_localName;
};
TagNodeList::TagNodeList(Node *n, const AtomicString& namespaceURI, const AtomicString& localName)
: TreeNodeList(n),
: NodeList(n),
m_namespaceURI(namespaceURI),
m_localName(localName)