JavaScriptCore:
authorddkilzer <ddkilzer@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jul 2006 03:16:41 +0000 (03:16 +0000)
committerddkilzer <ddkilzer@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Jul 2006 03:16:41 +0000 (03:16 +0000)
        Reviewed by Darin.

        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9179
          Implement select.options.add() method

        * JavaScriptCore.exp: Added overloaded KJS::JSValue::toInt32() method.
        * JavaScriptCore.xcodeproj/project.pbxproj: Altered attributes metadata for
        kjs/value.h to make it available as a forwarded header.
        * kjs/lookup.h:
        (KJS::lookupPut): Extracted a lookupPut() method from the existing lookupPut() method.
        The new method returns a boolean value if no entry is found in the lookup table.
        * kjs/value.cpp:
        (KJS::JSValue::toInt32): Overloaded toInt32() method with boolean "Ok" argument.
        * kjs/value.h: Ditto.

LayoutTests:

        Reviewed by Darin.

        - test for http://bugzilla.opendarwin.org/show_bug.cgi?id=9179
          Implement select.options.add() method

        * fast/dom/select-selectedIndex-multiple-expected.txt: Updated test results.
        * fast/dom/select-selectedIndex-multiple.html: Updated to print comments between
        tests to make failures easier to track down.
        * fast/dom/select-selectedIndex-expected.txt: Mirrored updates from select-selectedIndex-multiple.html
        * fast/dom/select-selectedIndex.html: Ditto.
        * fast/js/resources/select-options-add.js: Added.
        * fast/js/select-options-add-expected.txt: Added.
        * fast/js/select-options-add.html: Added.

WebCore:

        Reviewed by Darin.

        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9179
          Implement select.options.add() method

        Tests:
        - fast/dom/select-selectedIndex-multiple.html
        - fast/dom/select-selectedIndex.html
        - fast/js/select-options-add.html

        * DerivedSources.make: Added JSHTMLOptionsCollection.h.
        * ForwardingHeaders/kjs/operations.h: Added.
        * WebCore.xcodeproj/project.pbxproj: Added new source files.
        * bindings/js/JSHTMLOptionsCollectionCustom.cpp: Added.
        (WebCore::JSHTMLOptionsCollection::length):
        (WebCore::JSHTMLOptionsCollection::setLength):
        (WebCore::JSHTMLOptionsCollection::indexSetter):
        * bindings/js/kjs_html.cpp: Removed JSHTMLOptionsCollection implementation.
        Renamed classes and methods for consistency.
        (KJS::JSHTMLElement::selectGetter):
        (KJS::JSHTMLElement::put):
        (KJS::JSHTMLElement::selectSetter):
        (KJS::JSHTMLCollection::JSHTMLCollection):
        (KJS::JSHTMLCollectionProtoFunc::callAsFunction):
        (KJS::getHTMLOptionsCollection):
        * bindings/js/kjs_html.h: Ditto.
        * bindings/scripts/CodeGeneratorJS.pm: Added support for HasCustomIndexSetter class attribute.
        Added support for Optional parameter attribute, which makes generated code assume overloaded
        implementation methods are available for a JavaScript function with optional arguments.  Changed
        local 'impl' variables to 'imp' so that impl() methods could be called without class designation.
        * html/HTMLOptionElement.idl: Added GenerateNativeConverter attribute.
        * html/HTMLOptionsCollection.cpp: Added methods used by generated JSHTMLOptionsCollection class.
        (WebCore::HTMLOptionsCollection::HTMLOptionsCollection):
        (WebCore::HTMLOptionsCollection::add):
        (WebCore::HTMLOptionsCollection::selectedIndex):
        (WebCore::HTMLOptionsCollection::setSelectedIndex):
        (WebCore::HTMLOptionsCollection::setLength):
        * html/HTMLOptionsCollection.h: Ditto.
        * html/HTMLOptionsCollection.idl: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15321 268f45cc-cd09-0410-ab3c-d52691b4dbfc

26 files changed:
JavaScriptCore/ChangeLog
JavaScriptCore/JavaScriptCore.exp
JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
JavaScriptCore/kjs/lookup.h
JavaScriptCore/kjs/value.cpp
JavaScriptCore/kjs/value.h
LayoutTests/ChangeLog
LayoutTests/fast/dom/select-selectedIndex-expected.txt
LayoutTests/fast/dom/select-selectedIndex-multiple-expected.txt
LayoutTests/fast/dom/select-selectedIndex-multiple.html
LayoutTests/fast/dom/select-selectedIndex.html
LayoutTests/fast/js/resources/select-options-add.js [new file with mode: 0644]
LayoutTests/fast/js/select-options-add-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/select-options-add.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/DerivedSources.make
WebCore/ForwardingHeaders/kjs/operations.h [new file with mode: 0644]
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp [new file with mode: 0644]
WebCore/bindings/js/kjs_html.cpp
WebCore/bindings/js/kjs_html.h
WebCore/bindings/scripts/CodeGeneratorJS.pm
WebCore/html/HTMLOptionElement.idl
WebCore/html/HTMLOptionsCollection.cpp
WebCore/html/HTMLOptionsCollection.h
WebCore/html/HTMLOptionsCollection.idl [new file with mode: 0644]

index 83eb39830780ccfd5963818564f02faea2a6528b..fd3f5db1b13700f7700c458f5e04edc7a6252444 100644 (file)
@@ -1,3 +1,20 @@
+2006-07-10  David Kilzer  <ddkilzer@kilzer.net>
+
+        Reviewed by Darin.
+
+        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9179
+          Implement select.options.add() method
+
+        * JavaScriptCore.exp: Added overloaded KJS::JSValue::toInt32() method.
+        * JavaScriptCore.xcodeproj/project.pbxproj: Altered attributes metadata for
+        kjs/value.h to make it available as a forwarded header.
+        * kjs/lookup.h:
+        (KJS::lookupPut): Extracted a lookupPut() method from the existing lookupPut() method.
+        The new method returns a boolean value if no entry is found in the lookup table.
+        * kjs/value.cpp:
+        (KJS::JSValue::toInt32): Overloaded toInt32() method with boolean "Ok" argument.
+        * kjs/value.h: Ditto.
+
 2006-07-10  Geoffrey Garen  <ggaren@apple.com>
 
         No review necessary. Removed bogus file I accidentally checked in before.
index 3ddbf0110e6ff05f8bfae3b526d84e7d585286ca..437da3d79705dbebfa71862e9744f55a0c5543a2 100644 (file)
@@ -236,6 +236,7 @@ __ZNK3KJS6JSCell9getStringERNS_7UStringE
 __ZNK3KJS6JSCell9getStringEv
 __ZNK3KJS6JSCell9getUInt32ERj
 __ZNK3KJS7JSValue7toInt32EPNS_9ExecStateE
+__ZNK3KJS7JSValue7toInt32EPNS_9ExecStateERb
 __ZNK3KJS7JSValue8toUInt32EPNS_9ExecStateE
 __ZNK3KJS7JSValue9toIntegerEPNS_9ExecStateE
 __ZNK3KJS7UString10UTF8StringEv
index 906358f8d1a24c8bf1faa3f7283f71e07fc46ea4..ec3b894c9c92fe0f2b367c0c73ff6ae335dbbeee 100644 (file)
                932F5B510822A1C700736975 /* number_object.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8710255597D01FF60F7 /* number_object.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B530822A1C700736975 /* object_object.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8740255597D01FF60F7 /* object_object.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B540822A1C700736975 /* object.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8760255597D01FF60F7 /* object.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               932F5B550822A1C700736975 /* operations.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8780255597D01FF60F7 /* operations.h */; };
+               932F5B550822A1C700736975 /* operations.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A8780255597D01FF60F7 /* operations.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B560822A1C700736975 /* property_map.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A87A0255597D01FF60F7 /* property_map.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B570822A1C700736975 /* regexp_object.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A87C0255597D01FF60F7 /* regexp_object.h */; settings = {ATTRIBUTES = (Private, ); }; };
                932F5B580822A1C700736975 /* regexp.h in Headers */ = {isa = PBXBuildFile; fileRef = F692A87E0255597D01FF60F7 /* regexp.h */; settings = {ATTRIBUTES = (Private, ); }; };
