1
2
3
4
5
6
7
8
9
10
11
12
13
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 import org.openqa.selenium.WebDriverException;
22
23
24
25
26
27
28
29 public class ScriptableObjectTest extends WebDriverTestCase {
30
31
32
33
34
35
36
37 @Test
38 @Alerts({"default", "default", "default"})
39 public void readOnlyPrototype() throws Exception {
40 final String html = DOCTYPE_HTML
41 + "<html><body>\n"
42 + "<script>\n"
43 + LOG_TITLE_FUNCTION
44 + " var proto = Object.create(Object.prototype, {\n"
45 + " myProp: {\n"
46 + " get: function() { return 'default'; }\n"
47 + " }\n"
48 + " });\n"
49 + " var o1 = Object.create(proto);\n"
50 + " var o2 = Object.create(proto);\n"
51 + " o2.myProp = 'bar';\n"
52 + " log(o2.myProp);\n"
53 + " log(o1.myProp);\n"
54 + " log(proto.myProp)"
55 + "</script>\n"
56 + "</body>\n"
57 + "</html>\n";
58
59 loadPageVerifyTitle2(html);
60 }
61
62
63
64
65 @Test
66 @Alerts({"2", "symbol", "symbol", "1", "c"})
67 public void getOwnPropertySymbols() throws Exception {
68 final String html = DOCTYPE_HTML
69 + "<html><body>\n"
70 + "<script>\n"
71 + LOG_TITLE_FUNCTION
72 + " if (Object.getOwnPropertySymbols) {\n"
73
74 + " var obj = {};\n"
75 + " var a = Symbol('a');\n"
76 + " var b = Symbol.for('b');\n"
77
78 + " obj[a] = 'localSymbol';\n"
79 + " obj[b] = 'globalSymbol';\n"
80 + " obj['c'] = 'something else';\n"
81
82 + " var objectSymbols = Object.getOwnPropertySymbols(obj);\n"
83 + " log(objectSymbols.length);\n"
84 + " log(typeof objectSymbols[0]);\n"
85 + " log(typeof objectSymbols[1]);\n"
86
87 + " var objectNames = Object.getOwnPropertyNames(obj);\n"
88 + " log(objectNames.length);\n"
89 + " log(objectNames[0]);\n"
90
91 + " } else { log('not defined'); }\n"
92 + "</script>\n"
93 + "</body>\n"
94 + "</html>\n";
95
96 loadPageVerifyTitle2(html);
97 }
98
99
100
101
102 @Test
103 @Alerts({"TypeError", "true", "true"})
104 public void ctorNotChangeableForPrimitives() throws Exception {
105 final String html = DOCTYPE_HTML
106 + "<html><body>\n"
107 + "<script>\n"
108 + LOG_TITLE_FUNCTION
109 + " let val = null;\n"
110 + " try {\n"
111 + " val.constructor = 1;\n"
112 + " } catch(e) { logEx(e); }\n"
113
114 + " val = 'abc';\n"
115 + " val.constructor = Number;"
116 + " log(val.constructor === String)\n"
117
118
119 + " val.foo = 'bar';\n"
120
121
122 + " log (val.foo === undefined);\n"
123
124 + "</script>\n"
125 + "</body>\n"
126 + "</html>\n";
127
128 loadPageVerifyTitle2(html);
129 }
130
131
132
133
134
135 @Test
136 @Alerts({"TypeError", "true", "true"})
137 @HtmlUnitNYI(CHROME = "org.htmlunit.ScriptException: TypeError: Cannot set property \"constructor\" of abc",
138 EDGE = "org.htmlunit.ScriptException: TypeError: Cannot set property \"constructor\" of abc",
139 FF = "org.htmlunit.ScriptException: TypeError: Cannot set property \"constructor\" of abc",
140 FF_ESR = "org.htmlunit.ScriptException: TypeError: Cannot set property \"constructor\" of abc")
141 public void ctorNotChangeableForPrimitivesStrict() throws Exception {
142 final String html = DOCTYPE_HTML
143 + "<html><body>\n"
144 + "<script>\n"
145 + LOG_TITLE_FUNCTION
146
147 + " 'use strict';\n"
148
149 + " let val = null;\n"
150 + " try {\n"
151 + " val.constructor = 1;\n"
152 + " } catch(e) { logEx(e); }\n"
153
154 + " val = 'abc';\n"
155 + " val.constructor = Number;"
156 + " log(val.constructor === String)\n"
157
158
159 + " val.foo = 'bar';\n"
160
161
162 + " log (val.foo === undefined);\n"
163
164 + "</script>\n"
165 + "</body>\n"
166 + "</html>\n";
167
168 try {
169 loadPageVerifyTitle2(html);
170 }
171 catch (final WebDriverException e) {
172 assertTrue(e.getMessage(), e.getMessage().startsWith(getExpectedAlerts()[0]));
173 }
174 }
175
176
177
178
179 @Test
180 @Alerts({"true", "false", "true", "ctor", "true"})
181 public void ctorChangeableHasNoEffectForTypeOf() throws Exception {
182 final String html = DOCTYPE_HTML
183 + "<html><body>\n"
184 + "<script>\n"
185 + LOG_TITLE_FUNCTION
186
187 + " let a = [];\n"
188 + " a.constructor = String\n"
189 + " log(a.constructor === String);\n"
190 + " log(a instanceof String);\n"
191 + " log(a instanceof Array);\n"
192
193 + " try {\n"
194 + " a = new Event('test');\n"
195 + " log('ctor');\n"
196 + " a.constructor = 'bar';\n"
197 + " log(a.constructor === 'bar');\n"
198 + " } catch(e) { logEx(e) }\n"
199
200 + "</script>\n"
201 + "</body>\n"
202 + "</html>\n";
203
204 loadPageVerifyTitle2(html);
205 }
206
207
208
209
210 @Test
211 @Alerts({"true", "false", "true", "ctor", "true"})
212 public void ctorChangeableHasNoEffectForTypeOfStrict() throws Exception {
213 final String html = DOCTYPE_HTML
214 + "<html><body>\n"
215 + "<script>\n"
216 + " 'use strict';\n"
217 + LOG_TITLE_FUNCTION
218
219 + " let a = [];\n"
220 + " a.constructor = String\n"
221 + " log(a.constructor === String);\n"
222 + " log(a instanceof String);\n"
223 + " log(a instanceof Array);\n"
224
225 + " try {\n"
226 + " a = new Event('test');\n"
227 + " log('ctor');\n"
228 + " a.constructor = 'bar';\n"
229 + " log(a.constructor === 'bar');\n"
230 + " } catch(e) { logEx(e) }\n"
231
232 + "</script>\n"
233 + "</body>\n"
234 + "</html>\n";
235
236 loadPageVerifyTitle2(html);
237 }
238
239
240
241
242 @Test
243 @Alerts("true")
244 public void ctorChangeableHasNoEffectForSealed() throws Exception {
245 final String html = DOCTYPE_HTML
246 + "<html><body>\n"
247 + "<script>\n"
248 + LOG_TITLE_FUNCTION
249
250 + " let a = Object.seal({});\n"
251 + " a.constructor = Number;\n"
252 + " log(a.constructor === Object);\n"
253
254 + "</script>\n"
255 + "</body>\n"
256 + "</html>\n";
257
258 loadPageVerifyTitle2(html);
259 }
260
261
262
263
264 @Test
265 @Alerts("true")
266 @HtmlUnitNYI(CHROME = "TypeError",
267 EDGE = "TypeError",
268 FF = "TypeError",
269 FF_ESR = "TypeError")
270 public void ctorChangeableHasNoEffectForSealedStrict() throws Exception {
271 final String html = DOCTYPE_HTML
272 + "<html><body>\n"
273 + "<script>\n"
274 + LOG_TITLE_FUNCTION
275
276 + " 'use strict';\n"
277
278 + " let a = Object.seal({});\n"
279 + " try {\n"
280 + " a.constructor = Number;\n"
281 + " log(a.constructor === Object);\n"
282 + " } catch(e) { logEx(e) }\n"
283
284 + "</script>\n"
285 + "</body>\n"
286 + "</html>\n";
287
288 loadPageVerifyTitle2(html);
289 }
290 }