Object-toSource.js (10635B)
1 // |reftest| skip-if(!Object.prototype.toSource) 2 3 var BUGNUMBER = 1317400; 4 var summary = "Function string representation in Object.prototype.toSource"; 5 6 print(BUGNUMBER + ": " + summary); 7 8 // Methods. 9 10 assertEq(({ foo(){} }).toSource(), 11 "({foo(){}})"); 12 assertEq(({ *foo(){} }).toSource(), 13 "({*foo(){}})"); 14 assertEq(({ async foo(){} }).toSource(), 15 "({async foo(){}})"); 16 17 assertEq(({ 1(){} }).toSource(), 18 "({1(){}})"); 19 20 // Methods with more spacing. 21 // Spacing is kept. 22 23 assertEq(({ foo (){} }).toSource(), 24 "({foo (){}})"); 25 assertEq(({ foo () {} }).toSource(), 26 "({foo () {}})"); 27 28 // Methods with computed name. 29 // Method syntax is composed. 30 31 let name = "foo"; 32 assertEq(({ [name](){} }).toSource(), 33 "({foo(){}})"); 34 assertEq(({ *[name](){} }).toSource(), 35 "({*foo(){}})"); 36 assertEq(({ async [name](){} }).toSource(), 37 "({async foo(){}})"); 38 39 assertEq(({ [ Symbol.iterator ](){} }).toSource(), 40 "({[Symbol.iterator](){}})"); 41 42 // Accessors. 43 44 assertEq(({ get foo(){} }).toSource(), 45 "({get foo(){}})"); 46 assertEq(({ set foo(v){} }).toSource(), 47 "({set foo(v){}})"); 48 49 // Accessors with computed name. 50 // Method syntax is composed. 51 52 assertEq(({ get [name](){} }).toSource(), 53 "({get foo(){}})"); 54 assertEq(({ set [name](v){} }).toSource(), 55 "({set foo(v){}})"); 56 57 assertEq(({ get [ Symbol.iterator ](){} }).toSource(), 58 "({get [Symbol.iterator](){}})"); 59 assertEq(({ set [ Symbol.iterator ](v){} }).toSource(), 60 "({set [Symbol.iterator](v){}})"); 61 62 // Getter and setter with same name. 63 // Getter always comes before setter. 64 65 assertEq(({ get foo(){}, set foo(v){} }).toSource(), 66 "({get foo(){}, set foo(v){}})"); 67 assertEq(({ set foo(v){}, get foo(){} }).toSource(), 68 "({get foo(){}, set foo(v){}})"); 69 70 // Normal properties. 71 72 assertEq(({ foo: function(){} }).toSource(), 73 "({foo:(function(){})})"); 74 assertEq(({ foo: function bar(){} }).toSource(), 75 "({foo:(function bar(){})})"); 76 assertEq(({ foo: function*(){} }).toSource(), 77 "({foo:(function*(){})})"); 78 assertEq(({ foo: async function(){} }).toSource(), 79 "({foo:(async function(){})})"); 80 81 // Normal properties with computed name. 82 83 assertEq(({ [ Symbol.iterator ]: function(){} }).toSource(), 84 "({[Symbol.iterator]:(function(){})})"); 85 86 // Dynamically defined properties with function expression. 87 // Never become a method syntax. 88 89 let obj = {}; 90 obj.foo = function() {}; 91 assertEq(obj.toSource(), 92 "({foo:(function() {})})"); 93 94 obj = {}; 95 Object.defineProperty(obj, "foo", {value: function() {}}); 96 assertEq(obj.toSource(), 97 "({})"); 98 99 obj = {}; 100 Object.defineProperty(obj, "foo", {value: function() {}, enumerable: true}); 101 assertEq(obj.toSource(), 102 "({foo:(function() {})})"); 103 104 obj = {}; 105 Object.defineProperty(obj, "foo", {value: function bar() {}, enumerable: true}); 106 assertEq(obj.toSource(), 107 "({foo:(function bar() {})})"); 108 109 obj = {}; 110 Object.defineProperty(obj, Symbol.iterator, {value: function() {}, enumerable: true}); 111 assertEq(obj.toSource(), 112 "({[Symbol.iterator]:(function() {})})"); 113 114 // Dynamically defined property with other object's method. 115 // Method syntax is composed. 116 117 let method = ({foo() {}}).foo; 118 119 obj = {}; 120 Object.defineProperty(obj, "foo", {value: method, enumerable: true}); 121 assertEq(obj.toSource(), 122 "({foo() {}})"); 123 124 obj = {}; 125 Object.defineProperty(obj, "bar", {value: method, enumerable: true}); 126 assertEq(obj.toSource(), 127 "({bar() {}})"); 128 129 method = ({*foo() {}}).foo; 130 131 obj = {}; 132 Object.defineProperty(obj, "bar", {value: method, enumerable: true}); 133 assertEq(obj.toSource(), 134 "({*bar() {}})"); 135 136 method = ({async foo() {}}).foo; 137 138 obj = {}; 139 Object.defineProperty(obj, "bar", {value: method, enumerable: true}); 140 assertEq(obj.toSource(), 141 "({async bar() {}})"); 142 143 // Dynamically defined accessors. 144 // Accessor syntax is composed. 145 146 obj = {}; 147 Object.defineProperty(obj, "foo", {get: function() {}, enumerable: true}); 148 assertEq(obj.toSource(), 149 "({get foo() {}})"); 150 151 obj = {}; 152 Object.defineProperty(obj, "foo", {set: function() {}, enumerable: true}); 153 assertEq(obj.toSource(), 154 "({set foo() {}})"); 155 156 obj = {}; 157 Object.defineProperty(obj, Symbol.iterator, {get: function() {}, enumerable: true}); 158 assertEq(obj.toSource(), 159 "({get [Symbol.iterator]() {}})"); 160 161 obj = {}; 162 Object.defineProperty(obj, Symbol.iterator, {set: function() {}, enumerable: true}); 163 assertEq(obj.toSource(), 164 "({set [Symbol.iterator]() {}})"); 165 166 // Dynamically defined accessors with other object's accessors. 167 // Accessor syntax is composed. 168 169 let accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get; 170 obj = {}; 171 Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); 172 assertEq(obj.toSource(), 173 "({get foo() {}})"); 174 175 accessor = Object.getOwnPropertyDescriptor({ get bar() {} }, "bar").get; 176 obj = {}; 177 Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); 178 assertEq(obj.toSource(), 179 "({get foo() {}})"); 180 181 accessor = Object.getOwnPropertyDescriptor({ set foo(v) {} }, "foo").set; 182 obj = {}; 183 Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); 184 assertEq(obj.toSource(), 185 "({get foo(v) {}})"); 186 187 accessor = Object.getOwnPropertyDescriptor({ set bar(v) {} }, "bar").set; 188 obj = {}; 189 Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); 190 assertEq(obj.toSource(), 191 "({get foo(v) {}})"); 192 193 accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get; 194 obj = {}; 195 Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); 196 assertEq(obj.toSource(), 197 "({set foo() {}})"); 198 199 accessor = Object.getOwnPropertyDescriptor({ get bar() {} }, "bar").get; 200 obj = {}; 201 Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); 202 assertEq(obj.toSource(), 203 "({set foo() {}})"); 204 205 accessor = Object.getOwnPropertyDescriptor({ set foo(v) {} }, "foo").set; 206 obj = {}; 207 Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); 208 assertEq(obj.toSource(), 209 "({set foo(v) {}})"); 210 211 accessor = Object.getOwnPropertyDescriptor({ set bar(v) {} }, "bar").set; 212 obj = {}; 213 Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); 214 assertEq(obj.toSource(), 215 "({set foo(v) {}})"); 216 217 // Methods with proxy. 218 // Treated as normal property. 219 220 method = ({foo() {}}).foo; 221 let handler = { 222 get(that, name) { 223 if (name == "toSource") { 224 return function() { 225 return that.toSource(); 226 }; 227 } 228 return that[name]; 229 } 230 }; 231 let proxy = new Proxy(method, handler); 232 233 obj = {}; 234 Object.defineProperty(obj, "foo", {value: proxy, enumerable: true}); 235 assertEq(obj.toSource(), 236 "({foo:foo() {}})"); 237 238 // Accessors with proxy. 239 // Accessor syntax is composed. 240 241 accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get; 242 proxy = new Proxy(accessor, handler); 243 244 obj = {}; 245 Object.defineProperty(obj, "foo", {get: proxy, enumerable: true}); 246 assertEq(obj.toSource(), 247 "({get foo() {}})"); 248 249 obj = {}; 250 Object.defineProperty(obj, "foo", {set: proxy, enumerable: true}); 251 assertEq(obj.toSource(), 252 "({set foo() {}})"); 253 254 // Methods from other global. 255 // Treated as normal property in the cross-compartment case. 256 257 let g = newGlobal(); 258 259 method = g.eval("({ foo() {} }).foo"); 260 261 obj = {}; 262 Object.defineProperty(obj, "foo", {value: method, enumerable: true}); 263 assertEq((obj.toSource() === "({foo:foo() {}})" || 264 obj.toSource() === "({foo() {}})"), 265 true); 266 267 // Accessors from other global. 268 // Accessor syntax is composed. 269 270 accessor = g.eval("Object.getOwnPropertyDescriptor({ get foo() {} }, 'foo').get"); 271 272 obj = {}; 273 Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); 274 assertEq(obj.toSource(), 275 "({get foo() {}})"); 276 277 accessor = g.eval("Object.getOwnPropertyDescriptor({ get bar() {} }, 'bar').get"); 278 279 obj = {}; 280 Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); 281 assertEq(obj.toSource(), 282 "({get foo() {}})"); 283 284 accessor = g.eval("Object.getOwnPropertyDescriptor({ set foo(v) {} }, 'foo').set"); 285 286 obj = {}; 287 Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); 288 assertEq(obj.toSource(), 289 "({get foo(v) {}})"); 290 291 accessor = g.eval("Object.getOwnPropertyDescriptor({ set bar(v) {} }, 'bar').set"); 292 293 obj = {}; 294 Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); 295 assertEq(obj.toSource(), 296 "({get foo(v) {}})"); 297 298 accessor = g.eval("Object.getOwnPropertyDescriptor({ get foo() {} }, 'foo').get"); 299 300 obj = {}; 301 Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); 302 assertEq(obj.toSource(), 303 "({set foo() {}})"); 304 305 accessor = g.eval("Object.getOwnPropertyDescriptor({ get bar() {} }, 'bar').get"); 306 307 obj = {}; 308 Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); 309 assertEq(obj.toSource(), 310 "({set foo() {}})"); 311 312 accessor = g.eval("Object.getOwnPropertyDescriptor({ set foo(v) {} }, 'foo').set"); 313 314 obj = {}; 315 Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); 316 assertEq(obj.toSource(), 317 "({set foo(v) {}})"); 318 319 accessor = g.eval("Object.getOwnPropertyDescriptor({ set bar(v) {} }, 'bar').set"); 320 321 obj = {}; 322 Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); 323 assertEq(obj.toSource(), 324 "({set foo(v) {}})"); 325 326 // **** Some weird cases **** 327 328 // Accessors with generator or async. 329 330 obj = {}; 331 Object.defineProperty(obj, "foo", {get: function*() {}, enumerable: true}); 332 assertEq(obj.toSource(), 333 "({get foo() {}})"); 334 335 obj = {}; 336 Object.defineProperty(obj, "foo", {set: async function() {}, enumerable: true}); 337 assertEq(obj.toSource(), 338 "({set foo() {}})"); 339 340 // Modified toSource. 341 342 obj = { foo() {} }; 343 obj.foo.toSource = () => "hello"; 344 assertEq(obj.toSource(), 345 "({hello})"); 346 347 obj = { foo() {} }; 348 obj.foo.toSource = () => "bar() {}"; 349 assertEq(obj.toSource(), 350 "({bar() {}})"); 351 352 // Modified toSource with different method name. 353 354 obj = {}; 355 Object.defineProperty(obj, "foo", {value: function bar() {}, enumerable: true}); 356 obj.foo.toSource = () => "hello"; 357 assertEq(obj.toSource(), 358 "({foo:hello})"); 359 360 obj = {}; 361 Object.defineProperty(obj, "foo", {value: function* bar() {}, enumerable: true}); 362 obj.foo.toSource = () => "hello"; 363 assertEq(obj.toSource(), 364 "({foo:hello})"); 365 366 obj = {}; 367 Object.defineProperty(obj, "foo", {value: async function bar() {}, enumerable: true}); 368 obj.foo.toSource = () => "hello"; 369 assertEq(obj.toSource(), 370 "({foo:hello})"); 371 372 if (typeof reportCompare === "function") 373 reportCompare(true, true);