Commit c254287d authored by jl@opera.com's avatar jl@opera.com

Use union types for HTMLSelectElement.add()'s arguments

According to the specification, the first argument should be
  (HTMLOptionElement or HTMLOptGroupElement)
and the second argument should be
  (HTMLElement or long)?
(and also be optional and default to null).

This changes behavior for the first argument (previously HTMLElement)
where a call was a silent no-op for invalid element types, and where
HTMLHRElement was allowed against the specification and with no
observable effects.

The new behavior is to throw TypeError for all invalid arguments, which is
compatible with Firefox and MSIE.

Also apply the same change to HTMLOptionsCollection.add(), which is little
more than a short-hand for calling add() on the owning select element.
Also drop the custom bindings implementation for that method, which was
essentially implementing the unionized second argument.

The behavior of HTMLOptionsCollection.add() is changed to ignore all
invalid (out of range) integer second arguments, rather than to throw for
negative ones below than -1. This change is also per specification and
compatible with other implementations.

BUG=430337

Review URL: https://codereview.chromium.org/716773002

git-svn-id: svn://svn.chromium.org/blink/trunk@185199 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent dfdb65e7
......@@ -70,7 +70,7 @@ PASS mySelect.selectedIndex is -1
PASS mySelect.options.length is 10
PASS mySelect.selectedIndex is -1
23) trying to add a non-option element
PASS mySelect.options.add({}) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS mySelect.options.add({}) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS mySelect.options.length is 10
PASS mySelect.selectedIndex is -1
......
......@@ -12,10 +12,10 @@ PASS aNode.isSameNode(void 0) is false
PASS aNode.lookupPrefix(aDOMImplementation) is null
PASS aNode.lookupPrefix(void 0) is null
PASS aNode.cloneNode(aDOMImplementation) instanceof HTMLDivElement is true
PASS aSelect.add(aDOMImplementation, aDOMImplementation) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS aSelect.add(aDOMImplementation, anOption) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS aSelect.add(void 0, void 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS aSelect.add(void 0, anOption) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS aSelect.add(aDOMImplementation, aDOMImplementation) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS aSelect.add(aDOMImplementation, anOption) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS aSelect.add(void 0, void 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS aSelect.add(void 0, anOption) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS aSelect.add(anOption, aDOMImplementation) is undefined.
PASS aSelect.add(anOption, void 0) is undefined.
PASS successfullyParsed is true
......
......@@ -18,12 +18,12 @@ PASS addOption(Infinity) is "X,0,1,2"
PASS addOption(-Infinity) is "X,0,1,2"
PASS addOption("foo") is "X,0,1,2"
PASS select.add() threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': 1 argument required, but only 0 present..
PASS select.add("foo") threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add("foo", 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add(undefined) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add(undefined, 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add(null) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add(null, 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add("foo") threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS select.add("foo", 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS select.add(undefined) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS select.add(undefined, 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS select.add(null) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS select.add(null, 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS getSelectOptions() is "0,X,Y,1,2"
Test select multiple
PASS addOption(0) is "X,0,1,2"
......@@ -40,12 +40,12 @@ PASS addOption(Infinity) is "X,0,1,2"
PASS addOption(-Infinity) is "X,0,1,2"
PASS addOption("foo") is "X,0,1,2"
PASS select.add() threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': 1 argument required, but only 0 present..
PASS select.add("foo") threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add("foo", 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add(undefined) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add(undefined, 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add(null) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add(null, 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': parameter 1 is not of type 'HTMLElement'..
PASS select.add("foo") threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS select.add("foo", 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS select.add(undefined) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS select.add(undefined, 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS select.add(null) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS select.add(null, 0) threw exception TypeError: Failed to execute 'add' on 'HTMLSelectElement': Not a valid union member..
PASS getSelectOptions() is "0,X,Y,1,2"
PASS successfullyParsed is true
......
......@@ -237,91 +237,91 @@ debug("");
debug("2.8 Add an Option at index -2");
option2 = document.createElement("OPTION");
shouldThrow("select2.options.add(option2, -2)");
shouldBe("select2.options.length", "7");
shouldNotThrow("select2.options.add(option2, -2)");
shouldBe("select2.options.length", "8");
shouldBe("select2.selectedIndex", "1");
debug("");
debug("2.9 Add an Option at index -Infinity");
option2 = document.createElement("OPTION");
shouldNotThrow("select2.options.add(option2, -1/0)");
shouldBe("select2.options.length", "8");
shouldBe("select2.options.length", "9");
shouldBe("select2.selectedIndex", "2");
debug("");
debug("2.10 Add an Option at index NaN");
option2 = document.createElement("OPTION");
shouldNotThrow("select2.options.add(option2, 0/0)");
shouldBe("select2.options.length", "9");
shouldBe("select2.options.length", "10");
shouldBe("select2.selectedIndex", "3");
debug("");
debug("2.11 Add an Option at index Infinity");
option2 = document.createElement("OPTION");
shouldNotThrow("select2.options.add(option2, 1/0)");
shouldBe("select2.options.length", "10");
shouldBe("select2.options.length", "11");
shouldBe("select2.selectedIndex", "4");
debug("");
debug("2.12 Add a non-Option element");
option2 = document.createElement("DIV");
shouldThrow("select2.options.add(option2, 1)");
shouldBe("select2.options.length", "10");
shouldBe("select2.options.length", "11");
shouldBe("select2.selectedIndex", "4");
debug("");
debug("2.13 Add a non-element (string)");
option2 = "o";
shouldThrow("select2.options.add(option2, 1)");
shouldBe("select2.options.length", "10");
shouldBe("select2.options.length", "11");
shouldBe("select2.selectedIndex", "4");
debug("");
debug("2.14 Add a non-element (number)");
option2 = 3.14;
shouldThrow("select2.options.add(option2, 1)");
shouldBe("select2.options.length", "10");
shouldBe("select2.options.length", "11");
shouldBe("select2.selectedIndex", "4");
debug("");
debug("2.15 Add a non-element (boolean)");
option2 = true;
shouldThrow("select2.options.add(option2, 1)");
shouldBe("select2.options.length", "10");
shouldBe("select2.options.length", "11");
shouldBe("select2.selectedIndex", "4");
debug("");
debug("2.16 Add undefined");
option2 = undefined;
shouldThrow("select2.options.add(option2, 1)");
shouldBe("select2.options.length", "10");
shouldBe("select2.options.length", "11");
shouldBe("select2.selectedIndex", "4");
debug("");
debug("2.17 Add null");
option2 = null;
shouldThrow("select2.options.add(option2, 1)");
shouldBe("select2.options.length", "10");
shouldBe("select2.options.length", "11");
shouldBe("select2.selectedIndex", "4");
debug("");
debug("2.18 Add negative infinity");
option2 = -1/0;
shouldThrow("select2.options.add(option2, 1)");
shouldBe("select2.options.length", "10");
shouldBe("select2.options.length", "11");
shouldBe("select2.selectedIndex", "4");
debug("");
debug("2.19 Add NaN");
option2 = 0/0;
shouldThrow("select2.options.add(option2, 1)");
shouldBe("select2.options.length", "10");
shouldBe("select2.options.length", "11");
shouldBe("select2.selectedIndex", "4");
debug("");
debug("2.20 Add positive infinity");
option2 = 1/0;
shouldThrow("select2.options.add(option2, 1)");
shouldBe("select2.options.length", "10");
shouldBe("select2.options.length", "11");
shouldBe("select2.selectedIndex", "4");
debug("");
......@@ -29,47 +29,47 @@ PASS select1.options[2].value is '3'
PASS select1.options[2].textContent is 'C'
1.4 Add a non-Option element
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select1.options.length is 3
PASS select1.selectedIndex is 0
1.5 Add a non-element (string)
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select1.options.length is 3
PASS select1.selectedIndex is 0
1.6 Add a non-element (number)
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select1.options.length is 3
PASS select1.selectedIndex is 0
1.7 Add a non-element (boolean)
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select1.options.length is 3
PASS select1.selectedIndex is 0
1.8 Add undefined
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select1.options.length is 3
PASS select1.selectedIndex is 0
1.9 Add null
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select1.options.length is 3
PASS select1.selectedIndex is 0
1.10 Add negative infinity
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select1.options.length is 3
PASS select1.selectedIndex is 0
1.11 Add NaN
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select1.options.length is 3
PASS select1.selectedIndex is 0
1.12 Add positive infinity
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select1.options.add(option1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select1.options.length is 3
PASS select1.selectedIndex is 0
......@@ -158,68 +158,68 @@ PASS select2.options[6].value is '5'
PASS select2.options[6].textContent is 'E'
2.8 Add an Option at index -2
PASS select2.options.add(option2, -2) threw exception IndexSizeError: Failed to execute 'add' on 'HTMLOptionsCollection': The index provided (-2) is less than -1..
PASS select2.options.length is 7
PASS select2.options.add(option2, -2) did not throw exception.
PASS select2.options.length is 8
PASS select2.selectedIndex is 1
2.9 Add an Option at index -Infinity
PASS select2.options.add(option2, -1/0) did not throw exception.
PASS select2.options.length is 8
PASS select2.options.length is 9
PASS select2.selectedIndex is 2
2.10 Add an Option at index NaN
PASS select2.options.add(option2, 0/0) did not throw exception.
PASS select2.options.length is 9
PASS select2.options.length is 10
PASS select2.selectedIndex is 3
2.11 Add an Option at index Infinity
PASS select2.options.add(option2, 1/0) did not throw exception.
PASS select2.options.length is 10
PASS select2.options.length is 11
PASS select2.selectedIndex is 4
2.12 Add a non-Option element
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select2.options.length is 10
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select2.options.length is 11
PASS select2.selectedIndex is 4
2.13 Add a non-element (string)
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select2.options.length is 10
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select2.options.length is 11
PASS select2.selectedIndex is 4
2.14 Add a non-element (number)
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select2.options.length is 10
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select2.options.length is 11
PASS select2.selectedIndex is 4
2.15 Add a non-element (boolean)
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select2.options.length is 10
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select2.options.length is 11
PASS select2.selectedIndex is 4
2.16 Add undefined
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select2.options.length is 10
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select2.options.length is 11
PASS select2.selectedIndex is 4
2.17 Add null
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select2.options.length is 10
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select2.options.length is 11
PASS select2.selectedIndex is 4
2.18 Add negative infinity
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select2.options.length is 10
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select2.options.length is 11
PASS select2.selectedIndex is 4
2.19 Add NaN
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select2.options.length is 10
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select2.options.length is 11
PASS select2.selectedIndex is 4
2.20 Add positive infinity
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': The element provided was not an HTMLOptionElement..
PASS select2.options.length is 10
PASS select2.options.add(option2, 1) threw exception TypeError: Failed to execute 'add' on 'HTMLOptionsCollection': Not a valid union member..
PASS select2.options.length is 11
PASS select2.selectedIndex is 4
PASS successfullyParsed is true
......
......@@ -43,29 +43,6 @@
namespace blink {
void V8HTMLOptionsCollection::addMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info)
{
ExceptionState exceptionState(ExceptionState::ExecutionContext, "add", "HTMLOptionsCollection", info.Holder(), info.GetIsolate());
if (!V8HTMLOptionElement::hasInstance(info[0], info.GetIsolate())) {
exceptionState.throwTypeError("The element provided was not an HTMLOptionElement.");
} else {
HTMLOptionsCollection* impl = V8HTMLOptionsCollection::toImpl(info.Holder());
HTMLOptionElement* option = V8HTMLOptionElement::toImpl(v8::Handle<v8::Object>(v8::Handle<v8::Object>::Cast(info[0])));
if (info.Length() < 2) {
impl->add(option, exceptionState);
} else {
int index = toInt32(info[1], exceptionState);
if (exceptionState.throwIfNeeded())
return;
impl->add(option, index, exceptionState);
}
}
exceptionState.throwIfNeeded();
}
void V8HTMLOptionsCollection::lengthAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info)
{
HTMLOptionsCollection* impl = V8HTMLOptionsCollection::toImpl(info.Holder());
......
......@@ -12,6 +12,17 @@ UNION_H_INCLUDES = frozenset([
'platform/heap/Handle.h',
])
UNION_CPP_INCLUDES_BLACKLIST = frozenset([
# This header defines static functions needed to implement event handler
# attributes in interfaces that implement GlobalEventHandlers. They are not
# needed or used by UnionTypes*.cpp, so including the header causes
# compilation errors.
# FIXME: We should solve this problem in a way that doesn't involve special-
# casing a header like this.
'core/dom/GlobalEventHandlers.h',
])
cpp_includes = set()
header_forward_decls = set()
......@@ -39,7 +50,7 @@ def union_context(union_types, interfaces_info):
return {
'containers': [container_context(union_type, interfaces_info)
for union_type in union_types_for_containers],
'cpp_includes': sorted(cpp_includes),
'cpp_includes': sorted(cpp_includes - UNION_CPP_INCLUDES_BLACKLIST),
'header_forward_decls': sorted(header_forward_decls),
'header_includes': sorted(UNION_H_INCLUDES),
'nullable_cpp_types': nullable_cpp_types,
......
......@@ -69,33 +69,9 @@ PassRefPtrWillBeRawPtr<HTMLOptionsCollection> HTMLOptionsCollection::create(Cont
return adoptRefWillBeNoop(new HTMLOptionsCollection(select));
}
void HTMLOptionsCollection::add(PassRefPtrWillBeRawPtr<HTMLOptionElement> element, ExceptionState& exceptionState)
void HTMLOptionsCollection::add(const HTMLOptionElementOrHTMLOptGroupElement& element, const HTMLElementOrLong& before, ExceptionState& exceptionState)
{
add(element, length(), exceptionState);
}
void HTMLOptionsCollection::add(PassRefPtrWillBeRawPtr<HTMLOptionElement> element, int index, ExceptionState& exceptionState)
{
HTMLOptionElement* newOption = element.get();
if (!newOption) {
exceptionState.throwTypeError("The element provided was not an HTMLOptionElement.");
return;
}
if (index < -1) {
exceptionState.throwDOMException(IndexSizeError, "The index provided (" + String::number(index) + ") is less than -1.");
return;
}
HTMLSelectElement& select = toHTMLSelectElement(ownerNode());
if (index == -1 || unsigned(index) >= length())
select.add(newOption, 0, exceptionState);
else
select.addBeforeOptionAtIndex(newOption, index, exceptionState);
ASSERT(!exceptionState.hadException());
toHTMLSelectElement(ownerNode()).add(element, before, exceptionState);
}
void HTMLOptionsCollection::remove(int index)
......
......@@ -30,6 +30,8 @@
namespace blink {
class ExceptionState;
class HTMLOptionElementOrHTMLOptGroupElement;
class HTMLElementOrLong;
class NodeListOrElement;
class HTMLOptionsCollection final : public HTMLCollection {
......@@ -39,8 +41,7 @@ public:
HTMLOptionElement* item(unsigned offset) const { return toHTMLOptionElement(HTMLCollection::item(offset)); }
void add(PassRefPtrWillBeRawPtr<HTMLOptionElement>, ExceptionState&);
void add(PassRefPtrWillBeRawPtr<HTMLOptionElement>, int index, ExceptionState&);
void add(const HTMLOptionElementOrHTMLOptGroupElement&, const HTMLElementOrLong&, ExceptionState&);
void remove(int index);
int selectedIndex() const;
......
......@@ -31,6 +31,7 @@
// FIXME: The spec and firefox return an Element (the first matching Element).
[ImplementedAs=namedGetter] getter (NodeList or Element)? namedItem(DOMString name);
[Custom, RaisesException] void add([Default=Undefined] optional HTMLOptionElement option, optional unsigned long index);
[RaisesException, TypeChecking=Interface] void add((HTMLOptionElement or HTMLOptGroupElement) element,
optional (HTMLElement or long)? before = null);
void remove(unsigned long index);
};
......@@ -31,6 +31,7 @@
#include "bindings/core/v8/ExceptionMessages.h"
#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "bindings/core/v8/UnionTypesCore.h"
#include "core/HTMLNames.h"
#include "core/accessibility/AXObjectCache.h"
#include "core/dom/Attribute.h"
......@@ -211,24 +212,27 @@ int HTMLSelectElement::activeSelectionEndListIndex() const
return lastSelectedListIndex();
}
void HTMLSelectElement::add(HTMLElement* element, HTMLElement* before, ExceptionState& exceptionState)
void HTMLSelectElement::add(const HTMLOptionElementOrHTMLOptGroupElement& element, const HTMLElementOrLong& before, ExceptionState& exceptionState)
{
// Make sure the element is ref'd and deref'd so we don't leak it.
RefPtrWillBeRawPtr<HTMLElement> protectNewChild(element);
RefPtrWillBeRawPtr<HTMLElement> elementToInsert;
ASSERT(!element.isNull());
if (element.isHTMLOptionElement())
elementToInsert = element.getAsHTMLOptionElement();
else
elementToInsert = element.getAsHTMLOptGroupElement();
if (!element || !(isHTMLOptionElement(element) || isHTMLOptGroupElement(element) || isHTMLHRElement(element)))
return;
RefPtrWillBeRawPtr<HTMLElement> beforeElement;
if (before.isHTMLElement())
beforeElement = before.getAsHTMLElement();
else if (before.isLong())
beforeElement = options()->item(before.getAsLong());
else
beforeElement = nullptr;
insertBefore(element, before, exceptionState);
insertBefore(elementToInsert, beforeElement.get(), exceptionState);
setNeedsValidityCheck();
}
void HTMLSelectElement::addBeforeOptionAtIndex(HTMLElement* element, int beforeIndex, ExceptionState& exceptionState)
{
HTMLOptionElement* beforeElement = options()->item(beforeIndex);
add(element, beforeElement, exceptionState);
}
void HTMLSelectElement::remove(int optionIndex)
{
int listIndex = optionToListIndex(optionIndex);
......@@ -465,18 +469,20 @@ void HTMLSelectElement::setOption(unsigned index, HTMLOptionElement* option, Exc
if (index > maxSelectItems - 1)
index = maxSelectItems - 1;
int diff = index - length();
RefPtrWillBeRawPtr<HTMLOptionElement> before = nullptr;
HTMLOptionElementOrHTMLOptGroupElement element;
element.setHTMLOptionElement(option);
HTMLElementOrLong before;
// Out of array bounds? First insert empty dummies.
if (diff > 0) {
setLength(index, exceptionState);
// Replace an existing entry?
} else if (diff < 0) {
before = options()->item(index + 1);
before.setHTMLElement(options()->item(index + 1));
remove(index);
}
// Finally add the new element.
if (!exceptionState.hadException()) {
add(option, before.get(), exceptionState);
add(element, before, exceptionState);
if (diff >= 0 && option->selected())
optionSelectionStateChanged(option, true);
}
......@@ -490,9 +496,7 @@ void HTMLSelectElement::setLength(unsigned newLen, ExceptionState& exceptionStat
if (diff < 0) { // Add dummy elements.
do {
RefPtrWillBeRawPtr<Element> option = document().createElement(optionTag, false);
ASSERT(option);
add(toHTMLElement(option), 0, exceptionState);
appendChild(document().createElement(optionTag, false), exceptionState);
if (exceptionState.hadException())
break;
} while (++diff);
......
......@@ -37,6 +37,8 @@ namespace blink {
class AutoscrollController;
class ExceptionState;
class HTMLOptionElement;
class HTMLOptionElementOrHTMLOptGroupElement;
class HTMLElementOrLong;
class HTMLSelectElement final : public HTMLFormControlElementWithState, public TypeAheadDataSource {
DEFINE_WRAPPERTYPEINFO();
......@@ -64,8 +66,7 @@ public:
bool usesMenuList() const;
void add(HTMLElement*, HTMLElement* beforeElement, ExceptionState&);
void addBeforeOptionAtIndex(HTMLElement*, int beforeIndex, ExceptionState&);
void add(const HTMLOptionElementOrHTMLOptGroupElement&, const HTMLElementOrLong&, ExceptionState&);
using Node::remove;
void remove(int index);
......
......@@ -37,9 +37,8 @@ interface HTMLSelectElement : HTMLElement {
getter Element item(unsigned long index);
Element namedItem([Default=Undefined] optional DOMString name);
// FIXME: should be union type http://crbug.com/240176
[RaisesException, TypeChecking=Interface] void add(HTMLElement element, optional HTMLElement? before = null);
[ImplementedAs=addBeforeOptionAtIndex, RaisesException, TypeChecking=Interface] void add(HTMLElement element, long before);
[RaisesException, TypeChecking=Interface] void add((HTMLOptionElement or HTMLOptGroupElement) element,
optional (HTMLElement or long)? before = null);
[RaisesException] void remove(); // ChildNode overload
void remove(long index);
[RaisesException, TypeChecking=Interface] setter HTMLOptionElement (unsigned long index, HTMLOptionElement? value);
......
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