1717import java .util .ArrayList ;
1818import java .util .List ;
1919
20+ import org .htmlunit .corejs .javascript .Callable ;
2021import org .htmlunit .corejs .javascript .Context ;
2122import org .htmlunit .corejs .javascript .Scriptable ;
2223import org .htmlunit .html .DomElement ;
2324import org .htmlunit .html .DomNode ;
25+ import org .htmlunit .html .HtmlForm ;
26+ import org .htmlunit .html .HtmlInput ;
2427import org .htmlunit .javascript .JavaScriptEngine ;
2528import org .htmlunit .javascript .configuration .JsxClass ;
2629import org .htmlunit .javascript .configuration .JsxConstructor ;
30+ import org .htmlunit .javascript .configuration .JsxFunction ;
31+ import org .htmlunit .javascript .configuration .JsxGetter ;
32+ import org .htmlunit .javascript .configuration .JsxSymbol ;
33+ import org .htmlunit .javascript .host .dom .AbstractList ;
2734
2835/**
2936 * A special {@link HTMLCollection} for <code>document.all</code>.
3239 * @author Ahmed Ashour
3340 */
3441@ JsxClass
35- public class HTMLAllCollection extends HTMLCollection {
42+ public class HTMLAllCollection extends AbstractList implements Callable {
3643
3744 /**
3845 * Creates an instance.
@@ -44,18 +51,16 @@ public HTMLAllCollection() {
4451 /**
4552 * JavaScript constructor.
4653 */
47- @ Override
4854 @ JsxConstructor
4955 public void jsConstructor () {
50- super .jsConstructor ();
5156 }
5257
5358 /**
5459 * Creates an instance.
5560 * @param parentScope parent scope
5661 */
5762 public HTMLAllCollection (final DomNode parentScope ) {
58- super (parentScope , false );
63+ super (parentScope , false , null );
5964 }
6065
6166 /**
@@ -64,7 +69,7 @@ public HTMLAllCollection(final DomNode parentScope) {
6469 * @return the element or elements corresponding to the specified index or key
6570 * @see <a href="http://msdn.microsoft.com/en-us/library/ms536460.aspx">MSDN doc</a>
6671 */
67- @ Override
72+ @ JsxFunction
6873 public Object item (final Object index ) {
6974 final double numb ;
7075
@@ -99,9 +104,13 @@ public Object item(final Object index) {
99104 }
100105
101106 /**
102- * {@inheritDoc}
107+ * Retrieves the item or items corresponding to the specified name (checks ids, and if
108+ * that does not work, then names).
109+ * @param name the name or id the element or elements to return
110+ * @return the element or elements corresponding to the specified name or id
111+ * @see <a href="http://msdn.microsoft.com/en-us/library/ms536634.aspx">MSDN doc</a>
103112 */
104- @ Override
113+ @ JsxFunction
105114 public final Scriptable namedItem (final String name ) {
106115 final List <DomNode > elements = getElements ();
107116
@@ -158,7 +167,13 @@ public Object call(final Context cx, final Scriptable scope, final Scriptable th
158167 }
159168 }
160169
161- final Object value = super .call (cx , scope , thisObj , args );
170+ if (args .length == 0 ) {
171+ throw JavaScriptEngine .reportRuntimeError ("Zero arguments; need an index or a key." );
172+ }
173+ Object value = getIt (args [0 ]);
174+ if (value == NOT_FOUND ) {
175+ value = null ;
176+ }
162177 if (nullIfNotFound && JavaScriptEngine .isUndefined (value )) {
163178 return null ;
164179 }
@@ -169,19 +184,68 @@ public Object call(final Context cx, final Scriptable scope, final Scriptable th
169184 * {@inheritDoc}
170185 */
171186 @ Override
172- protected boolean supportsParentheses () {
173- return true ;
187+ protected Object equivalentValues (final Object value ) {
188+ if (value == null || JavaScriptEngine .isUndefined (value )) {
189+ return Boolean .TRUE ;
190+ }
191+
192+ return super .equivalentValues (value );
193+ }
194+ /**
195+ * @return the Iterator symbol
196+ */
197+ @ JsxSymbol
198+ public Scriptable iterator () {
199+ return JavaScriptEngine .newArrayIteratorTypeValues (getParentScope (), this );
200+ }
201+
202+ /**
203+ * Returns the length.
204+ * @return the length
205+ */
206+ @ JsxGetter
207+ @ Override
208+ public final int getLength () {
209+ return super .getLength ();
174210 }
175211
176212 /**
177213 * {@inheritDoc}
178214 */
179215 @ Override
180- protected Object equivalentValues (final Object value ) {
181- if (value == null || JavaScriptEngine .isUndefined (value )) {
182- return Boolean .TRUE ;
216+ protected Object getWithPreemptionByName (final String name , final List <DomNode > elements ) {
217+ final List <DomNode > matchingElements = new ArrayList <>();
218+ final boolean searchName = isGetWithPreemptionSearchName ();
219+ for (final DomNode next : elements ) {
220+ if (next instanceof DomElement
221+ && (searchName || next instanceof HtmlInput || next instanceof HtmlForm )) {
222+ final String nodeName = ((DomElement ) next ).getAttributeDirect (DomElement .NAME_ATTRIBUTE );
223+ if (name .equals (nodeName )) {
224+ matchingElements .add (next );
225+ }
226+ }
183227 }
184228
185- return super .equivalentValues (value );
229+ if (matchingElements .isEmpty ()) {
230+ return NOT_FOUND ;
231+ }
232+
233+ if (matchingElements .size () == 1 ) {
234+ return getScriptableForElement (matchingElements .get (0 ));
235+ }
236+
237+ // many elements => build a sub collection
238+ final DomNode domNode = getDomNodeOrNull ();
239+ final HTMLCollection collection = new HTMLCollection (domNode , matchingElements );
240+ collection .setAvoidObjectDetection (true );
241+ return collection ;
242+ }
243+
244+ /**
245+ * Returns whether {@link #getWithPreemption(String)} should search by name or not.
246+ * @return whether {@link #getWithPreemption(String)} should search by name or not
247+ */
248+ protected boolean isGetWithPreemptionSearchName () {
249+ return true ;
186250 }
187251}
0 commit comments