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