View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.javascript.host;
16  
17  import java.util.Map;
18  
19  import org.htmlunit.WebDriverTestCase;
20  import org.htmlunit.junit.BrowserRunner;
21  import org.htmlunit.junit.annotation.Alerts;
22  import org.junit.Test;
23  import org.junit.runner.RunWith;
24  
25  /**
26   * Tests for {@link Map}.
27   *
28   * @author Ahmed Ashour
29   * @author Ronald Brill
30   */
31  @RunWith(BrowserRunner.class)
32  public class MapTest extends WebDriverTestCase {
33  
34      /**
35       * @throws Exception if the test fails
36       */
37      @Test
38      @Alerts({"3", "value1"})
39      public void get() throws Exception {
40          final String html = DOCTYPE_HTML
41              + "<html><head>\n"
42              + "<script>\n"
43              + LOG_TITLE_FUNCTION
44              + "  function test() {\n"
45              + "    if (window.Map) {\n"
46              + "      var kvArray = [['key1', 'value1'], ['key2', 'value2']];\n"
47              + "      var myMap = new Map(kvArray);\n"
48              + "      myMap.set(1, 2);\n"
49              + "      log(myMap.size);\n"
50              + "      log(myMap.get('key1'));\n"
51              + "    }\n"
52              + "  }\n"
53              + "</script></head><body onload='test()'>\n"
54              + "</body></html>";
55  
56          loadPageVerifyTitle2(html);
57      }
58  
59      /**
60       * @throws Exception if the test fails
61       */
62      @Test
63      @Alerts({"function entries() { [native code] }",
64               "[object Map Iterator]", "0,foo", "1,bar", "[object Object],baz", "undefined"})
65      public void iterator() throws Exception {
66          final String html = DOCTYPE_HTML
67              + "<html>\n"
68              + "<head>\n"
69              + "<script>\n"
70              + LOG_TITLE_FUNCTION
71              + "  function test() {\n"
72              + "    if (window.Symbol) {\n"
73              + "      var myMap = new Map();\n"
74              + "      myMap.set('0', 'foo');\n"
75              + "      myMap.set(1, 'bar');\n"
76              + "      myMap.set({}, 'baz');\n"
77              + "      log(myMap[Symbol.iterator]);\n"
78              + "      var iter = myMap[Symbol.iterator]();\n"
79              + "      log(iter);\n"
80              + "      log(iter.next().value);\n"
81              + "      log(iter.next().value);\n"
82              + "      log(iter.next().value);\n"
83              + "      log(iter.next().value);\n"
84              + "    }\n"
85              + "  }\n"
86              + "</script>\n"
87              + "</head>\n"
88              + "<body onload='test()'>\n"
89              + "</body></html>";
90  
91          loadPageVerifyTitle2(html);
92      }
93  
94      /**
95       * @throws Exception if the test fails
96       */
97      @Test
98      @Alerts({"function entries() { [native code] }",
99               "[object Map Iterator]", "0,foo", "1,bar", "[object Object],baz", "undefined"})
100     public void entries() throws Exception {
101         final String html = DOCTYPE_HTML
102             + "<html>\n"
103             + "<head>\n"
104             + "<script>\n"
105             + LOG_TITLE_FUNCTION
106             + "  function test() {\n"
107             + "    if (window.Symbol) {\n"
108             + "      var myMap = new Map();\n"
109             + "      myMap.set('0', 'foo');\n"
110             + "      myMap.set(1, 'bar');\n"
111             + "      myMap.set({}, 'baz');\n"
112             + "      log(myMap.entries);\n"
113             + "      var iter = myMap.entries();\n"
114             + "      log(iter);\n"
115             + "      log(iter.next().value);\n"
116             + "      log(iter.next().value);\n"
117             + "      log(iter.next().value);\n"
118             + "      log(iter.next().value);\n"
119             + "    }\n"
120             + "  }\n"
121             + "</script>\n"
122             + "</head>\n"
123             + "<body onload='test()'>\n"
124             + "</body></html>";
125 
126         loadPageVerifyTitle2(html);
127     }
128 
129     /**
130      * @throws Exception if the test fails
131      */
132     @Test
133     @Alerts({"function values() { [native code] }",
134              "[object Map Iterator]", "foo", "bar", "baz", "undefined"})
135     public void values() throws Exception {
136         final String html = DOCTYPE_HTML
137             + "<html>\n"
138             + "<head>\n"
139             + "<script>\n"
140             + LOG_TITLE_FUNCTION
141             + "  function test() {\n"
142             + "    if (window.Symbol) {\n"
143             + "      var myMap = new Map();\n"
144             + "      myMap.set('0', 'foo');\n"
145             + "      myMap.set(1, 'bar');\n"
146             + "      myMap.set({}, 'baz');\n"
147             + "      log(myMap.values);\n"
148             + "      var iter = myMap.values();\n"
149             + "      log(iter);\n"
150             + "      log(iter.next().value);\n"
151             + "      log(iter.next().value);\n"
152             + "      log(iter.next().value);\n"
153             + "      log(iter.next().value);\n"
154             + "    }\n"
155             + "  }\n"
156             + "</script>\n"
157             + "</head>\n"
158             + "<body onload='test()'>\n"
159             + "</body></html>";
160 
161         loadPageVerifyTitle2(html);
162     }
163 
164     /**
165      * @throws Exception if the test fails
166      */
167     @Test
168     @Alerts({"function keys() { [native code] }",
169              "[object Map Iterator]", "0", "1", "[object Object]", "undefined"})
170     public void keys() throws Exception {
171         final String html = DOCTYPE_HTML
172             + "<html>\n"
173             + "<head>\n"
174             + "<script>\n"
175             + LOG_TITLE_FUNCTION
176             + "  function test() {\n"
177             + "    if (window.Symbol) {\n"
178             + "      var myMap = new Map();\n"
179             + "      myMap.set('0', 'foo');\n"
180             + "      myMap.set(1, 'bar');\n"
181             + "      myMap.set({}, 'baz');\n"
182             + "      log(myMap.keys);\n"
183             + "      var iter = myMap.keys();\n"
184             + "      log(iter);\n"
185             + "      log(iter.next().value);\n"
186             + "      log(iter.next().value);\n"
187             + "      log(iter.next().value);\n"
188             + "      log(iter.next().value);\n"
189             + "    }\n"
190             + "  }\n"
191             + "</script>\n"
192             + "</head>\n"
193             + "<body onload='test()'>\n"
194             + "</body></html>";
195 
196         loadPageVerifyTitle2(html);
197     }
198 
199     /**
200      * @throws Exception if the test fails
201      */
202     @Test
203     @Alerts("2")
204     public void constructorArray() throws Exception {
205         final String html = DOCTYPE_HTML
206             + "<html><head>\n"
207             + "<script>\n"
208             + LOG_TITLE_FUNCTION
209             + "function test() {\n"
210             + "  var myMap = new Map([[ 1, 'one' ],[ 2, 'two' ]]);\n"
211             + "  log(myMap.size);\n"
212             + "}\n"
213             + "</script></head><body onload='test()'>\n"
214             + "</body></html>";
215 
216         loadPageVerifyTitle2(html);
217     }
218 
219     /**
220      * @throws Exception if the test fails
221      */
222     @Test
223     @Alerts("TypeError")
224     public void constructorInt32Array() throws Exception {
225         final String html = DOCTYPE_HTML
226             + "<html><head>\n"
227             + "<script>\n"
228             + LOG_TITLE_FUNCTION
229             + "function test() {\n"
230             + "  var array = new Int32Array([2, 7]);\n"
231             + "  try {\n"
232             + "    var myMap = new Map(array);\n"
233             + "    log(myMap.size);\n"
234             + "  } catch(e) {\n"
235             + "    logEx(e);\n"
236             + "  }\n"
237             + "}\n"
238             + "</script></head><body onload='test()'>\n"
239             + "</body></html>";
240 
241         loadPageVerifyTitle2(html);
242     }
243 
244     /**
245      * @throws Exception if the test fails
246      */
247     @Test
248     @Alerts("TypeError")
249     public void constructorStringParam() throws Exception {
250         final String html = DOCTYPE_HTML
251             + "<html><head>\n"
252             + "<script>\n"
253             + LOG_TITLE_FUNCTION
254             + "function test() {\n"
255             + "  try {\n"
256             + "    var myMap = new Map('test');\n"
257             + "    log(myMap.size);\n"
258             + "  } catch(e) {\n"
259             + "    logEx(e);\n"
260             + "  }\n"
261             + "}\n"
262             + "</script></head><body onload='test()'>\n"
263             + "</body></html>";
264 
265         loadPageVerifyTitle2(html);
266     }
267 
268     /**
269      * @throws Exception if the test fails
270      */
271     @Test
272     @Alerts("TypeError")
273     public void constructorSetParam() throws Exception {
274         final String html = DOCTYPE_HTML
275             + "<html><head>\n"
276             + "<script>\n"
277             + LOG_TITLE_FUNCTION
278             + "function test() {\n"
279             + "  try {\n"
280             + "    var myMap = new Map(new Set('test'));\n"
281             + "    log(myMap.size);\n"
282             + "  } catch(e) {\n"
283             + "    logEx(e);\n"
284             + "  }\n"
285             + "}\n"
286             + "</script></head><body onload='test()'>\n"
287             + "</body></html>";
288 
289         loadPageVerifyTitle2(html);
290     }
291 
292     /**
293      * @throws Exception if the test fails
294      */
295     @Test
296     @Alerts("2")
297     public void constructorMapParam() throws Exception {
298         final String html = DOCTYPE_HTML
299             + "<html><head>\n"
300             + "<script>\n"
301             + LOG_TITLE_FUNCTION
302             + "function test() {\n"
303             + "  var kvArray = [['key1', 'value1'], ['key2', 'value2']];\n"
304             + "  var testMap = new Map(kvArray);\n"
305             + "  var myMap = new Map(testMap);\n"
306             + "  log(myMap.size);\n"
307             + "}\n"
308             + "</script></head><body onload='test()'>\n"
309             + "</body></html>";
310 
311         loadPageVerifyTitle2(html);
312     }
313 
314     /**
315      * @throws Exception if the test fails
316      */
317     @Test
318     @Alerts({"1", "77", "one"})
319     public void constructorIteratorParam() throws Exception {
320         final String html = DOCTYPE_HTML
321             + "<html><head>\n"
322             + "<script>\n"
323             + LOG_TITLE_FUNCTION
324             + "function logElement(value, key) {\n"
325             + "  log(key);\n"
326             + "  log(value);\n"
327             + "}\n"
328             + "function test() {\n"
329             + "  try {\n"
330             + "    var myIterable = {};\n"
331             + "    myIterable[Symbol.iterator] = function() {\n"
332             + "      return {\n"
333             + "        next: function() {\n"
334             + "          if (this._first) {;\n"
335             + "            this._first = false;\n"
336             + "            return { value: [ 77, 'one' ], done: false };\n"
337             + "          }\n"
338             + "          return { done: true };\n"
339             + "        },\n"
340             + "        _first: true\n"
341             + "      };\n"
342             + "    };\n"
343             + "    var myMap = new Map(myIterable);\n"
344             + "    log(myMap.size);\n"
345             + "    myMap.forEach(logElement);\n"
346             + "  }catch(e) { logEx(e); }"
347             + "}\n"
348             + "</script></head>\n"
349             + "<body onload='test()'>\n"
350             + "</body></html>";
351 
352         loadPageVerifyTitle2(html);
353     }
354 
355     /**
356      * @throws Exception if the test fails
357      */
358     @Test
359     @Alerts({"value1", "key1", "[object Map]", "[object Window]",
360              "[object Object]", "key2", "[object Map]", "[object Window]",
361              "null", "key3", "[object Map]", "[object Window]",
362              "undefined", "key4", "[object Map]", "[object Window]"})
363     public void forEach() throws Exception {
364         final String html = DOCTYPE_HTML
365             + "<html><head>\n"
366             + "<script>\n"
367             + LOG_TITLE_FUNCTION
368             + "function logElement(value, key, m) {\n"
369             + "  log(value);\n"
370             + "  log(key);\n"
371             + "  log(m);\n"
372             + "  log(this);\n"
373             + "}\n"
374             + "function test() {\n"
375             + "try {"
376             + "  var myMap = new Map([['key1', 'value1'], ['key2', {}], ['key3', null], ['key4', undefined]]);\n"
377             + "  myMap.forEach(logElement);\n"
378              + "}catch(e){log(e)}"
379             + "}\n"
380             + "</script>\n"
381             + "</head>\n"
382             + "<body onload='test()'>\n"
383             + "</body></html>";
384 
385         loadPageVerifyTitle2(html);
386     }
387 
388     /**
389      * @throws Exception if the test fails
390      */
391     @Test
392     @Alerts({"value1", "key1", "[object Map]", "undefined",
393              "[object Object]", "key2", "[object Map]", "undefined",
394              "null", "key3", "[object Map]", "undefined",
395              "undefined", "key4", "[object Map]", "undefined"})
396     public void forEachStrict() throws Exception {
397         final String html = DOCTYPE_HTML
398             + "<html><head>\n"
399             + "<script>\n"
400             + "'use strict';\n"
401             + LOG_TITLE_FUNCTION
402             + "function logElement(value, key, m) {\n"
403             + "  log(value);\n"
404             + "  log(key);\n"
405             + "  log(m);\n"
406             + "  log(this);\n"
407             + "}\n"
408             + "function test() {\n"
409             + "try {"
410             + "  var myMap = new Map([['key1', 'value1'], ['key2', {}], ['key3', null], ['key4', undefined]]);\n"
411             + "  myMap.forEach(logElement);\n"
412              + "}catch(e){log(e)}"
413             + "}\n"
414             + "</script>\n"
415             + "</head>\n"
416             + "<body onload='test()'>\n"
417             + "</body></html>";
418 
419         loadPageVerifyTitle2(html);
420     }
421 
422     /**
423      * @throws Exception if the test fails
424      */
425     @Test
426     @Alerts({"value1", "key1", "[object Map]", "hello",
427              "[object Object]", "key2", "[object Map]", "hello",
428              "null", "key3", "[object Map]", "hello",
429              "undefined", "key4", "[object Map]", "hello"})
430     public void forEachThis() throws Exception {
431         final String html = DOCTYPE_HTML
432             + "<html><head>\n"
433             + "<script>\n"
434             + LOG_TITLE_FUNCTION
435             + "function logElement(value, key, m) {\n"
436             + "  log(value);\n"
437             + "  log(key);\n"
438             + "  log(m);\n"
439             + "  log(this);\n"
440             + "}\n"
441             + "function test() {\n"
442             + "  var myMap = new Map([['key1', 'value1'], ['key2', {}], ['key3', null], ['key4', undefined]]);\n"
443             + "  myMap.forEach(logElement, 'hello');\n"
444             + "}\n"
445             + "</script></head><body onload='test()'>\n"
446             + "</body></html>";
447 
448         loadPageVerifyTitle2(html);
449     }
450 
451     /**
452      * Test case for Bug #1868.
453      *
454      * @throws Exception if the test fails
455      */
456     @Test
457     @Alerts("[object Map Iterator]")
458     public void iteratorPrototype() throws Exception {
459         final String html = DOCTYPE_HTML
460             + "<html>\n"
461             + "<head>\n"
462             + "<script>\n"
463             + LOG_TITLE_FUNCTION
464             + "  function test() {\n"
465             + "    if (window.Symbol) {\n"
466             + "      var myMap = new Map();\n"
467             + "      var iter = myMap[Symbol.iterator]();\n"
468             + "      log(Object.getPrototypeOf(iter));\n"
469             + "    }\n"
470             + "  }\n"
471             + "</script>\n"
472             + "</head>\n"
473             + "<body onload='test()'>\n"
474             + "</body></html>";
475 
476         loadPageVerifyTitle2(html);
477     }
478 
479     /**
480      * @throws Exception if the test fails
481      */
482     @Test
483     @Alerts({"value1", "undefined", "[object Map]", "[object Window]",
484              "[object Object]", "key2", "[object Map]", "[object Window]"})
485     public void forEach_withElision() throws Exception {
486         final String html = DOCTYPE_HTML
487             + "<html><head>\n"
488             + "<script>\n"
489             + LOG_TITLE_FUNCTION
490             + "function logElement(value, key, m) {\n"
491             + "  log(value);\n"
492             + "  log(key);\n"
493             + "  log(m);\n"
494             + "  log(this);\n"
495             + "}\n"
496             + "function test() {\n"
497             + "try {"
498             + "  var myMap = new Map([[, 'value1'], ['key2', {}]]);\n"
499             + "  myMap.forEach(logElement);\n"
500              + "}catch(e){log(e)}"
501             + "}\n"
502             + "</script></head><body onload='test()'>\n"
503             + "</body></html>";
504 
505         loadPageVerifyTitle2(html);
506     }
507 
508     /**
509      * @throws Exception if the test fails
510      */
511     @Test
512     @Alerts({"0", "0"})
513     public void setSize() throws Exception {
514         final String html = DOCTYPE_HTML
515             + "<html>\n"
516             + "<head>\n"
517             + "<script>\n"
518             + LOG_TITLE_FUNCTION
519             + "function test() {\n"
520             + "  var map = new Map();\n"
521             + "  try {\n"
522             + "    log(map.size);\n"
523             + "    map.size = 100;\n"
524             + "    log(map.size);\n"
525             + "  } catch(e) { log(e); }\n"
526             + "}\n"
527             + "</script></head>\n"
528             + "<body onload='test()'>\n"
529             + "</body></html>";
530 
531         loadPageVerifyTitle2(html);
532     }
533 
534     /**
535      * @throws Exception if the test fails
536      */
537     @Test
538     @Alerts({"0", "Type error"})
539     public void setSizeStrictMode() throws Exception {
540         final String html = DOCTYPE_HTML
541             + "<html>\n"
542             + "<head>\n"
543             + "<script>\n"
544             + LOG_TITLE_FUNCTION
545             + "function test() {\n"
546             + "  'use strict';\n"
547             + "  var map = new Map();\n"
548             + "  try {\n"
549             + "    log(map.size);\n"
550             + "    map.size = 100;\n"
551             + "    log(map.size);\n"
552             + "  } catch(e) { log('Type error'); }\n"
553             + "}\n"
554             + "</script></head>\n"
555             + "<body onload='test()'>\n"
556             + "</body></html>";
557 
558         loadPageVerifyTitle2(html);
559     }
560 
561 }