index 29f76e9b75f190c914930ade4ab535cc2b17e6bc..55506f0e2f2fa9752ca519c151298cf0f58d8aa2 100644 (file)
@@ -229,18 +229,20 @@ namespace KJS {
 
   /**
    * This one is for "put".
-   * Lookup hash entry for property to be set, and set the value.
+   * It looks up a hash entry for the property to be set.  If an entry
+   * is found it sets the value and returns true, else it returns false.
    */
-  template <class ThisImp, class ParentImp>
-  inline void lookupPut(ExecState *exec, const Identifier &propertyName,
-                        JSValue *value, int attr,
+  template <class ThisImp>
+  inline bool lookupPut(ExecState* exec, const Identifier &propertyName,
+                        JSValuevalue, int attr,
                         const HashTable* table, ThisImp* thisObj)
   {
     const HashEntry* entry = Lookup::findEntry(table, propertyName);
 
-    if (!entry) // not found: forward to parent
-      thisObj->ParentImp::put(exec, propertyName, value, attr);
-    else if (entry->attr & Function) // function: put as override property
+    if (!entry)
+      return false;
+
+    if (entry->attr & Function) // function: put as override property
       thisObj->JSObject::put(exec, propertyName, value, attr);
     else if (entry->attr & ReadOnly) // readonly! Can't put!
 #ifdef KJS_VERBOSE
@@ -250,6 +252,23 @@ namespace KJS {
 #endif
     else
       thisObj->putValueProperty(exec, entry->value, value, attr);
+
+    return true;
+  }
+
+  /**
+   * This one is for "put".
+   * It calls lookupPut<ThisImp>() to set the value.  If that call
+   * returns false (meaning no entry in the hash table was found),
+   * then it calls put() on the ParentImp class.
+   */
+  template <class ThisImp, class ParentImp>
+  inline void lookupPut(ExecState* exec, const Identifier &propertyName,
+                        JSValue* value, int attr,
+                        const HashTable* table, ThisImp* thisObj)
+  {
+    if (!lookupPut<ThisImp>(exec, propertyName, value, attr, table, thisObj))
+      thisObj->ParentImp::put(exec, propertyName, value, attr); // not found: forward to parent
   }
 
 } // namespace
index 85a8a2f11a06b58b0f6e3e31ddec45946e36eaea..24615c5688493e664979a015a22c5769480a89af 100644 (file)
@@ -55,15 +55,19 @@ double JSValue::toInteger(ExecState *exec) const
     return roundValue(exec, const_cast<JSValue*>(this));
 }
 
-int32_t JSValue::toInt32(ExecState *exec) const
+int32_t JSValue::toInt32(ExecState* exec, bool& ok) const
 {
+    ok = true;
+
     uint32_t i;
     if (getUInt32(i))
         return i;
 
     double d = roundValue(exec, const_cast<JSValue*>(this));
-    if (isNaN(d) || isInf(d))
+    if (isNaN(d) || isInf(d)) {
+        ok = false;
         return 0;
+    }
     double d32 = fmod(d, D32);
 
     if (d32 >= D32 / 2)
index 2d61e68956888ccfb31f9be1793a18ee664b674d..49bca7e9bb6d78b1fab870f78a5bf912ad4d81aa 100644 (file)
@@ -94,7 +94,8 @@ public:
 
     // Integer conversions.
     double toInteger(ExecState *exec) const;
-    int32_t toInt32(ExecState *exec) const;
+    int32_t toInt32(ExecState*) const;
+    int32_t toInt32(ExecState*, bool& Ok) const;
     uint32_t toUInt32(ExecState *exec) const;
     uint16_t toUInt16(ExecState *exec) const;
 
@@ -369,6 +370,12 @@ inline bool JSValue::toBoolean(ExecState *exec) const
     return JSImmediate::isImmediate(this) ? JSImmediate::toBoolean(this) : downcast()->toBoolean(exec);
 }
 
+inline int32_t JSValue::toInt32(ExecState* exec) const
+{
+    bool ignored;
+    return toInt32(exec, ignored);
+}
+
 inline double JSValue::toNumber(ExecState *exec) const
 {
     return JSImmediate::isImmediate(this) ? JSImmediate::toDouble(this) : downcast()->toNumber(exec);
index e668d8e9e24d1ef4355c732ea26bb7749eab855a..172f6446214e3a32bc5a58678f319cedf13df329 100644 (file)
@@ -1,3 +1,19 @@
+2006-07-10  David Kilzer  <ddkilzer@kilzer.net>
+
+        Reviewed by Darin.
+
+        - test for http://bugzilla.opendarwin.org/show_bug.cgi?id=9179
+          Implement select.options.add() method
+
+        * fast/dom/select-selectedIndex-multiple-expected.txt: Updated test results.
+        * fast/dom/select-selectedIndex-multiple.html: Updated to print comments between
+        tests to make failures easier to track down.
+        * fast/dom/select-selectedIndex-expected.txt: Mirrored updates from select-selectedIndex-multiple.html
+        * fast/dom/select-selectedIndex.html: Ditto.
+        * fast/js/resources/select-options-add.js: Added.
+        * fast/js/select-options-add-expected.txt: Added.
+        * fast/js/select-options-add.html: Added.
+
 2006-07-10  Adele Peterson  <adele@apple.com>
 
         Reviewed by Beth.
index cbb4f628f13f850cacfd418099888a97d672c8df..2875266666dc92bb148f6a67f286a8446f279e22 100644 (file)
@@ -1,30 +1,70 @@
 
+1) setting length to a negative length
+PASS mySelect.options.length = -1; threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
 PASS mySelect.options.length is 2
 PASS mySelect.selectedIndex is 1
+2) setting length to a larger length
 PASS mySelect.options.length is 5
 PASS mySelect.selectedIndex is 1
+3) setting length to a smaller length
 PASS mySelect.options.length is 2
 PASS mySelect.selectedIndex is 1
 PASS mySelect.options.length is 1
 PASS mySelect.selectedIndex is -1
+4) setting length to the same length
 PASS mySelect.options.length is 2
 PASS mySelect.selectedIndex is 1
+5) setting length to non-integer value: null
 PASS mySelect.options.length is 0
 PASS mySelect.selectedIndex is -1
+6) setting length to non-integer value: undefined
 PASS mySelect.options.length is 0
 PASS mySelect.selectedIndex is -1
+7) setting length to non-integer value: non-numeric string
 PASS mySelect.options.length is 0
 PASS mySelect.selectedIndex is -1
+8) setting length to non-integer value: object
+PASS mySelect.options.length is 0
+PASS mySelect.selectedIndex is -1
+9) setting length to non-integer value: negative infinity
+PASS mySelect.options.length is 0
+PASS mySelect.selectedIndex is -1
+10) setting length to non-integer value: NaN
+PASS mySelect.options.length is 0
+PASS mySelect.selectedIndex is -1
+11) setting length to non-integer value: positive infinity
+PASS mySelect.options.length is 0
+PASS mySelect.selectedIndex is -1
+12) setting length to non-integer value: floating point number
 PASS mySelect.options.length is 2
 PASS mySelect.selectedIndex is 1
+13) setting an element by index past the end of the current list
 PASS mySelect.options.length is 11
 PASS mySelect.selectedIndex is 10
+14) setting an existing element by index
 PASS mySelect.options.length is 11
 PASS mySelect.selectedIndex is 10
+15) trying to set an element that's not an option: null
 PASS mySelect.options.length is 10
 PASS mySelect.selectedIndex is -1
+16) trying to set an element that's not an option: undefined
 PASS mySelect.options.length is 10
 PASS mySelect.selectedIndex is -1
+17) trying to set an element that's not an option: select element
+PASS mySelect.options[10] = mySelect; threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
 PASS mySelect.options.length is 10
 PASS mySelect.selectedIndex is -1
+18) trying to set a option element using an invalid index: negative infinity
+PASS mySelect.options.length is 10
+PASS mySelect.selectedIndex is -1
+19) trying to set a option element using an invalid index: NaN
+PASS mySelect.options.length is 10
+PASS mySelect.selectedIndex is -1
+20) trying to set a option element using an invalid index: positive infinity
+PASS mySelect.options.length is 10
+PASS mySelect.selectedIndex is -1
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
 
index 01eb767e8d3c3040e2bdf86e894e76df094b2463..536ba65ebb3dcc6a439d7a673cd7c781fadc04ba 100644 (file)
@@ -1,30 +1,70 @@
 
+1) setting length to a negative length
+PASS mySelect.options.length = -1; threw exception Error: INDEX_SIZE_ERR: DOM Exception 1.
 PASS mySelect.options.length is 2
 PASS mySelect.selectedIndex is 0
+2) setting length to a larger length
 PASS mySelect.options.length is 5
 PASS mySelect.selectedIndex is 0
+3) setting length to a smaller length
 PASS mySelect.options.length is 2
 PASS mySelect.selectedIndex is 0
 PASS mySelect.options.length is 1
 PASS mySelect.selectedIndex is 0
+4) setting length to the same length
 PASS mySelect.options.length is 2
 PASS mySelect.selectedIndex is 0
+5) setting length to non-integer value: null
 PASS mySelect.options.length is 0
 PASS mySelect.selectedIndex is -1
+6) setting length to non-integer value: undefined
 PASS mySelect.options.length is 0
 PASS mySelect.selectedIndex is -1
+7) setting length to non-integer value: non-numeric string
 PASS mySelect.options.length is 0
 PASS mySelect.selectedIndex is -1
+8) setting length to non-integer value: object
+PASS mySelect.options.length is 0
+PASS mySelect.selectedIndex is -1
+9) setting length to non-integer value: negative infinity
+PASS mySelect.options.length is 0
+PASS mySelect.selectedIndex is -1
+10) setting length to non-integer value: NaN
+PASS mySelect.options.length is 0
+PASS mySelect.selectedIndex is -1
+11) setting length to non-integer value: positive infinity
+PASS mySelect.options.length is 0
+PASS mySelect.selectedIndex is -1
+12) setting length to non-integer value: floating point number
 PASS mySelect.options.length is 2
 PASS mySelect.selectedIndex is 0
+13) setting an element by index past the end of the current list
 PASS mySelect.options.length is 11
 PASS mySelect.selectedIndex is 0
+14) setting an existing element by index
 PASS mySelect.options.length is 11
 PASS mySelect.selectedIndex is 0
+15) trying to set an element that's not an option: null
 PASS mySelect.options.length is 10
 PASS mySelect.selectedIndex is 0
+16) trying to set an element that's not an option: undefined
 PASS mySelect.options.length is 10
 PASS mySelect.selectedIndex is 0
+17) trying to set an element that's not an option: select element
+PASS mySelect.options[10] = mySelect; threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
 PASS mySelect.options.length is 10
 PASS mySelect.selectedIndex is 0
+18) trying to set a option element using an invalid index: negative infinity
+PASS mySelect.options.length is 10
+PASS mySelect.selectedIndex is 0
+19) trying to set a option element using an invalid index: NaN
+PASS mySelect.options.length is 10
+PASS mySelect.selectedIndex is 0
+20) trying to set a option element using an invalid index: positive infinity
+PASS mySelect.options.length is 10
+PASS mySelect.selectedIndex is 0
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
 
index abbf310213bf9add727b20c195b52f36bbd70013..81a9a496ab1644e79ab544e3caf978b05f5ca7eb 100644 (file)
@@ -1,3 +1,4 @@
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
 <select multiple id="test" size="3">
 </select>
 <div id="console"></div>
