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;
16  
17  import org.htmlunit.WebDriverTestCase;
18  import org.htmlunit.junit.BrowserRunner;
19  import org.htmlunit.junit.annotation.Alerts;
20  import org.htmlunit.junit.annotation.HtmlUnitNYI;
21  import org.junit.Test;
22  import org.junit.runner.RunWith;
23  
24  /**
25   * Object is a native JavaScript object and therefore provided by Rhino but some tests are needed here
26   * to be sure that we have the expected results.
27   *
28   * @author Marc Guillemot
29   * @author Frank Danek
30   * @author Ahmed Ashour
31   * @author Natasha Lazarova
32   * @author Ronald Brill
33   */
34  @RunWith(BrowserRunner.class)
35  public class NativeObjectTest extends WebDriverTestCase {
36  
37      /**
38       * Test for the methods with the same expectations for all browsers.
39       * @throws Exception if the test fails
40       */
41      @Test
42      @Alerts({"assign: undefined", "constructor: function", "create: undefined", "defineProperties: undefined",
43               "defineProperty: undefined", "freeze: undefined", "getOwnPropertyDescriptor: undefined",
44               "getOwnPropertyNames: undefined", "getPrototypeOf: undefined", "hasOwnProperty: function",
45               "isExtensible: undefined", "isFrozen: undefined", "isPrototypeOf: function", "isSealed: undefined",
46               "keys: undefined", "preventExtensions: undefined", "propertyIsEnumerable: function", "seal: undefined",
47               "toLocaleString: function", "toString: function", "valueOf: function", "__defineGetter__: function",
48               "__defineSetter__: function", "__lookupGetter__: function", "__lookupSetter__: function"})
49      public void common() throws Exception {
50          final String[] methods = {
51              "assign", "constructor", "create", "defineProperties", "defineProperty", "freeze",
52              "getOwnPropertyDescriptor", "getOwnPropertyNames", "getPrototypeOf", "hasOwnProperty", "isExtensible",
53              "isFrozen", "isPrototypeOf", "isSealed", "keys", "preventExtensions", "propertyIsEnumerable", "seal",
54              "toLocaleString", "toString", "valueOf", "__defineGetter__", "__defineSetter__",
55              "__lookupGetter__", "__lookupSetter__"};
56          final String html = NativeDateTest.createHTMLTestMethods("new Object()", methods);
57          loadPageVerifyTitle2(html);
58      }
59  
60      /**
61       * Test for the methods with the different expectations depending on the browsers.
62       * @throws Exception if the test fails
63       */
64      @Test
65      @Alerts("toSource: undefined")
66      public void others() throws Exception {
67          final String[] methods = {"toSource"};
68          final String html = NativeDateTest.createHTMLTestMethods("new Object()", methods);
69          loadPageVerifyTitle2(html);
70      }
71  
72      /**
73       * @throws Exception if the test fails
74       */
75      @Test
76      @Alerts("1")
77      public void assign() throws Exception {
78          final String html = DOCTYPE_HTML
79              + "<html><head><script>\n"
80              + LOG_TITLE_FUNCTION
81              + "function test() {\n"
82              + "  if (Object.assign) {\n"
83              + "    var obj = { a: 1 };\n"
84              + "    var copy = Object.assign({}, obj);\n"
85              + "    log(copy.a);\n"
86              + "  }\n"
87              + "}\n"
88              + "</script></head><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("1")
99      public void assignUndefined() throws Exception {
100         final String html = DOCTYPE_HTML
101             + "<html><head><script>\n"
102             + "function test() {\n"
103             + LOG_TITLE_FUNCTION
104             + "  if (Object.assign) {\n"
105             + "    var obj = { a: 1 };\n"
106             + "    var copy = Object.assign({}, undefined, obj);\n"
107             + "    log(copy.a);\n"
108             + "  }\n"
109             + "}\n"
110             + "</script></head><body onload='test()'>\n"
111             + "</body></html>";
112 
113         loadPageVerifyTitle2(html);
114     }
115 
116     /**
117      * @throws Exception if the test fails
118      */
119     @Test
120     @Alerts("undefined")
121     public void assignUndefined2() throws Exception {
122         final String html = DOCTYPE_HTML
123                 + "<html><head><script>\n"
124                 + "function test() {\n"
125                 + LOG_TITLE_FUNCTION
126                 + "  if (Object.assign) {\n"
127                 + "    var copy = Object.assign({}, undefined, undefined);\n"
128                 + "    log(copy.a);\n"
129                 + "  }\n"
130                 + "}\n"
131                 + "</script></head><body onload='test()'>\n"
132                 + "</body></html>";
133 
134         loadPageVerifyTitle2(html);
135     }
136 
137     /**
138      * @throws Exception if the test fails
139      */
140     @Test
141     @Alerts("undefined")
142     public void assignNull() throws Exception {
143         final String html = DOCTYPE_HTML
144                 + "<html><head><script>\n"
145                 + "function test() {\n"
146                 + LOG_TITLE_FUNCTION
147                 + "  if (Object.assign) {\n"
148                 + "    var copy = Object.assign({}, null);\n"
149                 + "    log(copy.a);\n"
150                 + "  }\n"
151                 + "}\n"
152                 + "</script></head><body onload='test()'>\n"
153                 + "</body></html>";
154 
155         loadPageVerifyTitle2(html);
156     }
157 
158     /**
159      * @throws Exception if the test fails
160      */
161     @Test
162     @Alerts("undefined")
163     public void assignNull2() throws Exception {
164         final String html = DOCTYPE_HTML
165                 + "<html><head><script>\n"
166                 + "function test() {\n"
167                 + LOG_TITLE_FUNCTION
168                 + "  if (Object.assign) {\n"
169                 + "    var copy = Object.assign({}, null, null);\n"
170                 + "    log(copy.a);\n"
171                 + "  }\n"
172                 + "}\n"
173                 + "</script></head><body onload='test()'>\n"
174                 + "</body></html>";
175 
176         loadPageVerifyTitle2(html);
177     }
178 
179     /**
180      * @throws Exception if the test fails
181      */
182     @Test
183     @Alerts(DEFAULT = "function\\s()\\s{\\s[native\\scode]\\s}",
184             FF = "function\\s()\\s{\\n\\s\\s\\s\\s[native\\scode]\\n}",
185             FF_ESR = "function\\s()\\s{\\n\\s\\s\\s\\s[native\\scode]\\n}")
186     public void proto() throws Exception {
187         final String html = DOCTYPE_HTML
188             + "<html><head>\n"
189             + "<script>\n"
190             + LOG_TITLE_FUNCTION_NORMALIZE
191             + "  function test() {\n"
192             + "    log(Object.__proto__);\n"
193             + "  }\n"
194             + "</script>\n"
195             + "</head>\n"
196             + "<body onload='test()'>\n"
197             + "</body></html>";
198 
199         loadPageVerifyTitle2(html);
200     }
201 
202     /**
203      * Test case for Bug #1856.
204      *
205      * @throws Exception if the test fails
206      */
207     @Test
208     @Alerts({"[object Object]", "null"})
209     public void proto2() throws Exception {
210         final String html = DOCTYPE_HTML
211             + "<html><head>\n"
212             + "<script>\n"
213             + LOG_TITLE_FUNCTION
214             + "  function test() {\n"
215             + "    log({}.__proto__);\n"
216             + "    log({}.__proto__.__proto__);\n"
217             + "  }\n"
218             + "</script>\n"
219             + "</head>\n"
220             + "<body onload='test()'>\n"
221             + "</body></html>";
222 
223         loadPageVerifyTitle2(html);
224     }
225 
226     /**
227      * Test case for #1855.
228      *
229      * @throws Exception if the test fails
230      */
231     @Test
232     @Alerts("true")
233     public void getPrototypeOfString() throws Exception {
234         final String html = DOCTYPE_HTML
235             + "<html><head>\n"
236             + "<script>\n"
237             + LOG_TITLE_FUNCTION
238             + "  function test() {\n"
239             + "    try {\n"
240             + "      log(String.prototype === Object.getPrototypeOf(''));\n"
241             + "    } catch(e) { logEx(e) }\n"
242             + "  }\n"
243             + "</script>\n"
244             + "</head>\n"
245             + "<body onload='test()'>\n"
246             + "</body></html>";
247 
248         loadPageVerifyTitle2(html);
249     }
250 
251     /**
252      * @throws Exception if the test fails
253      */
254     @Test
255     @Alerts("true")
256     public void getPrototypeOfNumber() throws Exception {
257         final String html = DOCTYPE_HTML
258             + "<html><head>\n"
259             + "<script>\n"
260             + LOG_TITLE_FUNCTION
261             + "  function test() {\n"
262             + "    try {\n"
263             + "      log(Number.prototype === Object.getPrototypeOf(1));\n"
264             + "    } catch(e) { logEx(e) }\n"
265             + "  }\n"
266             + "</script>\n"
267             + "</head>\n"
268             + "<body onload='test()'>\n"
269             + "</body></html>";
270 
271         loadPageVerifyTitle2(html);
272     }
273 
274     /**
275      * @throws Exception if the test fails
276      */
277     @Test
278     @Alerts("true")
279     public void getPrototypeOfBoolean() throws Exception {
280         final String html = DOCTYPE_HTML
281             + "<html><head>\n"
282             + "<script>\n"
283             + LOG_TITLE_FUNCTION
284             + "  function test() {\n"
285             + "    try {\n"
286             + "      log(Boolean.prototype === Object.getPrototypeOf(true));\n"
287             + "    } catch(e) { logEx(e) }\n"
288             + "  }\n"
289             + "</script>\n"
290             + "</head>\n"
291             + "<body onload='test()'>\n"
292             + "</body></html>";
293 
294         loadPageVerifyTitle2(html);
295     }
296 
297     /**
298      * @throws Exception if the test fails
299      */
300     @Test
301     @Alerts("object")
302     public void getTypeOfPrototypeOfNumber() throws Exception {
303         final String html = DOCTYPE_HTML
304             + "<html><head>\n"
305             + "<script>\n"
306             + LOG_TITLE_FUNCTION
307             + "  function test() {\n"
308             + "    try {\n"
309             + "      log(typeof Object.getPrototypeOf(1));\n"
310             + "    } catch(e) { logEx(e) }\n"
311             + "  }\n"
312             + "</script>\n"
313             + "</head>\n"
314             + "<body onload='test()'>\n"
315             + "</body></html>";
316 
317         loadPageVerifyTitle2(html);
318     }
319 
320     /**
321      * @throws Exception if the test fails
322      */
323     @Test
324     @Alerts({"2", "true", "true"})
325     public void getOwnPropertySymbols() throws Exception {
326         final String html = DOCTYPE_HTML
327             + "<html><head>\n"
328             + "<script>\n"
329             + LOG_TITLE_FUNCTION
330             + "  function test() {\n"
331             + "    try {\n"
332             + "      var obj = {};\n"
333             + "      var a = Symbol('a');\n"
334             + "      var b = Symbol.for('b');\n"
335             + "\n"
336             + "      obj[a] = 'localSymbol';\n"
337             + "      obj[b] = 'globalSymbol';\n"
338             + "\n"
339             + "      var objectSymbols = Object.getOwnPropertySymbols(obj);\n"
340             + "      log(objectSymbols.length);\n"
341             + "      log(objectSymbols[0] === a);\n"
342             + "      log(objectSymbols[1] === b);\n"
343             + "    } catch(e) { logEx(e) }\n"
344             + "  }\n"
345             + "</script>\n"
346             + "</head>\n"
347             + "<body onload='test()'>\n"
348             + "</body></html>";
349 
350         loadPageVerifyTitle2(html);
351     }
352 
353     /**
354      * @throws Exception if the test fails
355      */
356     @Test
357     @Alerts("TypeError")
358     public void getOwnPropertySymbolsEmpty() throws Exception {
359         final String html = DOCTYPE_HTML
360             + "<html><head>\n"
361             + "<script>\n"
362             + LOG_TITLE_FUNCTION
363             + "  function test() {\n"
364             + "    try {\n"
365             + "      var objectSymbols = Object.getOwnPropertySymbols();\n"
366             + "      log(objectSymbols.length);\n"
367             + "    } catch(e) { logEx(e) }\n"
368             + "  }\n"
369             + "</script>\n"
370             + "</head>\n"
371             + "<body onload='test()'>\n"
372             + "</body></html>";
373 
374         loadPageVerifyTitle2(html);
375     }
376 
377     /**
378      * @throws Exception if the test fails
379      */
380     @Test
381     @Alerts(CHROME = {"[object HTMLInputElement]", "[object HTMLInputElement]", "[object Object]", "function"},
382             EDGE = {"[object HTMLInputElement]", "[object HTMLInputElement]", "[object Object]", "function"},
383             FF = {"[object HTMLInputElement]", "[object HTMLInputElement]", "[object Object]", "function"},
384             FF_ESR = {"[object HTMLInputElement]", "[object HTMLInputElement]", "[object Object]", "function"})
385     public void getOwnPropertyDescriptor() throws Exception {
386         final String html = DOCTYPE_HTML
387             + "<html><head>\n"
388             + "<script>\n"
389             + LOG_TITLE_FUNCTION
390             + "  function test() {\n"
391             + "    try {\n"
392             + "      var input = document.getElementById('myInput');\n"
393             + "      log(input);\n"
394             + "      var proto = input.constructor.prototype;\n"
395             + "      log(proto);\n"
396             + "      var desc = Object.getOwnPropertyDescriptor(proto, 'value');\n"
397             + "      log(desc);\n"
398 
399             + "      log(typeof desc.get);\n"
400             + "    } catch(e) { logEx(e) }\n"
401             + "  }\n"
402             + "</script>\n"
403             + "</head>\n"
404             + "<body onload='test()'>\n"
405             + "  <input id='myInput' value='some test'>\n"
406             + "</body></html>";
407 
408         loadPageVerifyTitle2(html);
409     }
410 
411     /**
412      * @throws Exception if the test fails
413      */
414     @Test
415     @Alerts(DEFAULT = {"[object HTMLInputElement]", "x = [object Object]",
416                        "x.get = function get value() { [native code] }",
417                        "x.get.call = function call() { [native code] }"},
418             FF = {"[object HTMLInputElement]", "x = [object Object]",
419                   "x.get = function value() {\n    [native code]\n}",
420                   "x.get.call = function call() {\n    [native code]\n}"},
421             FF_ESR = {"[object HTMLInputElement]", "x = [object Object]",
422                       "x.get = function value() {\n    [native code]\n}",
423                       "x.get.call = function call() {\n    [native code]\n}"})
424     @HtmlUnitNYI(CHROME = {"[object HTMLInputElement]", "x = [object Object]",
425                            "x.get = function value() { [native code] }",
426                            "x.get.call = function call() { [native code] }"},
427             EDGE = {"[object HTMLInputElement]", "x = [object Object]",
428                     "x.get = function value() { [native code] }",
429                     "x.get.call = function call() { [native code] }"})
430     public void getOwnPropertyDescriptorGetCall() throws Exception {
431         final String html = DOCTYPE_HTML
432             + "<html><head><script>\n"
433             + LOG_TEXTAREA_FUNCTION
434             + "function test() {\n"
435             + "  var proto = i1.constructor.prototype;\n"
436             + "  log(proto);\n"
437             + "  var x = Object.getOwnPropertyDescriptor(i1.constructor.prototype, 'value');\n"
438             + "  log('x = ' + x);\n"
439             + "  log('x.get = ' + x.get);\n"
440             + "  log('x.get.call = ' + x.get.call);\n"
441             + "}\n"
442             + "</script></head>\n"
443             + "<body onload='test()'>\n"
444             + "  <input type='text' id='i1' value='foo' />\n"
445             + LOG_TEXTAREA
446             + "</body></html>";
447 
448         loadPageVerifyTextArea2(html);
449     }
450 
451     /**
452      * @throws Exception if the test fails
453      */
454     @Test
455     @Alerts({"before: [object Object]", "after: [object Object]", "true"})
456     public void definePropertyUsingConsString() throws Exception {
457         final String html = DOCTYPE_HTML
458             + "<html><head><script>\n"
459             + LOG_TITLE_FUNCTION
460             + "function test() {\n"
461             + "  'use strict';\n"
462             + "  var f = function () {};\n"
463             + "  var a1='proto';\n"
464             + "  var p = a1 + 'type';\n"
465             + "  log('before: ' + f.prototype);\n"
466             + "  Object.defineProperty(f, p, {});\n"
467             + "  log('after: ' + f.prototype);\n"
468             + "  var p = new f();\n"
469             + "  log(p instanceof f);\n"
470             + "}\n"
471             + "</script></head>\n"
472             + "<body onload='test()'>\n"
473             + "</body></html>";
474 
475         loadPageVerifyTitle2(html);
476     }
477 }