@@ -11,17 +12,19 @@ function reset(mySelect) {
 
 var mySelect = document.getElementById("test");
 reset(mySelect);
+var i = 0;
 
-mySelect.options.length = -1;
+debug((++i) + ") setting length to a negative length");
+shouldThrow("mySelect.options.length = -1;");
 shouldBe("mySelect.options.length", "2");
 shouldBe("mySelect.selectedIndex", "0");
 
-// 1) setting length to a larger length
+debug((++i) + ") setting length to a larger length");
 mySelect.options.length = 5;
 shouldBe("mySelect.options.length", "5");
 shouldBe("mySelect.selectedIndex", "0");
 
-// 2) setting length to a smaller length
+debug((++i) + ") setting length to a smaller length");
 mySelect.options.length = 2;
 shouldBe("mySelect.options.length", "2");
 shouldBe("mySelect.selectedIndex", "0");
@@ -31,53 +34,99 @@ shouldBe("mySelect.options.length", "1");
 shouldBe("mySelect.selectedIndex", "0");
 reset(mySelect);
 
-// 3) setting length to the same length
+debug((++i) + ") setting length to the same length");
 mySelect.options.length = 2;
 shouldBe("mySelect.options.length", "2");
 shouldBe("mySelect.selectedIndex", "0");
 
-// 4) setting length to non-integer values (null,
-// undefined, non-numeric string, floating point number)
+debug((++i) + ") setting length to non-integer value: null");
 mySelect.options.length = null;
 shouldBe("mySelect.options.length", "0");
 shouldBe("mySelect.selectedIndex", "-1");
 reset(mySelect);
 
+debug((++i) + ") setting length to non-integer value: undefined");
 mySelect.options.length = undefined;
 shouldBe("mySelect.options.length", "0");
 shouldBe("mySelect.selectedIndex", "-1");
 reset(mySelect);
 
+debug((++i) + ") setting length to non-integer value: non-numeric string");
 mySelect.options.length = "apple";
 shouldBe("mySelect.options.length", "0");
 shouldBe("mySelect.selectedIndex", "-1");
 reset(mySelect);
 
+debug((++i) + ") setting length to non-integer value: object");
+mySelect.options.length = new Object();
+shouldBe("mySelect.options.length", "0");
+shouldBe("mySelect.selectedIndex", "-1");
+reset(mySelect);
+
+debug((++i) + ") setting length to non-integer value: negative infinity");
+mySelect.options.length = -1/0;
+shouldBe("mySelect.options.length", "0");
+shouldBe("mySelect.selectedIndex", "-1");
+reset(mySelect);
+
+debug((++i) + ") setting length to non-integer value: NaN");
+mySelect.options.length = 0/0;
+shouldBe("mySelect.options.length", "0");
+shouldBe("mySelect.selectedIndex", "-1");
+reset(mySelect);
+
+debug((++i) + ") setting length to non-integer value: positive infinity");
+mySelect.options.length = 1/0;
+shouldBe("mySelect.options.length", "0");
+shouldBe("mySelect.selectedIndex", "-1");
+reset(mySelect);
+
+debug((++i) + ") setting length to non-integer value: floating point number");
 mySelect.options.length = 2.1;
 shouldBe("mySelect.options.length", "2");
 shouldBe("mySelect.selectedIndex", "0");
 
-// 5) setting an element by index past the end of the current list
+debug((++i) + ") setting an element by index past the end of the current list");
 mySelect.options[10] = new Option("ten", "value", true, true);
 shouldBe("mySelect.options.length", "11");
 shouldBe("mySelect.selectedIndex", "0");
 
-// 6) setting an existing element by index
+debug((++i) + ") setting an existing element by index");
 mySelect.options[10] = mySelect.options[10];
 shouldBe("mySelect.options.length", "11");
 shouldBe("mySelect.selectedIndex", "0");
 
-// 7) trying to set an element that's not an option
-// element (null, undefined, other kinds of objects, other kinds of elements)
+debug((++i) + ") trying to set an element that's not an option: null");
 mySelect.options[10] = null;
 shouldBe("mySelect.options.length", "10");
 shouldBe("mySelect.selectedIndex", "0");
+
+debug((++i) + ") trying to set an element that's not an option: undefined");
 mySelect.options[10] = undefined;
 shouldBe("mySelect.options.length", "10");
 shouldBe("mySelect.selectedIndex", "0");
-mySelect.options[10] = mySelect;
+
+debug((++i) + ") trying to set an element that's not an option: select element");
+shouldThrow("mySelect.options[10] = mySelect;");
 shouldBe("mySelect.options.length", "10");
 shouldBe("mySelect.selectedIndex", "0");
 
-</script>
+debug((++i) + ") trying to set a option element using an invalid index: negative infinity");
+mySelect.options[-1/0] = document.createElement("option");
+shouldBe("mySelect.options.length", "10");
+shouldBe("mySelect.selectedIndex", "0");
 
+debug((++i) + ") trying to set a option element using an invalid index: NaN");
+mySelect.options[0/0] = document.createElement("option");
+shouldBe("mySelect.options.length", "10");
+shouldBe("mySelect.selectedIndex", "0");
+
+debug((++i) + ") trying to set a option element using an invalid index: positive infinity");
+mySelect.options[1/0] = document.createElement("option");
+shouldBe("mySelect.options.length", "10");
+shouldBe("mySelect.selectedIndex", "0");
+
+debug("");
+var successfullyParsed = true;
+</script>
+<script src="../js/resources/js-test-post.js"></script>
index 43905eb1943f86f3791abba2a2f933a62cf07276..6ad00310965006f3461358b2e94729182c57844f 100644 (file)
@@ -1,3 +1,4 @@
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
 <select id="test" size="3">
 </select>
 <div id="console"></div>
@@ -11,17 +12,19 @@ function reset(mySelect) {
 
 var mySelect = document.getElementById("test");
 reset(mySelect);
+var i = 0;
 
-mySelect.options.length = -1;
+debug((++i) + ") setting length to a negative length");
+shouldThrow("mySelect.options.length = -1;");
 shouldBe("mySelect.options.length", "2");
 shouldBe("mySelect.selectedIndex", "1");
 
-// 1) setting length to a larger length
+debug((++i) + ") setting length to a larger length");
 mySelect.options.length = 5;
 shouldBe("mySelect.options.length", "5");
 shouldBe("mySelect.selectedIndex", "1");
 
-// 2) setting length to a smaller length
+debug((++i) + ") setting length to a smaller length");
 mySelect.options.length = 2;
 shouldBe("mySelect.options.length", "2");
 shouldBe("mySelect.selectedIndex", "1");
@@ -31,52 +34,99 @@ shouldBe("mySelect.options.length", "1");
 shouldBe("mySelect.selectedIndex", "-1");
 reset(mySelect);
 
-// 3) setting length to the same length
+debug((++i) + ") setting length to the same length");
 mySelect.options.length = 2;
 shouldBe("mySelect.options.length", "2");
 shouldBe("mySelect.selectedIndex", "1");
 
-// 4) setting length to non-integer values (null,
-// undefined, non-numeric string, floating point number)
+debug((++i) + ") setting length to non-integer value: null");
 mySelect.options.length = null;
 shouldBe("mySelect.options.length", "0");
 shouldBe("mySelect.selectedIndex", "-1");
 reset(mySelect);
 
+debug((++i) + ") setting length to non-integer value: undefined");
 mySelect.options.length = undefined;
 shouldBe("mySelect.options.length", "0");
 shouldBe("mySelect.selectedIndex", "-1");
 reset(mySelect);
 
+debug((++i) + ") setting length to non-integer value: non-numeric string");
 mySelect.options.length = "apple";
 shouldBe("mySelect.options.length", "0");
 shouldBe("mySelect.selectedIndex", "-1");
 reset(mySelect);
 
+debug((++i) + ") setting length to non-integer value: object");
+mySelect.options.length = new Object();
+shouldBe("mySelect.options.length", "0");
+shouldBe("mySelect.selectedIndex", "-1");
+reset(mySelect);
+
+debug((++i) + ") setting length to non-integer value: negative infinity");
+mySelect.options.length = -1/0;
+shouldBe("mySelect.options.length", "0");
+shouldBe("mySelect.selectedIndex", "-1");
+reset(mySelect);
+
+debug((++i) + ") setting length to non-integer value: NaN");
+mySelect.options.length = 0/0;
+shouldBe("mySelect.options.length", "0");
+shouldBe("mySelect.selectedIndex", "-1");
+reset(mySelect);
+
+debug((++i) + ") setting length to non-integer value: positive infinity");
+mySelect.options.length = 1/0;
+shouldBe("mySelect.options.length", "0");
+shouldBe("mySelect.selectedIndex", "-1");
+reset(mySelect);
+
+debug((++i) + ") setting length to non-integer value: floating point number");
 mySelect.options.length = 2.1;
 shouldBe("mySelect.options.length", "2");
 shouldBe("mySelect.selectedIndex", "1");
 
-// 5) setting an element by index past the end of the current list
+debug((++i) + ") setting an element by index past the end of the current list");
 mySelect.options[10] = new Option("ten", "value", true, true);
 shouldBe("mySelect.options.length", "11");
 shouldBe("mySelect.selectedIndex", "10");
 
-// 6) setting an existing element by index
+debug((++i) + ") setting an existing element by index");
 mySelect.options[10] = mySelect.options[10];
 shouldBe("mySelect.options.length", "11");
 shouldBe("mySelect.selectedIndex", "10");
 
-// 7) trying to set an element that's not an option
-// element (null, undefined, other kinds of objects, other kinds of elements)
+debug((++i) + ") trying to set an element that's not an option: null");
 mySelect.options[10] = null;
 shouldBe("mySelect.options.length", "10");
 shouldBe("mySelect.selectedIndex", "-1");
+
+debug((++i) + ") trying to set an element that's not an option: undefined");
 mySelect.options[10] = undefined;
 shouldBe("mySelect.options.length", "10");
 shouldBe("mySelect.selectedIndex", "-1");
-mySelect.options[10] = mySelect;
+
+debug((++i) + ") trying to set an element that's not an option: select element");
+shouldThrow("mySelect.options[10] = mySelect;");
+shouldBe("mySelect.options.length", "10");
+shouldBe("mySelect.selectedIndex", "-1");
+
+debug((++i) + ") trying to set a option element using an invalid index: negative infinity");
+mySelect.options[-1/0] = document.createElement("option");
+shouldBe("mySelect.options.length", "10");
+shouldBe("mySelect.selectedIndex", "-1");
+
+debug((++i) + ") trying to set a option element using an invalid index: NaN");
+mySelect.options[0/0] = document.createElement("option");
+shouldBe("mySelect.options.length", "10");
+shouldBe("mySelect.selectedIndex", "-1");
+
+debug((++i) + ") trying to set a option element using an invalid index: positive infinity");
+mySelect.options[1/0] = document.createElement("option");
 shouldBe("mySelect.options.length", "10");
 shouldBe("mySelect.selectedIndex", "-1");
 
+debug("");
+var successfullyParsed = true;
 </script>
+<script src="../js/resources/js-test-post.js"></script>
diff --git a/LayoutTests/fast/js/resources/select-options-add.js b/LayoutTests/fast/js/resources/select-options-add.js
new file mode 100644 (file)
index 0000000..beddcc1
--- /dev/null
@@ -0,0 +1,306 @@
+description(
+"This test checks the behavior of the add() method on the select.options object.<br>" +
+"It covers both the the one-argument (1.x) and two-argument (2.x) signatures of the add() method."
+);
+
+debug("1.1 Add Option to empty Options");
+var select1 = document.getElementById("select1");
+var option1 = document.createElement("OPTION");
+select1.options.add(option1);
+option1.value = "1";
+option1.textContent = "A";
+shouldBe("select1.options.length", "1");
+shouldBe("select1.selectedIndex", "0");
+shouldBe("select1.options[0].value", "'1'");
+shouldBe("select1.options[0].textContent", "'A'");
+debug("");
+
+debug("1.2 Add Option to non-empty Options");
+option1 = document.createElement("OPTION");
+select1.options.add(option1);
+option1.value = "2";
+option1.textContent = "B";
+shouldBe("select1.options.length", "2");
+shouldBe("select1.selectedIndex", "0");
+shouldBe("select1.options[0].value", "'1'");
+shouldBe("select1.options[0].textContent", "'A'");
+shouldBe("select1.options[1].value", "'2'");
+shouldBe("select1.options[1].textContent", "'B'");
+debug("");
+
+debug("1.3 Add Option after setting parameters");
+option1 = document.createElement("OPTION");
+option1.value = "3";
+option1.textContent = "C";
+select1.options.add(option1);
+shouldBe("select1.options.length", "3");
+shouldBe("select1.selectedIndex", "0");
+shouldBe("select1.options[0].value", "'1'");
+shouldBe("select1.options[0].textContent", "'A'");
+shouldBe("select1.options[1].value", "'2'");
+shouldBe("select1.options[1].textContent", "'B'");
+shouldBe("select1.options[2].value", "'3'");
+shouldBe("select1.options[2].textContent", "'C'");
+debug("");
+
+debug("1.4 Add a non-Option element");
+option1 = document.createElement("DIV");
+shouldThrow("select1.options.add(option1)");
+shouldBe("select1.options.length", "3");
+shouldBe("select1.selectedIndex", "0");
+debug("");
+
+debug("1.5 Add a non-element (string)");
+option1 = "o";
+shouldThrow("select1.options.add(option1)");
+shouldBe("select1.options.length", "3");
+shouldBe("select1.selectedIndex", "0");
+debug("");
+
+debug("1.6 Add a non-element (number)");
+option1 = 3.14;
+shouldThrow("select1.options.add(option1)");
+shouldBe("select1.options.length", "3");
+shouldBe("select1.selectedIndex", "0");
+debug("");
+
+debug("1.7 Add undefined");
+option1 = undefined;
+shouldThrow("select1.options.add(option1)");
+shouldBe("select1.options.length", "3");
+shouldBe("select1.selectedIndex", "0");
+debug("");
+
+debug("1.8 Add null");
+option1 = null;
+shouldThrow("select1.options.add(option1)");
+shouldBe("select1.options.length", "3");
+shouldBe("select1.selectedIndex", "0");
+debug("");
+
+debug("1.9 Add negative infinity");
+option1 = -1/0;
+shouldThrow("select1.options.add(option1)");
+shouldBe("select1.options.length", "3");
+shouldBe("select1.selectedIndex", "0");
+debug("");
+
+debug("1.10 Add NaN");
+option1 = 0/0;
+shouldThrow("select1.options.add(option1)");
+shouldBe("select1.options.length", "3");
+shouldBe("select1.selectedIndex", "0");
+debug("");
+
+debug("1.11 Add positive infinity");
+option1 = 1/0;
+shouldThrow("select1.options.add(option1)");
+shouldBe("select1.options.length", "3");
+shouldBe("select1.selectedIndex", "0");
+debug("");
+
+debug("2.1 Add Option to empty Options");
+var select2 = document.getElementById("select2");
+var option2 = document.createElement("OPTION");
+select2.options.add(option2, 0);
+option2.value = "1";
+option2.textContent = "A";
+shouldBe("select2.options.length", "1");
+shouldBe("select2.selectedIndex", "0");
+shouldBe("select2.options[0].value", "'1'");
+shouldBe("select2.options[0].textContent", "'A'");
+debug("");
+
+debug("2.2 Add Option after setting parameters");
+option2 = document.createElement("OPTION");
+option2.value = "2";
+option2.textContent = "B";
+select2.options.add(option2, 1);
+shouldBe("select2.options.length", "2");
+shouldBe("select2.selectedIndex", "0");
+shouldBe("select2.options[0].value", "'1'");
+shouldBe("select2.options[0].textContent", "'A'");
+shouldBe("select2.options[1].value", "'2'");
+shouldBe("select2.options[1].textContent", "'B'");
+debug("");
+
+debug("2.3 Insert Option at beginning of Options");
+option2 = document.createElement("OPTION");
+select2.options.add(option2, 0);
+option2.value = "0";
+option2.textContent = "Z";
+shouldBe("select2.options.length", "3");
+shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options[0].value", "'0'");
+shouldBe("select2.options[0].textContent", "'Z'");
+shouldBe("select2.options[1].value", "'1'");
+shouldBe("select2.options[1].textContent", "'A'");
+shouldBe("select2.options[2].value", "'2'");
+shouldBe("select2.options[2].textContent", "'B'");
+debug("");
+
+debug("2.4 Insert Option in middle of Options");
+option2 = document.createElement("OPTION");
+select2.options.add(option2, 2);
+option2.value = "1.5";
+option2.textContent = "A.5";
+shouldBe("select2.options.length", "4");
+shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options[0].value", "'0'");
+shouldBe("select2.options[0].textContent", "'Z'");
+shouldBe("select2.options[1].value", "'1'");
+shouldBe("select2.options[1].textContent", "'A'");
+shouldBe("select2.options[2].value", "'1.5'");
+shouldBe("select2.options[2].textContent", "'A.5'");
+shouldBe("select2.options[3].value", "'2'");
+shouldBe("select2.options[3].textContent", "'B'");
+debug("");
+
+debug("2.5 Insert Option at end of Options");
+option2 = document.createElement("OPTION");
+select2.options.add(option2, 4);
+option2.value = "3";
+option2.textContent = "C";
+shouldBe("select2.options.length", "5");
+shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options[0].value", "'0'");
+shouldBe("select2.options[0].textContent", "'Z'");
+shouldBe("select2.options[1].value", "'1'");
+shouldBe("select2.options[1].textContent", "'A'");
+shouldBe("select2.options[2].value", "'1.5'");
+shouldBe("select2.options[2].textContent", "'A.5'");
+shouldBe("select2.options[3].value", "'2'");
+shouldBe("select2.options[3].textContent", "'B'");
+shouldBe("select2.options[4].value", "'3'");
+shouldBe("select2.options[4].textContent", "'C'");
+debug("");
+
+debug("2.6 Insert Option beyond the end of Options");
+option2 = document.createElement("OPTION");
+select2.options.add(option2, 6);
+option2.value = "4";
+option2.textContent = "D";
+shouldBe("select2.options.length", "6");
+shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options[0].value", "'0'");
+shouldBe("select2.options[0].textContent", "'Z'");
+shouldBe("select2.options[1].value", "'1'");
+shouldBe("select2.options[1].textContent", "'A'");
+shouldBe("select2.options[2].value", "'1.5'");
+shouldBe("select2.options[2].textContent", "'A.5'");
+shouldBe("select2.options[3].value", "'2'");
+shouldBe("select2.options[3].textContent", "'B'");
+shouldBe("select2.options[4].value", "'3'");
+shouldBe("select2.options[4].textContent", "'C'");
+shouldBe("select2.options[5].value", "'4'");
+shouldBe("select2.options[5].textContent", "'D'");
+debug("");
+
+debug("2.7 Add an Option at index -1");
+option2 = document.createElement("OPTION");
+select2.options.add(option2, -1);
+option2.value = "5";
+option2.textContent = "E";
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+shouldBe("select2.options[0].value", "'0'");
+shouldBe("select2.options[0].textContent", "'Z'");
+shouldBe("select2.options[1].value", "'1'");
+shouldBe("select2.options[1].textContent", "'A'");
+shouldBe("select2.options[2].value", "'1.5'");
+shouldBe("select2.options[2].textContent", "'A.5'");
+shouldBe("select2.options[3].value", "'2'");
+shouldBe("select2.options[3].textContent", "'B'");
+shouldBe("select2.options[4].value", "'3'");
+shouldBe("select2.options[4].textContent", "'C'");
+shouldBe("select2.options[5].value", "'4'");
+shouldBe("select2.options[5].textContent", "'D'");
+shouldBe("select2.options[6].value", "'5'");
+shouldBe("select2.options[6].textContent", "'E'");
+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");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.9 Add an Option at index -Infinity");
+option2 = document.createElement("OPTION");
+shouldThrow("select2.options.add(option2, -1/0)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.10 Add an Option at index NaN");
+option2 = document.createElement("OPTION");
+shouldThrow("select2.options.add(option2, 0/0)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.11 Add an Option at index Infinity");
+option2 = document.createElement("OPTION");
+shouldThrow("select2.options.add(option2, 1/0)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.12 Add a non-Option element");
+option2 = document.createElement("DIV");
+shouldThrow("select2.options.add(option2, 1)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.13 Add a non-element (string)");
+option2 = "o";
+shouldThrow("select2.options.add(option2, 1)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.14 Add a non-element (number)");
+option2 = 3.14;
+shouldThrow("select2.options.add(option2, 1)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.15 Add undefined");
+option2 = undefined;
+shouldThrow("select2.options.add(option2, 1)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.16 Add null");
+option2 = null;
+shouldThrow("select2.options.add(option2, 1)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.17 Add negative infinity");
+option2 = -1/0;
+shouldThrow("select2.options.add(option2, 1)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.18 Add NaN");
+option2 = 0/0;
+shouldThrow("select2.options.add(option2, 1)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+debug("2.19 Add positive infinity");
+option2 = 1/0;
+shouldThrow("select2.options.add(option2, 1)");
+shouldBe("select2.options.length", "7");
+shouldBe("select2.selectedIndex", "1");
+debug("");
+
+successfullyParsed = true;
diff --git a/LayoutTests/fast/js/select-options-add-expected.txt b/LayoutTests/fast/js/select-options-add-expected.txt
new file mode 100644 (file)
index 0000000..88ac408
--- /dev/null
@@ -0,0 +1,219 @@
+This test checks the behavior of the add() method on the select.options object.
+It covers both the the one-argument (1.x) and two-argument (2.x) signatures of the add() method.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+1.1 Add Option to empty Options
+PASS select1.options.length is 1
+PASS select1.selectedIndex is 0
+PASS select1.options[0].value is '1'
+PASS select1.options[0].textContent is 'A'
+
+1.2 Add Option to non-empty Options
+PASS select1.options.length is 2
+PASS select1.selectedIndex is 0
+PASS select1.options[0].value is '1'
+PASS select1.options[0].textContent is 'A'
+PASS select1.options[1].value is '2'
+PASS select1.options[1].textContent is 'B'
+
+1.3 Add Option after setting parameters
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+PASS select1.options[0].value is '1'
+PASS select1.options[0].textContent is 'A'
+PASS select1.options[1].value is '2'
+PASS select1.options[1].textContent is 'B'
+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 Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+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 Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+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 Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.7 Add undefined
+PASS select1.options.add(option1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.8 Add null
+PASS select1.options.add(option1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.9 Add negative infinity
+PASS select1.options.add(option1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.10 Add NaN
+PASS select1.options.add(option1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+1.11 Add positive infinity
+PASS select1.options.add(option1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select1.options.length is 3
+PASS select1.selectedIndex is 0
+
+2.1 Add Option to empty Options
+PASS select2.options.length is 1
+PASS select2.selectedIndex is 0
+PASS select2.options[0].value is '1'
+PASS select2.options[0].textContent is 'A'
+
+2.2 Add Option after setting parameters
+PASS select2.options.length is 2
+PASS select2.selectedIndex is 0
+PASS select2.options[0].value is '1'
+PASS select2.options[0].textContent is 'A'
+PASS select2.options[1].value is '2'
+PASS select2.options[1].textContent is 'B'
+
+2.3 Insert Option at beginning of Options
+PASS select2.options.length is 3
+PASS select2.selectedIndex is 1
+PASS select2.options[0].value is '0'
+PASS select2.options[0].textContent is 'Z'
+PASS select2.options[1].value is '1'
+PASS select2.options[1].textContent is 'A'
+PASS select2.options[2].value is '2'
+PASS select2.options[2].textContent is 'B'
+
+2.4 Insert Option in middle of Options
+PASS select2.options.length is 4
+PASS select2.selectedIndex is 1
+PASS select2.options[0].value is '0'
+PASS select2.options[0].textContent is 'Z'
+PASS select2.options[1].value is '1'
+PASS select2.options[1].textContent is 'A'
+PASS select2.options[2].value is '1.5'
+PASS select2.options[2].textContent is 'A.5'
+PASS select2.options[3].value is '2'
+PASS select2.options[3].textContent is 'B'
+
+2.5 Insert Option at end of Options
+PASS select2.options.length is 5
+PASS select2.selectedIndex is 1
+PASS select2.options[0].value is '0'
+PASS select2.options[0].textContent is 'Z'
+PASS select2.options[1].value is '1'
+PASS select2.options[1].textContent is 'A'
+PASS select2.options[2].value is '1.5'
+PASS select2.options[2].textContent is 'A.5'
+PASS select2.options[3].value is '2'
+PASS select2.options[3].textContent is 'B'
+PASS select2.options[4].value is '3'
+PASS select2.options[4].textContent is 'C'
+
+2.6 Insert Option beyond the end of Options
+PASS select2.options.length is 6
+PASS select2.selectedIndex is 1
+PASS select2.options[0].value is '0'
+PASS select2.options[0].textContent is 'Z'
+PASS select2.options[1].value is '1'
+PASS select2.options[1].textContent is 'A'
+PASS select2.options[2].value is '1.5'
+PASS select2.options[2].textContent is 'A.5'
+PASS select2.options[3].value is '2'
+PASS select2.options[3].textContent is 'B'
+PASS select2.options[4].value is '3'
+PASS select2.options[4].textContent is 'C'
+PASS select2.options[5].value is '4'
+PASS select2.options[5].textContent is 'D'
+
+2.7 Add an Option at index -1
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+PASS select2.options[0].value is '0'
+PASS select2.options[0].textContent is 'Z'
+PASS select2.options[1].value is '1'
+PASS select2.options[1].textContent is 'A'
+PASS select2.options[2].value is '1.5'
+PASS select2.options[2].textContent is 'A.5'
+PASS select2.options[3].value is '2'
+PASS select2.options[3].textContent is 'B'
+PASS select2.options[4].value is '3'
+PASS select2.options[4].textContent is 'C'
+PASS select2.options[5].value is '4'
+PASS select2.options[5].textContent is 'D'
+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 Error: INDEX_SIZE_ERR: DOM Exception 1.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.9 Add an Option at index -Infinity
+PASS select2.options.add(option2, -1/0) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.10 Add an Option at index NaN
+PASS select2.options.add(option2, 0/0) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.11 Add an Option at index Infinity
+PASS select2.options.add(option2, 1/0) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.12 Add a non-Option element
+PASS select2.options.add(option2, 1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.13 Add a non-element (string)
+PASS select2.options.add(option2, 1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.14 Add a non-element (number)
+PASS select2.options.add(option2, 1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.15 Add undefined
+PASS select2.options.add(option2, 1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.16 Add null
+PASS select2.options.add(option2, 1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.17 Add negative infinity
+PASS select2.options.add(option2, 1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.18 Add NaN
+PASS select2.options.add(option2, 1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+2.19 Add positive infinity
+PASS select2.options.add(option2, 1) threw exception Error: TYPE_MISMATCH_ERR: DOM Exception 17.
+PASS select2.options.length is 7
+PASS select2.selectedIndex is 1
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/js/select-options-add.html b/LayoutTests/fast/js/select-options-add.html
new file mode 100644 (file)
index 0000000..3d8c1bd
--- /dev/null
@@ -0,0 +1,17 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="resources/js-test-style.css">
+<script src="resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<div>
+<select id="select1"></select>
+<select id="select2"></select>
+</div>
+<script src="resources/select-options-add.js"></script>
+<script src="resources/js-test-post.js"></script>
+</body>
+</html>
index f28b554c7adac222512d0caceef3b24c5d29dfff..0821b4f3a9fbb5ed325365059a423411e569ad47 100644 (file)
@@ -1,3 +1,45 @@
+2006-07-10  David Kilzer  <ddkilzer@kilzer.net>
+
+        Reviewed by Darin.
+
+        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9179
+          Implement select.options.add() method
+
+        Tests:
+        - fast/dom/select-selectedIndex-multiple.html
+        - fast/dom/select-selectedIndex.html
+        - fast/js/select-options-add.html
+
+        * DerivedSources.make: Added JSHTMLOptionsCollection.h.
+        * ForwardingHeaders/kjs/operations.h: Added.
+        * WebCore.xcodeproj/project.pbxproj: Added new source files.
+        * bindings/js/JSHTMLOptionsCollectionCustom.cpp: Added.
+        (WebCore::JSHTMLOptionsCollection::length):
+        (WebCore::JSHTMLOptionsCollection::setLength):
+        (WebCore::JSHTMLOptionsCollection::indexSetter):
+        * bindings/js/kjs_html.cpp: Removed JSHTMLOptionsCollection implementation.
+        Renamed classes and methods for consistency.
+        (KJS::JSHTMLElement::selectGetter):
+        (KJS::JSHTMLElement::put):
+        (KJS::JSHTMLElement::selectSetter):
+        (KJS::JSHTMLCollection::JSHTMLCollection):
+        (KJS::JSHTMLCollectionProtoFunc::callAsFunction):
+        (KJS::getHTMLOptionsCollection):
+        * bindings/js/kjs_html.h: Ditto.
+        * bindings/scripts/CodeGeneratorJS.pm: Added support for HasCustomIndexSetter class attribute.
+        Added support for Optional parameter attribute, which makes generated code assume overloaded
+        implementation methods are available for a JavaScript function with optional arguments.  Changed
+        local 'impl' variables to 'imp' so that impl() methods could be called without class designation.
+        * html/HTMLOptionElement.idl: Added GenerateNativeConverter attribute.
+        * html/HTMLOptionsCollection.cpp: Added methods used by generated JSHTMLOptionsCollection class.
+        (WebCore::HTMLOptionsCollection::HTMLOptionsCollection):
+        (WebCore::HTMLOptionsCollection::add):
+        (WebCore::HTMLOptionsCollection::selectedIndex):
+        (WebCore::HTMLOptionsCollection::setSelectedIndex):
+        (WebCore::HTMLOptionsCollection::setLength):
+        * html/HTMLOptionsCollection.h: Ditto.
+        * html/HTMLOptionsCollection.idl: Added.
+
 2006-07-10  David Harrison  <harrison@apple.com>
 
         Reviewed by Dave Hyatt.
index 70cc1a6b64c7c69af34b19bf19dc4003ae902b7f..9cae161eb1d5db2cb9ccfb64ad1765e37b534256 100644 (file)
@@ -98,6 +98,7 @@ all : \
     JSHTMLLinkElement.h \
     JSHTMLMenuElement.h \
     JSHTMLOptionElement.h \
+    JSHTMLOptionsCollection.h \
     JSHTMLOptGroupElement.h \
     JSHTMLQuoteElement.h \
     JSHTMLMapElement.h \
diff --git a/WebCore/ForwardingHeaders/kjs/operations.h b/WebCore/ForwardingHeaders/kjs/operations.h
new file mode 100644 (file)
index 0000000..eb80f49
--- /dev/null
@@ -0,0 +1 @@
+#include <JavaScriptCore/operations.h>
index c9445b51c3e26c43ae701e786a156b566e4b61f7..58e24bc28591f714ebc4beff26769079aeb30eca 100644 (file)
                1CD4418E0A4CE76F00A007AB /* northEastSouthWestResizeCursor.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 1CD4418A0A4CE76F00A007AB /* northEastSouthWestResizeCursor.tiff */; };
                1CD4418F0A4CE76F00A007AB /* northSouthResizeCursor.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 1CD4418B0A4CE76F00A007AB /* northSouthResizeCursor.tiff */; };
                1CD441900A4CE76F00A007AB /* northWestSouthEastResizeCursor.tiff in Resources */ = {isa = PBXBuildFile; fileRef = 1CD4418C0A4CE76F00A007AB /* northWestSouthEastResizeCursor.tiff */; };
+               448A29BF0A46D9CB0030759F /* JSHTMLOptionsCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 448A29BD0A46D9CB0030759F /* JSHTMLOptionsCollection.h */; };
+               448A29C00A46D9CB0030759F /* JSHTMLOptionsCollection.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 448A29BE0A46D9CB0030759F /* JSHTMLOptionsCollection.cpp */; };
+               448AD27C0A48137A0023D179 /* JSHTMLOptionsCollectionCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 448AD27A0A4813790023D179 /* JSHTMLOptionsCollectionCustom.cpp */; };
                4E1959210A39DABA00220FE5 /* MediaFeatureNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4E19591F0A39DABA00220FE5 /* MediaFeatureNames.cpp */; };
                4E1959220A39DABA00220FE5 /* MediaFeatureNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E1959200A39DABA00220FE5 /* MediaFeatureNames.h */; };
                4E1959290A39DACC00220FE5 /* MediaQuery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4E1959230A39DACC00220FE5 /* MediaQuery.cpp */; };
                1CD4418C0A4CE76F00A007AB /* northWestSouthEastResizeCursor.tiff */ = {isa = PBXFileReference; lastKnownFileType = image.tiff; path = northWestSouthEastResizeCursor.tiff; sourceTree = "<group>"; };
                2D90660B0665D937006B6F1A /* ClipboardMac.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ClipboardMac.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                2D90660C0665D937006B6F1A /* ClipboardMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ClipboardMac.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
+               448A29BD0A46D9CB0030759F /* JSHTMLOptionsCollection.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSHTMLOptionsCollection.h; sourceTree = "<group>"; };
+               448A29BE0A46D9CB0030759F /* JSHTMLOptionsCollection.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLOptionsCollection.cpp; sourceTree = "<group>"; };
+               448AD27A0A4813790023D179 /* JSHTMLOptionsCollectionCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLOptionsCollectionCustom.cpp; sourceTree = "<group>"; };
                4758C44308C5F217009BAF05 /* KCanvasPath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KCanvasPath.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                4E19591F0A39DABA00220FE5 /* MediaFeatureNames.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = MediaFeatureNames.cpp; sourceTree = "<group>"; };
                4E1959200A39DABA00220FE5 /* MediaFeatureNames.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MediaFeatureNames.h; sourceTree = "<group>"; };
                                A80E7E910A1A83E3007FB8C5 /* JSHTMLOptGroupElement.h */,
                                A80E7E900A1A83E3007FB8C5 /* JSHTMLOptionElement.cpp */,
                                A80E7E8F0A1A83E3007FB8C5 /* JSHTMLOptionElement.h */,
+                               448A29BE0A46D9CB0030759F /* JSHTMLOptionsCollection.cpp */,
+                               448A29BD0A46D9CB0030759F /* JSHTMLOptionsCollection.h */,
                                1AE2AB9E0A1CE90500B42B25 /* JSHTMLParagraphElement.cpp */,
                                1AE2AB9F0A1CE90500B42B25 /* JSHTMLParagraphElement.h */,
                                1AE2ABA00A1CE90500B42B25 /* JSHTMLParamElement.cpp */,
                                A80E7E630A1A82EC007FB8C5 /* JSHTMLInputElementBase.h */,
                                A826E8AD0A1A8F2300CD1BB6 /* JSHTMLOptionElementConstructor.cpp */,
                                A826E8AC0A1A8F2300CD1BB6 /* JSHTMLOptionElementConstructor.h */,
+                               448AD27A0A4813790023D179 /* JSHTMLOptionsCollectionCustom.cpp */,
                                93B70D4109EB0C7C009D8468 /* JSXMLHttpRequest.cpp */,
                                93B70D4209EB0C7C009D8468 /* JSXMLHttpRequest.h */,
                                93B70D4309EB0C7C009D8468 /* JSXMLSerializer.cpp */,
                                ABE7B5240A489F830031881C /* DeprecatedRenderSelect.h in Headers */,
                                DB23C2CC0A508D29002489EB /* IndentOutdentCommand.h in Headers */,
                                BCCD74DC0A4C8D35005FDA6D /* HTMLViewSourceDocument.h in Headers */,
+                               448A29BF0A46D9CB0030759F /* JSHTMLOptionsCollection.h in Headers */,
                                1A8086CC0A4D097600DFB6A7 /* DOMCSSInternal.h in Headers */,
                                1A1D13800A5325520064BF5F /* DOMXPath.h in Headers */,
                                1A1D13CA0A5329090064BF5F /* DOMXPathInternal.h in Headers */,
                                51F11E150A48C2920034A24E /* SQLTransaction.cpp in Sources */,
                                DB23C2CB0A508D29002489EB /* IndentOutdentCommand.cpp in Sources */,
                                BCCD74E50A4C8DDF005FDA6D /* HTMLViewSourceDocument.cpp in Sources */,
+                               448A29C00A46D9CB0030759F /* JSHTMLOptionsCollection.cpp in Sources */,
+                               448AD27C0A48137A0023D179 /* JSHTMLOptionsCollectionCustom.cpp in Sources */,
                                E1052C320A4D70010072D99B /* DOMEventsNonstandard.mm in Sources */,
                                516149ED0A525E3A003DFC7A /* SiteIcon.cpp in Sources */,
                                1A1D13810A5325520064BF5F /* DOMXPath.mm in Sources */,
diff --git a/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp b/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp
new file mode 100644 (file)
index 0000000..2b7fa7c
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "JSHTMLOptionsCollection.h"
+
+#include "ExceptionCode.h"
+#include "HTMLNames.h"
+#include "HTMLOptionElement.h"
+#include "HTMLOptionsCollection.h"
+#include "HTMLSelectElement.h"
+#include "JSHTMLOptionElement.h"
+
+#include <kjs/operations.h>
+
+using namespace KJS;
+
+namespace WebCore {
+
+JSValue* JSHTMLOptionsCollection::length(ExecState* exec) const
+{
+    HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl());
+    return jsNumber(imp->length());
+}
+
+void JSHTMLOptionsCollection::setLength(ExecState* exec, JSValue* value)
+{
+    HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl());
+    ExceptionCode ec = 0;
+    unsigned newLength = 0;
+    double lengthValue;
+    if (!value->isUndefinedOrNull() && value->getNumber(lengthValue)) {
+        if (isNaN(lengthValue) || isInf(lengthValue))
+            newLength = 0;
+        else if (lengthValue < 0.0)
+            ec = INDEX_SIZE_ERR;
+        else if (lengthValue > static_cast<double>(UINT_MAX))
+            newLength = UINT_MAX;
+        else
+            newLength = static_cast<unsigned>(lengthValue);
+    }
+    if (!ec)
+        imp->setLength(newLength, ec);
+    setDOMException(exec, ec);
+}
+
+void JSHTMLOptionsCollection::indexSetter(KJS::ExecState* exec, const KJS::Identifier &propertyName, KJS::JSValue* value, int attr)
+{
+    bool ok;
+    unsigned index = propertyName.toUInt32(&ok);
+    if (!ok)
+        return;
+
+    HTMLOptionsCollection* imp = static_cast<HTMLOptionsCollection*>(impl());
+    HTMLSelectElement* base = static_cast<HTMLSelectElement*>(imp->base());
+    if (value->isUndefinedOrNull())
+        base->remove(index);
+    else {
+        ExceptionCode ec = 0;
+        HTMLOptionElement* option = toHTMLOptionElement(value);
+        if (!option)
+            ec = TYPE_MISMATCH_ERR;
+        else
+            base->setOption(index, option, ec);
+        setDOMException(exec, ec);
+    }
+}
+
+}
index a8bd42ecab200931925f1db019cb0a9a5785ea32..4a9273a4fdfcc52a32091dba020ee264bdc10f50 100644 (file)
@@ -66,6 +66,7 @@
 #include "HTMLTableRowElement.h"
 #include "HTMLTableSectionElement.h"
 #include "JSHTMLImageElement.h"
+#include "JSHTMLOptionsCollection.h"
 #include "NameNodeList.h"
 #include "RenderLayer.h"
 #include "Text.h"
@@ -834,7 +835,7 @@ JSValue *JSHTMLElement::selectGetter(ExecState* exec, int token) const
         case SelectValue:           return jsString(select.value());
         case SelectLength:          return jsNumber(select.length());
         case SelectForm:            return toJS(exec, select.form()); // type HTMLFormElement
-        case SelectOptions:         return getSelectHTMLCollection(exec, select.options().get(), &select); // type JSHTMLCollection
+        case SelectOptions:         return getHTMLOptionsCollection(exec, select.options().get());
         case SelectDisabled:        return jsBoolean(select.disabled());
         case SelectMultiple:        return jsBoolean(select.multiple());
         case SelectName:            return jsString(select.name());
@@ -1278,7 +1279,7 @@ void JSHTMLElement::put(ExecState* exec, const Identifier &propertyName, JSValue
         bool ok;
         /*unsigned u =*/ propertyName.toUInt32(&ok);
         if (ok) {
-            JSObject* coll = static_cast<JSObject*>(getSelectHTMLCollection(exec, select.options().get(), &select));
+            JSObject* coll = static_cast<JSObject*>(getHTMLOptionsCollection(exec, select.options().get()));
             coll->put(exec,propertyName,value);
             return;
         }
@@ -1314,7 +1315,7 @@ void JSHTMLElement::selectSetter(ExecState* exec, int token, JSValue *value, con
         case SelectSelectedIndex:   { select.setSelectedIndex(value->toInt32(exec)); return; }
         case SelectValue:           { select.setValue(str); return; }
         case SelectLength:          { // read-only according to the NS spec, but webpages need it writeable
-                                        JSObject* coll = static_cast<JSObject*>(getSelectHTMLCollection(exec, select.options().get(), &select));
+                                        JSObject* coll = static_cast<JSObject*>(getHTMLOptionsCollection(exec, select.options().get()));
                                         coll->put(exec,lengthPropertyName,value);
                                         return;
                                     }
@@ -1573,23 +1574,22 @@ HTMLTableSectionElement* toHTMLTableSectionElement(JSValue *val)
 }
 
 // -------------------------------------------------------------------------
-/* Source for HTMLCollectionProtoTable. Use "make hashtables" to regenerate.
-@begin HTMLCollectionProtoTable 3
+/* Source for JSHTMLCollectionProtoTable. Use "make hashtables" to regenerate.
+@begin JSHTMLCollectionProtoTable 3
   item          JSHTMLCollection::Item            DontDelete|Function 1
   namedItem     JSHTMLCollection::NamedItem       DontDelete|Function 1
   tags          JSHTMLCollection::Tags            DontDelete|Function 1
 @end
 */
-KJS_DEFINE_PROTOTYPE(HTMLCollectionProto)
-KJS_IMPLEMENT_PROTOFUNC(HTMLCollectionProtoFunc)
-KJS_IMPLEMENT_PROTOTYPE("HTMLCollection",HTMLCollectionProto,HTMLCollectionProtoFunc)
+KJS_IMPLEMENT_PROTOFUNC(JSHTMLCollectionProtoFunc)
+KJS_IMPLEMENT_PROTOTYPE("HTMLCollection",JSHTMLCollectionProto,JSHTMLCollectionProtoFunc)
 
 const ClassInfo JSHTMLCollection::info = { "Collection", 0, 0, 0 };
 
-JSHTMLCollection::JSHTMLCollection(ExecState* exec, HTMLCollection *c)
+JSHTMLCollection::JSHTMLCollection(ExecState* exec, HTMLCollectionc)
   : m_impl(c) 
 {
-  setPrototype(HTMLCollectionProto::self(exec));
+  setPrototype(JSHTMLCollectionProto::self(exec));
 }
 
 JSHTMLCollection::~JSHTMLCollection()
@@ -1695,7 +1695,7 @@ JSValue *JSHTMLCollection::getNamedItems(ExecState* exec, const Identifier &prop
     return new DOMNamedNodesCollection(exec, namedItems);
 }
 
-JSValue *HTMLCollectionProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
+JSValue* JSHTMLCollectionProtoFunc::callAsFunction(ExecState* exec, JSObject* thisObj, const List &args)
 {
   if (!thisObj->inherits(&JSHTMLCollection::info))
     return throwError(exec, TypeError);
@@ -1713,75 +1713,6 @@ JSValue *HTMLCollectionProtoFunc::callAsFunction(ExecState* exec, JSObject* this
   }
 }
 
-// -------------------------------------------------------------------------
-
-JSHTMLSelectCollection::JSHTMLSelectCollection(ExecState* exec, HTMLCollection *c, HTMLSelectElement* e)
-  : JSHTMLCollection(exec, c), m_element(e)
-{
-}
-
-JSValue *JSHTMLSelectCollection::selectedIndexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)
-{
-    JSHTMLSelectCollection *thisObj = static_cast<JSHTMLSelectCollection*>(slot.slotBase());
-    return jsNumber(thisObj->m_element->selectedIndex());
-}
-
-bool JSHTMLSelectCollection::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
-{
-  if (propertyName == "selectedIndex") {
-    slot.setCustom(this, selectedIndexGetter);
-    //result = jsNumber(m_element->selectedIndex());
-    return true;
-  }
-
-  return JSHTMLCollection::getOwnPropertySlot(exec, propertyName, slot);
-}
-
-void JSHTMLSelectCollection::put(ExecState* exec, const Identifier &propertyName, JSValue *value, int)
-{
-#ifdef KJS_VERBOSE
-  kdDebug(6070) << "JSHTMLSelectCollection::put " << propertyName.deprecatedString() << endl;
-#endif
-  if ( propertyName == "selectedIndex" )
-    m_element->setSelectedIndex(value->toInt32(exec));
-  else if (propertyName == lengthPropertyName) {
-    // resize ?
-    if (value->isNumber()) {
-      double newLen;
-      if (value->getNumber(newLen)) {
-        int exception = 0;
-        if (newLen >= 0) {
-          m_element->setLength(unsigned(floor(newLen)), exception);
-          setDOMException(exec, exception);
-        }
-      }
-    } else {
-      int exception = 0;
-      m_element->setLength(0, exception);
-      setDOMException(exec, exception);
-    }
-  } else {
-    // an index ?
-    bool ok;
-    unsigned i = propertyName.toUInt32(&ok);
-    if (ok) {
-      if (value->isUndefinedOrNull()) {
-        // null and undefined delete. others, too ?
-        m_element->remove(i);
-      } else {
-        WebCore::Node *option = toNode(value);
-        // is v an option element ?
-        if (!option || !option->hasTagName(optionTag))
-            return;
-
-        int exception = 0;
-        m_element->setOption(i, static_cast<HTMLOptionElement*>(option), exception);
-        setDOMException(exec, exception);
-      }
-    }
-  }
-}
-
 ////////////////////// Image Object ////////////////////////
 
 ImageConstructorImp::ImageConstructorImp(ExecState* exec, Document* d)
@@ -1832,17 +1763,17 @@ JSValue* getHTMLCollection(ExecState* exec, HTMLCollection* c)
     return cacheDOMObject<HTMLCollection, JSHTMLCollection>(exec, c);
 }
 
-JSValue *getSelectHTMLCollection(ExecState* exec, HTMLCollection *c, HTMLSelectElement* e)
+JSValue* getHTMLOptionsCollection(ExecState* exec, HTMLOptionsCollection* c)
 {
-  DOMObject *ret;
+  DOMObjectret;
   if (!c)
     return jsNull();
   ScriptInterpreter* interp = static_cast<ScriptInterpreter*>(exec->dynamicInterpreter());
   if ((ret = interp->getDOMObject(c)))
     return ret;
   else {
-    ret = new JSHTMLSelectCollection(exec, c, e);
-    interp->putDOMObject(c,ret);
+    ret = new JSHTMLOptionsCollection(exec, c);
+    interp->putDOMObject(c, ret);
     return ret;
   }
 }
index bf3aa203c662ca17ffdb6e04540b0e50141b87fc..d6d2f197f4be47221148eca5fbd15a803daeb2eb 100644 (file)
@@ -30,6 +30,7 @@ namespace WebCore {
     class HTMLCollection;
     class HTMLDocument;
     class HTMLElement;
+    class HTMLOptionsCollection;
     class HTMLSelectElement;
     class HTMLTableCaptionElement;
     class HTMLTableSectionElement;
@@ -169,6 +170,8 @@ namespace KJS {
   WebCore::HTMLTableCaptionElement* toHTMLTableCaptionElement(JSValue*); // returns 0 if passed-in value is not a JSHTMLElement object for a HTMLTableCaptionElement
   WebCore::HTMLTableSectionElement* toHTMLTableSectionElement(JSValue*); // returns 0 if passed-in value is not a JSHTMLElement object for a HTMLTableSectionElement
 
+  KJS_DEFINE_PROTOTYPE(JSHTMLCollectionProto)
+
   class JSHTMLCollection : public DOMObject {
   public:
     JSHTMLCollection(ExecState*, WebCore::HTMLCollection*);
@@ -190,17 +193,6 @@ namespace KJS {
     static JSValue* nameGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
   };
 
-  class JSHTMLSelectCollection : public JSHTMLCollection {
-  public:
-    JSHTMLSelectCollection(ExecState*, WebCore::HTMLCollection*, WebCore::HTMLSelectElement*);
-    virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
-    virtual void put(ExecState*, const Identifier& propertyName, JSValue*, int attr = None);
-  private:
-    static JSValue* selectedIndexGetter(ExecState*, JSObject*, const Identifier&, const PropertySlot&);
-
-    RefPtr<WebCore::HTMLSelectElement> m_element;
-  };
-
   class HTMLAllCollection : public JSHTMLCollection {
   public:
     HTMLAllCollection(ExecState* exec, WebCore::HTMLCollection* c) :
@@ -221,7 +213,7 @@ namespace KJS {
   };
 
   JSValue* getHTMLCollection(ExecState*, WebCore::HTMLCollection*);
-  JSValue* getSelectHTMLCollection(ExecState*, WebCore::HTMLCollection*, WebCore::HTMLSelectElement*);
+  JSValue* getHTMLOptionsCollection(ExecState*, WebCore::HTMLOptionsCollection*);
   JSValue* getAllHTMLCollection(ExecState*, WebCore::HTMLCollection*);
 
 } // namespace
index 3d176ff57723637acc63e572ed7334ab7c4efc9f..30a18ad8416aa8ac87258764824e2eb1093a9a8a 100644 (file)
@@ -348,7 +348,12 @@ sub GenerateHeader
             }
         }
     }
-  
+
+    # Index setter
+    if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
+        push(@headerContent, "    void indexSetter(KJS::ExecState*, const KJS::Identifier &propertyName, KJS::JSValue*, int attr);\n");
+    }
+
     if (!$hasParent) {
         push(@headerContent, "    $implClassName* impl() const { return m_impl.get(); }\n");
         push(@headerContent, "private:\n");
@@ -691,7 +696,7 @@ sub GenerateImplementation
     push(@implContent, "}\n\n");
   
     push(@implContent, "JSValue* ${className}::getValueProperty(ExecState* exec, int token) const\n{\n");
-    push(@implContent, "    $implClassName* impl = static_cast<$implClassName*>(${className}::impl());\n\n");
+    push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(impl());\n\n");
     push(@implContent, "    switch (token) {\n");
 
     foreach my $attribute (@{$dataNode->attributes}) {
@@ -708,11 +713,11 @@ sub GenerateImplementation
         push(@implContent, "        return JS" . $constructorType . "::getConstructor(exec);\n");
       } elsif (!@{$attribute->getterExceptions}) {
         push(@implContent, "    case " . ucfirst($name) . "AttrNum:\n");
-        push(@implContent, "        return " . NativeToJSValue($attribute->signature, "impl->$name()") . ";\n");
+        push(@implContent, "        return " . NativeToJSValue($attribute->signature, "imp->$name()") . ";\n");
       } else {
         push(@implContent, "    case " . ucfirst($name) . "AttrNum: {\n");
         push(@implContent, "        ExceptionCode ec = 0;\n");
-        push(@implContent, "        KJS::JSValue* result = " . NativeToJSValue($attribute->signature, "impl->$name(ec)") . ";\n");
+        push(@implContent, "        KJS::JSValue* result = " . NativeToJSValue($attribute->signature, "imp->$name(ec)") . ";\n");
         push(@implContent, "        setDOMException(exec, ec);\n");
         push(@implContent, "        return result;\n");
         push(@implContent, "    }\n");
@@ -728,12 +733,20 @@ sub GenerateImplementation
     }
     if ($hasReadWriteProperties) {
       push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)\n");
-      push(@implContent, "{\n    lookupPut<$className, $parentClassName>" .
-                         "(exec, propertyName, value, attr, &${className}Table, this);\n}\n\n");
-                         
+      if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
+        push(@implContent, "{\n" .
+                           "    if (!lookupPut<$className>(exec, propertyName, value, attr, &${className}Table, this))\n");
+        push(@implContent, "        indexSetter(exec, propertyName, value, attr);\n");
+        push(@implContent, "}\n\n");
+      }
+      else {
+        push(@implContent, "{\n    lookupPut<$className, $parentClassName>" .
+                           "(exec, propertyName, value, attr, &${className}Table, this);\n}\n\n");
+      }
+
       push(@implContent, "void ${className}::putValueProperty(ExecState* exec, int token, JSValue* value, int /*attr*/)\n");
       push(@implContent, "{\n");
-      push(@implContent, "    $implClassName* impl = static_cast<$implClassName*>(${className}::impl());\n\n");
+      push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(impl());\n\n");
       push(@implContent, "    switch (token) {\n");
 
       foreach my $attribute (@{$dataNode->attributes}) {
@@ -757,7 +770,7 @@ sub GenerateImplementation
           } else {
               push(@implContent, "    case " . ucfirst($name) ."AttrNum: {\n");
               push(@implContent, "        ExceptionCode ec = 0;\n") if @{$attribute->setterExceptions};
-              push(@implContent, "        impl->set" . ucfirst($name) . "(" . JSValueToNative($attribute->signature, "value"));
+              push(@implContent, "        imp->set" . ucfirst($name) . "(" . JSValueToNative($attribute->signature, "value"));
               push(@implContent, ", ec") if @{$attribute->setterExceptions};
               push(@implContent, ");\n");
               push(@implContent, "        setDOMException(exec, ec);\n") if @{$attribute->setterExceptions};
@@ -770,7 +783,7 @@ sub GenerateImplementation
         
       if ($interfaceName eq "DOMWindow") {
           push(@implContent, "    // FIXME: Hack to prevent unused variable warning -- remove once DOMWindow includes a settable property\n");
-          push(@implContent, "    (void)impl;\n");
+          push(@implContent, "    (void)imp;\n");
       }
       push(@implContent, "}\n\n"); # end function
     }
@@ -788,34 +801,49 @@ sub GenerateImplementation
     push(@implContent, "    if (!thisObj->inherits(&${className}::info))\n");
     push(@implContent, "      return throwError(exec, TypeError);\n\n");
 
-    push(@implContent, "    $implClassName* impl = static_cast<$implClassName*>(static_cast<$className*>(thisObj)->impl());\n\n");
-    
-    
+    push(@implContent, "    $implClassName* imp = static_cast<$implClassName*>(static_cast<$className*>(thisObj)->impl());\n\n");
+
     push(@implContent, "    switch (id) {\n");
-    foreach my $function (@{$dataNode->functions}) {      
+    foreach my $function (@{$dataNode->functions}) {
       push(@implContent, "    case ${className}::" . ucfirst($function->signature->name) . "FuncNum: {\n");
-      
+
       if ($function->signature->extendedAttributes->{"Custom"}) {
         push(@implContent, "        return static_cast<${className}*>(thisObj)->" . $function->signature->name . "(exec, args);\n    }\n");
         next;
       }
-      
+
       AddIncludesForType($function->signature->type);
-      
+
+      if (@{$function->raisesExceptions}) {
+        push(@implContent, "        ExceptionCode ec = 0;\n");
+      }
+
       my $paramIndex = 0;
-      my $functionString = "impl->" . $function->signature->name . "(";
+      my $functionString = "imp->" . $function->signature->name . "(";
       my $numParameters = @{$function->parameters};
-      
+      my $hasOptionalArguments = 0;
+
       foreach my $parameter (@{$function->parameters}) {
+        if (!$hasOptionalArguments && $parameter->extendedAttributes->{"Optional"}) {
+          push(@implContent, "\n        int argsCount = args.size();\n");
+          $hasOptionalArguments = 1;
+        }
+
+        if ($hasOptionalArguments) {
+          push(@implContent, "        if (argsCount < " . ($paramIndex + 1) . ") {\n");
+          GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 3);
+          push(@implContent, "        }\n\n");
+        }
+
         my $name = $parameter->name;
         push(@implContent, "        bool ${name}Ok;\n") if TypeCanFailConversion($parameter);
         push(@implContent, "        " . GetNativeType($parameter) . " $name = " . JSValueToNative($parameter, "args[$paramIndex]", TypeCanFailConversion($parameter) ? "${name}Ok" : undef) . ";\n");        
-    if (TypeCanFailConversion($parameter)) {
-        push(@implContent, "        if (!${name}Ok) {\n");
-        push(@implContent, "            setDOMException(exec, TYPE_MISMATCH_ERR);\n");
-        push(@implContent, "            return jsUndefined();\n        }\n");
-    }          
-        
+        if (TypeCanFailConversion($parameter)) {
+          push(@implContent, "        if (!${name}Ok) {\n");
+          push(@implContent, "            setDOMException(exec, TYPE_MISMATCH_ERR);\n");
+          push(@implContent, "            return jsUndefined();\n        }\n");
+        }          
+
         # If a parameter is "an index", it should throw an INDEX_SIZE_ERR
         # exception        
         if ($parameter->extendedAttributes->{"IsIndex"}) {
@@ -824,37 +852,23 @@ sub GenerateImplementation
           push(@implContent, "            setDOMException(exec, INDEX_SIZE_ERR);\n");
           push(@implContent, "            return jsUndefined();\n        }\n");          
         }
-        
+
         $functionString .= ", " if $paramIndex;
         $functionString .= $name;
 
         $paramIndex++;
       }
-  
-      if (@{$function->raisesExceptions}) {
-        $functionString .= ", " if $paramIndex;
-        $functionString .= "ec";
-        push(@implContent, "        ExceptionCode ec = 0;\n");
-      }
-      $functionString .= ")";
-      
-      if ($function->signature->type eq "void") {
-        push(@implContent, "\n        $functionString;\n");
-        push(@implContent, "        setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
-        push(@implContent, "        return jsUndefined();\n");
-      } else {
-        push(@implContent, "\n        KJS::JSValue* result = " . NativeToJSValue($function->signature, $functionString) . ";\n");
-        push(@implContent, "        setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
-        push(@implContent, "        return result;\n");
-      }
 
-      push(@implContent, "    }\n");
+      push(@implContent, "\n");
+      GenerateImplementationFunctionCall($function, $functionString, $paramIndex, "    " x 2);
+
+      push(@implContent, "    }\n"); # end case
     }
-    push(@implContent, "    }\n");
+    push(@implContent, "    }\n"); # end switch
     push(@implContent, "    return 0;\n");
-    push(@implContent, "}\n")
+    push(@implContent, "}\n");
   }
-  
+
   if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
     push(@implContent, "\nJSValue* ${className}::indexGetter(ExecState* exec, JSObject* originalObject, const Identifier& propertyName, const PropertySlot& slot)\n");
     push(@implContent, "{\n");
@@ -862,7 +876,7 @@ sub GenerateImplementation
     push(@implContent, "    return toJS(exec, static_cast<$implClassName*>(thisObj->impl())->item(slot.index()));\n");
     push(@implContent, "}\n");
   }
-    
+
   if (!$hasParent) {
     my $implContent = << "EOF";
 KJS::JSValue* toJS(KJS::ExecState* exec, $implClassName* obj)
@@ -895,6 +909,30 @@ EOF
   push(@implContent, "\n#endif // ${conditional}_SUPPORT\n") if $conditional;
 }
 
+sub GenerateImplementationFunctionCall()
+{
+    my $function = shift;
+    my $functionString = shift;
+    my $paramIndex = shift;
+    my $indent = shift;
+
+    if (@{$function->raisesExceptions}) {
+        $functionString .= ", " if $paramIndex;
+        $functionString .= "ec";
+    }
+    $functionString .= ")";
+
+    if ($function->signature->type eq "void") {
+        push(@implContent, $indent . "$functionString;\n");
+        push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
+        push(@implContent, $indent . "return jsUndefined();\n");
+    } else {
+        push(@implContent, "\n" . $indent . "KJS::JSValue* result = " . NativeToJSValue($function->signature, $functionString) . ";\n");
+        push(@implContent, $indent . "setDOMException(exec, ec);\n") if @{$function->raisesExceptions};
+        push(@implContent, $indent . "return result;\n");
+    }
+}
+
 sub GetNativeType
 {
     my $signature = shift;
@@ -943,7 +981,8 @@ sub TypeCanFailConversion
   if ($type eq "boolean") {
     return 0;
   } elsif ($type eq "unsigned long" or $type eq "long") {
-    return 0; # or can it?
+    $implIncludes{"ExceptionCode.h"} = 1;
+    return 1;
   } elsif ($type eq "unsigned short") {
     return 0; # or can it?
   } elsif ($type eq "CompareHow") {
@@ -967,7 +1006,8 @@ sub TypeCanFailConversion
            $type eq "XPathResult" or
            $type eq "SVGMatrix" or
            $type eq "SVGRect" or
-           $type eq "SVGElement") {
+           $type eq "SVGElement" or
+           $type eq "HTMLOptionElement") {
       return 0;
   } else {
     die "Don't know whether a JS value can fail conversion to type $type."
@@ -993,7 +1033,11 @@ sub JSValueToNative
     } elsif ($type eq "unsigned long" or
              $type eq "long" or
              $type eq "unsigned short") {
-        return "$value->toInt32(exec)";
+        if ($maybeOkParam) {
+            return "$value->toInt32(exec${maybeOkParam})";
+        } else {
+            return "$value->toInt32(exec)";
+        }
     } elsif ($type eq "CompareHow") {
         return "static_cast<Range::CompareHow>($value->toInt32(exec))";
     } elsif ($type eq "float") {
@@ -1112,7 +1156,7 @@ sub NativeToJSValue
     } elsif ($type eq "StyleSheetList") {
         $implIncludes{"StyleSheetList.h"} = 1;
         $implIncludes{"kjs_css.h"} = 1;
-        return "toJS(exec, $value, impl)";
+        return "toJS(exec, $value, imp)";
     } elsif ($type eq "CSSStyleDeclaration" or $type eq "Rect") {
         $implIncludes{"CSSStyleDeclaration.h"} = 1;
         $implIncludes{"RectImpl.h"} = 1;
index 333331806a615c67b810e9beeefaa046e8aa34a4..a168d8196d4e394329642172e3659df5763846c7 100644 (file)
@@ -19,7 +19,7 @@
 
 module html {
 
-    interface [LegacyParent=KJS::JSHTMLElement] HTMLOptionElement : HTMLElement {
+    interface [LegacyParent=KJS::JSHTMLElement, GenerateNativeConverter] HTMLOptionElement : HTMLElement {
         readonly attribute  HTMLFormElement      form;
                  attribute  boolean              defaultSelected;
                  attribute  DOMString            text
index 67f7ed37f0e2deb69444ba9dea0997874677b2dc..76444ff9bf2c0eb07cea52f44b7e87f27eba0527 100644 (file)
@@ -24,6 +24,7 @@
 #include "HTMLOptionsCollection.h"
 
 #include "ExceptionCode.h"
+#include "HTMLOptionElement.h"
 #include "HTMLSelectElement.h"
 
 namespace WebCore {
@@ -32,13 +33,52 @@ HTMLOptionsCollection::HTMLOptionsCollection(HTMLSelectElement* select)
     : HTMLCollection(select, SelectOptions)
 {
     ASSERT(!info);
-
     info = select->collectionInfo();
 }
 
-void HTMLOptionsCollection::setLength(unsigned, ExceptionCode& ec)
+void HTMLOptionsCollection::add(PassRefPtr<HTMLOptionElement> element, ExceptionCode &ec)
+{
+    add(element, length(), ec);
+}
+
+void HTMLOptionsCollection::add(PassRefPtr<HTMLOptionElement> element, int index, ExceptionCode &ec)
+{
+    HTMLOptionElement* newOption = element.get();
+
+    if (!newOption) {
+        ec = TYPE_MISMATCH_ERR;
+        return;
+    }
+
+    if (index < -1) {
+        ec = INDEX_SIZE_ERR;
+        return;
+    }
+
+    ec = 0;
+    HTMLSelectElement* select = static_cast<HTMLSelectElement*>(m_base.get());
+
+    if (index == -1 || unsigned(index) >= length())
+        select->add(newOption, 0, ec);
+    else
+        select->add(newOption, static_cast<HTMLOptionElement*>(item(index)), ec);
+
+    ASSERT(ec == 0);
+}
+
+int HTMLOptionsCollection::selectedIndex() const
+{
+    return static_cast<HTMLSelectElement*>(m_base.get())->selectedIndex();
+}
+
+void HTMLOptionsCollection::setSelectedIndex(int index)
+{
+    static_cast<HTMLSelectElement*>(m_base.get())->setSelectedIndex(index);
+}
+
+void HTMLOptionsCollection::setLength(unsigned length, ExceptionCode& ec)
 {
-    ec = NOT_SUPPORTED_ERR;
+    static_cast<HTMLSelectElement*>(m_base.get())->setLength(length, ec);
 }
 
 } //namespace
index a4724f7483e8d7d0c2643e8977bb31f38e04aa37..4f18cfa342caddc3ec092bd7565ca3d5e86424a1 100644 (file)
@@ -27,6 +27,7 @@
 #define HTML_HTMLOptionsCollectionImpl_H
 
 #include "HTMLCollection.h"
+#include "HTMLOptionElement.h"
 
 namespace WebCore {
 
@@ -38,6 +39,12 @@ class HTMLOptionsCollection : public HTMLCollection {
 public:
     HTMLOptionsCollection(HTMLSelectElement*);
 
+    void add(PassRefPtr<HTMLOptionElement>, ExceptionCode&);
+    void add(PassRefPtr<HTMLOptionElement>, int index, ExceptionCode&);
+
+    int selectedIndex() const;
+    void setSelectedIndex(int);
+
     void setLength(unsigned, ExceptionCode&);
 };
 
diff --git a/WebCore/html/HTMLOptionsCollection.idl b/WebCore/html/HTMLOptionsCollection.idl
new file mode 100644 (file)
index 0000000..c582f5e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+module html {
+
+    interface [LegacyParent=KJS::JSHTMLCollection, HasCustomIndexSetter] HTMLOptionsCollection : HTMLCollection {
+                 attribute          long                 selectedIndex;
+                 attribute [Custom] long                 length
+                        setter raises (DOMException);
+
+        void               add(in HTMLOptionElement option, in [Optional] unsigned long index)
+             raises (DOMException);
+    };
+}