ExecutionTracer-traced-values.js (18920B)
1 if (typeof enableExecutionTracing == "undefined") { 2 quit(); 3 } 4 const VALUE_SUMMARY_VERSION = 2; 5 6 const JSVAL_TYPE_DOUBLE = 0x00; 7 const JSVAL_TYPE_INT32 = 0x01; 8 const JSVAL_TYPE_BOOLEAN = 0x02; 9 const JSVAL_TYPE_UNDEFINED = 0x03; 10 const JSVAL_TYPE_NULL = 0x04; 11 const JSVAL_TYPE_MAGIC = 0x05; 12 const JSVAL_TYPE_STRING = 0x06; 13 const JSVAL_TYPE_SYMBOL = 0x07; 14 const JSVAL_TYPE_BIGINT = 0x09; 15 const JSVAL_TYPE_OBJECT = 0x0c; 16 17 const GETTER_SETTER_MAGIC = 0x0f; 18 19 const GENERIC_OBJECT_HAS_DENSE_ELEMENTS = 1; 20 21 const NUMBER_IS_OUT_OF_LINE_MAGIC = 0xf; 22 const MIN_INLINE_INT = -1; 23 const MAX_INLINE_INT = 13; 24 25 const STRING_ENCODING_LATIN1 = 0; 26 27 const OBJECT_KIND_ARRAY_LIKE = 1; 28 const OBJECT_KIND_MAP_LIKE = 2; 29 const OBJECT_KIND_FUNCTION = 3; 30 const OBJECT_KIND_WRAPPED_PRIMITIVE_OBJECT = 4; 31 const OBJECT_KIND_GENERIC_OBJECT = 5; 32 const OBJECT_KIND_PROXY_OBJECT = 6; 33 34 const MAX_COLLECTION_VALUES = 16; 35 36 class BufferReader { 37 #view; 38 #index; 39 40 constructor(buffer, index = 0) { 41 this.#view = new DataView(buffer); 42 this.#index = index; 43 } 44 45 peekUint8() { 46 return this.#view.getUint8(this.#index); 47 } 48 49 readUint8() { 50 let result = this.#view.getUint8(this.#index); 51 this.#index += 1; 52 return result; 53 } 54 55 readUint16() { 56 let result = this.#view.getUint16(this.#index, true); 57 this.#index += 2; 58 return result; 59 } 60 61 readUint32() { 62 let result = this.#view.getUint32(this.#index, true); 63 this.#index += 4; 64 return result; 65 } 66 67 readInt8() { 68 let result = this.#view.getInt8(this.#index); 69 this.#index += 1; 70 return result; 71 } 72 73 readInt16() { 74 let result = this.#view.getInt16(this.#index, true); 75 this.#index += 2; 76 return result; 77 } 78 79 readInt32() { 80 let result = this.#view.getInt32(this.#index, true); 81 this.#index += 4; 82 return result; 83 } 84 85 readFloat64() { 86 let result = this.#view.getFloat64(this.#index, true); 87 this.#index += 8; 88 return result; 89 } 90 91 readString() { 92 let encodingAndLength = this.readUint16(); 93 let length = encodingAndLength & ~(0b11 << 14); 94 let encoding = encodingAndLength >> 14; 95 if (length == 0) { 96 return ""; 97 } 98 99 // This assertion is just for simplicity in testing. Other values can occur 100 // in the wild 101 assertEq(encoding, STRING_ENCODING_LATIN1); 102 let result = String.fromCharCode(...new Uint8Array(this.#view.buffer.slice(this.#index, this.#index + length))); 103 104 this.#index += length; 105 return result; 106 } 107 } 108 109 var g = newGlobal({ newCompartment: true }); 110 var h = newGlobal({ newCompartment: true }); 111 g.ccw = h; 112 h.wrappedObject = {foo: 0}; 113 var dbg = new Debugger(); 114 dbg.addDebuggee(g); 115 116 g.enableExecutionTracing(); 117 118 g.eval(` 119 var wrappedNumber = new Number(0); 120 wrappedNumber.foo = 0; 121 122 [ 123 0.1, 124 0, 125 -2, 126 -1, 127 13, 128 14, 129 42, 130 false, 131 true, 132 "bar", 133 999999999999999999999999n, 134 new Proxy({}, {}), 135 [0], 136 new Set([0]), 137 new Map([[1, 0]]), 138 {foo: 42}, 139 function foo(a,b) {}, 140 {"1": 0}, 141 new String("foo"), 142 new Boolean(false), 143 new Number(0), 144 wrappedNumber, 145 [{foo: {}}], 146 new Set([{foo: {}}]), 147 new Map([[{foo: {}}, {bar: {}}]]), 148 ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t"], 149 {a:0,b:0,c:0,d:0,e:0,f:0,g:0,h:0,i:0,j:0,k:0,l:0,m:0,n:0,o:0,p:0,q:0,r:0,s:0,t:0}, 150 -0.0, 151 null, 152 undefined, 153 Symbol.for("foo"), 154 [,0], 155 {[42000]: 0, [Symbol.for("foo")]: 0}, 156 {shapeTest: 0}, 157 {shapeTest: 42}, 158 function foobar(a, {x}, bar = 42) {}, 159 function foobaz(a, a) {}, 160 function barbaz(a, ...rest) {}, 161 ccw.wrappedObject, 162 {get testGetter() {return 42}}, 163 ].map(function f1(x) { return x; });`); 164 165 const trace = g.getExecutionTrace(); 166 167 g.disableExecutionTracing(); 168 169 assertEq(trace.length, 1); 170 171 let versionReader = new BufferReader(trace[0].valueBuffer, 0); 172 assertEq(versionReader.readUint32(), VALUE_SUMMARY_VERSION); 173 174 function testSingleArgument(event, cb) { 175 assertEq(typeof event.values, "number"); 176 assertEq(event.values < trace[0].valueBuffer.byteLength, true); 177 178 let reader = new BufferReader(trace[0].valueBuffer, event.values); 179 180 // Array.prototype.map's callback is called with 3 args: element, index, array 181 assertEq(reader.readUint32(), 3); 182 183 cb(reader); 184 185 // Double check that we see the `index` argument afterwards 186 assertEq(reader.readUint8() & 0xf, JSVAL_TYPE_INT32); 187 } 188 189 function inlinedInt32Flags(val) { 190 return (val - MIN_INLINE_INT) << 4; 191 } 192 193 const events = trace[0].events.filter(e => e.kind == "FunctionEnter"); 194 195 testSingleArgument(events.shift(), reader => { 196 assertEq(reader.readUint8(), JSVAL_TYPE_DOUBLE | NUMBER_IS_OUT_OF_LINE_MAGIC << 4); 197 assertEq(reader.readFloat64(), 0.1); 198 }); 199 200 testSingleArgument(events.shift(), reader => { 201 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 202 }); 203 204 testSingleArgument(events.shift(), reader => { 205 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | NUMBER_IS_OUT_OF_LINE_MAGIC << 4); 206 assertEq(reader.readInt32(), -2); 207 }); 208 209 testSingleArgument(events.shift(), reader => { 210 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(-1)); 211 }); 212 213 testSingleArgument(events.shift(), reader => { 214 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(13)); 215 }); 216 217 testSingleArgument(events.shift(), reader => { 218 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | NUMBER_IS_OUT_OF_LINE_MAGIC << 4); 219 assertEq(reader.readInt32(), 14); 220 }); 221 222 testSingleArgument(events.shift(), reader => { 223 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | NUMBER_IS_OUT_OF_LINE_MAGIC << 4); 224 assertEq(reader.readInt32(), 42); 225 }); 226 227 testSingleArgument(events.shift(), reader => { 228 assertEq(reader.readUint8(), JSVAL_TYPE_BOOLEAN); 229 }); 230 231 testSingleArgument(events.shift(), reader => { 232 assertEq(reader.readUint8(), JSVAL_TYPE_BOOLEAN | 1 << 4); 233 }); 234 235 testSingleArgument(events.shift(), reader => { 236 assertEq(reader.readUint8(), JSVAL_TYPE_STRING); 237 assertEq(reader.readString(), "bar"); 238 }); 239 240 testSingleArgument(events.shift(), reader => { 241 assertEq(reader.readUint8(), JSVAL_TYPE_BIGINT); 242 assertEq(reader.readString(), "999999999999999999999999"); 243 }); 244 245 testSingleArgument(events.shift(), reader => { 246 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 247 assertEq(reader.readUint8(), OBJECT_KIND_PROXY_OBJECT); 248 249 let shape = trace[0].shapeSummaries[reader.readUint32()]; 250 assertEq(shape.length, 1); 251 assertEq(shape[0], "Proxy"); 252 }); 253 254 testSingleArgument(events.shift(), reader => { 255 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 256 assertEq(reader.readUint8(), OBJECT_KIND_ARRAY_LIKE); 257 258 let shape = trace[0].shapeSummaries[reader.readUint32()]; 259 assertEq(shape.length, 1); 260 assertEq(shape[0], "Array"); 261 262 assertEq(reader.readUint32(), 1); // length == 1 263 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 264 }); 265 266 testSingleArgument(events.shift(), reader => { 267 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 268 assertEq(reader.readUint8(), OBJECT_KIND_ARRAY_LIKE); 269 270 let shape = trace[0].shapeSummaries[reader.readUint32()]; 271 assertEq(shape.length, 1); 272 assertEq(shape[0], "Set"); 273 274 assertEq(reader.readUint32(), 1); // size == 1 275 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 276 }); 277 278 testSingleArgument(events.shift(), reader => { 279 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 280 assertEq(reader.readUint8(), OBJECT_KIND_MAP_LIKE); 281 282 let shape = trace[0].shapeSummaries[reader.readUint32()]; 283 assertEq(shape.length, 1); 284 assertEq(shape[0], "Map"); 285 286 assertEq(reader.readUint32(), 1); // size == 1 287 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(1)); 288 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 289 }); 290 291 testSingleArgument(events.shift(), reader => { 292 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 293 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 294 295 let shape = trace[0].shapeSummaries[reader.readUint32()]; 296 assertEq(shape.length, 2); 297 assertEq(shape[0], "Object"); 298 assertEq(shape[1], "foo"); 299 300 assertEq(reader.readUint32(), 1); 301 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | NUMBER_IS_OUT_OF_LINE_MAGIC << 4); 302 assertEq(reader.readInt32(), 42); 303 }); 304 305 testSingleArgument(events.shift(), reader => { 306 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 307 assertEq(reader.readUint8(), OBJECT_KIND_FUNCTION); 308 309 assertEq(reader.readString(), "foo"); 310 assertEq(reader.readUint32(), 2); 311 assertEq(reader.readString(), "a"); 312 assertEq(reader.readString(), "b"); 313 }); 314 315 testSingleArgument(events.shift(), reader => { 316 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT | (GENERIC_OBJECT_HAS_DENSE_ELEMENTS << 4)); 317 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 318 319 let shape = trace[0].shapeSummaries[reader.readUint32()]; 320 assertEq(shape.length, 1); 321 assertEq(shape[0], "Object"); 322 323 // 0 properties 324 assertEq(reader.readUint32(), 0); 325 326 // 2 dense elements (element 0 is a hole) 327 assertEq(reader.readUint32(), 2); 328 assertEq(reader.readUint8(), JSVAL_TYPE_MAGIC); 329 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 330 }); 331 332 testSingleArgument(events.shift(), reader => { 333 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 334 assertEq(reader.readUint8(), OBJECT_KIND_WRAPPED_PRIMITIVE_OBJECT); 335 336 assertEq(reader.readUint8(), JSVAL_TYPE_STRING); 337 assertEq(reader.readString(), "foo"); 338 339 let shape = trace[0].shapeSummaries[reader.readUint32()]; 340 assertEq(shape.length, 2); 341 assertEq(shape[0], "String"); 342 assertEq(shape[1], "length"); 343 344 // 1 properties 345 assertEq(reader.readUint32(), 1); 346 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(3)); 347 }); 348 349 testSingleArgument(events.shift(), reader => { 350 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 351 assertEq(reader.readUint8(), OBJECT_KIND_WRAPPED_PRIMITIVE_OBJECT); 352 353 assertEq(reader.readUint8(), JSVAL_TYPE_BOOLEAN); 354 355 let shape = trace[0].shapeSummaries[reader.readUint32()]; 356 assertEq(shape.length, 1); 357 assertEq(shape[0], "Boolean"); 358 359 // 0 properties 360 assertEq(reader.readUint32(), 0); 361 }); 362 363 testSingleArgument(events.shift(), reader => { 364 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 365 assertEq(reader.readUint8(), OBJECT_KIND_WRAPPED_PRIMITIVE_OBJECT); 366 367 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 368 369 let shape = trace[0].shapeSummaries[reader.readUint32()]; 370 assertEq(shape.length, 1); 371 assertEq(shape[0], "Number"); 372 373 // 0 properties 374 assertEq(reader.readUint32(), 0); 375 }); 376 377 testSingleArgument(events.shift(), reader => { 378 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 379 assertEq(reader.readUint8(), OBJECT_KIND_WRAPPED_PRIMITIVE_OBJECT); 380 381 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 382 383 let shape = trace[0].shapeSummaries[reader.readUint32()]; 384 assertEq(shape.length, 2); 385 assertEq(shape[0], "Number"); 386 assertEq(shape[1], "foo"); 387 388 // 1 property 389 assertEq(reader.readUint32(), 1); 390 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 391 }); 392 393 testSingleArgument(events.shift(), reader => { 394 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 395 assertEq(reader.readUint8(), OBJECT_KIND_ARRAY_LIKE); 396 397 let shape = trace[0].shapeSummaries[reader.readUint32()]; 398 assertEq(shape[0], "Array"); 399 400 assertEq(reader.readUint32(), 1); // length == 1 401 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 402 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 403 404 let nestedShape = trace[0].shapeSummaries[reader.readUint32()]; 405 assertEq(nestedShape.length, 2); 406 assertEq(nestedShape[0], "Object"); 407 assertEq(nestedShape[1], "foo"); 408 409 // We should have one property, but nothing after that 410 assertEq(reader.readUint32(), 1); 411 }); 412 413 testSingleArgument(events.shift(), reader => { 414 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 415 assertEq(reader.readUint8(), OBJECT_KIND_ARRAY_LIKE); 416 417 let shape = trace[0].shapeSummaries[reader.readUint32()]; 418 assertEq(shape[0], "Set"); 419 420 assertEq(reader.readUint32(), 1); // length == 1 421 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 422 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 423 424 let nestedShape = trace[0].shapeSummaries[reader.readUint32()]; 425 assertEq(nestedShape.length, 2); 426 assertEq(nestedShape[0], "Object"); 427 assertEq(nestedShape[1], "foo"); 428 429 // We should have one property, but nothing after that 430 assertEq(reader.readUint32(), 1); 431 }); 432 433 testSingleArgument(events.shift(), reader => { 434 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 435 assertEq(reader.readUint8(), OBJECT_KIND_MAP_LIKE); 436 437 let shape = trace[0].shapeSummaries[reader.readUint32()]; 438 assertEq(shape[0], "Map"); 439 440 assertEq(reader.readUint32(), 1); // length == 1 441 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 442 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 443 444 let nestedShape = trace[0].shapeSummaries[reader.readUint32()]; 445 assertEq(nestedShape.length, 2); 446 assertEq(nestedShape[0], "Object"); 447 assertEq(nestedShape[1], "foo"); 448 assertEq(reader.readUint32(), 1); 449 450 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 451 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 452 453 nestedShape = trace[0].shapeSummaries[reader.readUint32()]; 454 assertEq(nestedShape.length, 2); 455 assertEq(nestedShape[0], "Object"); 456 assertEq(nestedShape[1], "bar"); 457 assertEq(reader.readUint32(), 1); 458 }); 459 460 testSingleArgument(events.shift(), reader => { 461 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 462 assertEq(reader.readUint8(), OBJECT_KIND_ARRAY_LIKE); 463 464 let shape = trace[0].shapeSummaries[reader.readUint32()]; 465 assertEq(shape.length, 1); 466 assertEq(shape[0], "Array"); 467 468 assertEq(reader.readUint32(), 20); // length == 20 469 for (let i = 0; i < MAX_COLLECTION_VALUES; i++) { 470 assertEq(reader.readUint8(), JSVAL_TYPE_STRING); 471 assertEq(reader.readString(), String.fromCharCode("a".charCodeAt(0) + i)); 472 } 473 }); 474 475 testSingleArgument(events.shift(), reader => { 476 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 477 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 478 479 let shape = trace[0].shapeSummaries[reader.readUint32()]; 480 assertEq(shape.length, 17); 481 assertEq(shape[0], "Object"); 482 assertEq(shape.numProperties, 20); 483 484 assertEq(reader.readUint32(), 20); 485 for (let i = 0; i < MAX_COLLECTION_VALUES; i++) { 486 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 487 } 488 }); 489 490 testSingleArgument(events.shift(), reader => { 491 assertEq(reader.readUint8(), JSVAL_TYPE_DOUBLE | NUMBER_IS_OUT_OF_LINE_MAGIC << 4); 492 assertEq(reader.readFloat64(), -0.0); 493 }); 494 495 testSingleArgument(events.shift(), reader => { 496 assertEq(reader.readUint8(), JSVAL_TYPE_NULL); 497 }); 498 499 testSingleArgument(events.shift(), reader => { 500 assertEq(reader.readUint8(), JSVAL_TYPE_UNDEFINED); 501 }); 502 503 testSingleArgument(events.shift(), reader => { 504 assertEq(reader.readUint8(), JSVAL_TYPE_SYMBOL); 505 assertEq(reader.readString(), "foo"); 506 }); 507 508 testSingleArgument(events.shift(), reader => { 509 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 510 assertEq(reader.readUint8(), OBJECT_KIND_ARRAY_LIKE); 511 512 let shape = trace[0].shapeSummaries[reader.readUint32()]; 513 assertEq(shape.length, 1); 514 assertEq(shape[0], "Array"); 515 516 assertEq(reader.readUint32(), 2); // length == 2 517 assertEq(reader.readUint8(), JSVAL_TYPE_MAGIC); 518 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 519 }); 520 521 testSingleArgument(events.shift(), reader => { 522 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 523 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 524 525 let shape = trace[0].shapeSummaries[reader.readUint32()]; 526 assertEq(shape.length, 3); 527 assertEq(shape[0], "Object"); 528 assertEq(shape[1], "Symbol(foo)"); 529 assertEq(shape[2], "42000"); 530 531 assertEq(reader.readUint32(), 2); // length == 2 532 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 533 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 534 }); 535 536 let shapeTestId = -1; 537 testSingleArgument(events.shift(), reader => { 538 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 539 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 540 541 let shape = trace[0].shapeSummaries[reader.readUint32()]; 542 assertEq(shape.length, 2); 543 assertEq(shape[0], "Object"); 544 assertEq(shape[1], "shapeTest"); 545 546 // We're going to check in the next test that this ID is shared between 547 // same-shaped objects. 548 shapeTestId = shape; 549 550 assertEq(reader.readUint32(), 1); // length == 1 551 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 552 }); 553 554 testSingleArgument(events.shift(), reader => { 555 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 556 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 557 558 let shape = trace[0].shapeSummaries[reader.readUint32()]; 559 assertEq(shape.length, 2); 560 assertEq(shape[0], "Object"); 561 assertEq(shape[1], "shapeTest"); 562 563 assertEq(shape, shapeTestId); 564 565 assertEq(reader.readUint32(), 1); // length == 1 566 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | NUMBER_IS_OUT_OF_LINE_MAGIC << 4); 567 assertEq(reader.readInt32(), 42); 568 }); 569 570 testSingleArgument(events.shift(), reader => { 571 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 572 assertEq(reader.readUint8(), OBJECT_KIND_FUNCTION); 573 574 assertEq(reader.readString(), "foobar"); 575 assertEq(reader.readUint32(), 3); 576 assertEq(reader.readString(), "a"); 577 assertEq(reader.readString(), ""); 578 assertEq(reader.readString(), "bar"); 579 }); 580 581 testSingleArgument(events.shift(), reader => { 582 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 583 assertEq(reader.readUint8(), OBJECT_KIND_FUNCTION); 584 585 assertEq(reader.readString(), "foobaz"); 586 assertEq(reader.readUint32(), 2); 587 assertEq(reader.readString(), "a"); 588 assertEq(reader.readString(), "a"); 589 }); 590 591 testSingleArgument(events.shift(), reader => { 592 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 593 assertEq(reader.readUint8(), OBJECT_KIND_FUNCTION); 594 595 assertEq(reader.readString(), "barbaz"); 596 assertEq(reader.readUint32(), 2); 597 assertEq(reader.readString(), "a"); 598 assertEq(reader.readString(), "rest"); 599 }); 600 601 testSingleArgument(events.shift(), reader => { 602 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 603 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 604 605 let shape = trace[0].shapeSummaries[reader.readUint32()]; 606 assertEq(shape.length, 2); 607 assertEq(shape[0], "Object"); 608 assertEq(shape[1], "foo"); 609 610 assertEq(reader.readUint32(), 1); 611 assertEq(reader.readUint8(), JSVAL_TYPE_INT32 | inlinedInt32Flags(0)); 612 }); 613 614 testSingleArgument(events.shift(), reader => { 615 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 616 assertEq(reader.readUint8(), OBJECT_KIND_GENERIC_OBJECT); 617 618 let shape = trace[0].shapeSummaries[reader.readUint32()]; 619 assertEq(shape.length, 2); 620 assertEq(shape[0], "Object"); 621 assertEq(shape[1], "testGetter"); 622 623 assertEq(reader.readUint32(), 1); 624 assertEq(reader.readUint8(), GETTER_SETTER_MAGIC); 625 assertEq(reader.readUint8(), JSVAL_TYPE_OBJECT); 626 assertEq(reader.readUint8(), OBJECT_KIND_FUNCTION); 627 assertEq(reader.readString(), "get testGetter"); 628 assertEq(reader.readUint32(), 0); 629 assertEq(reader.readUint8(), JSVAL_TYPE_UNDEFINED); 630 }); 631 632 assertEq(events.length, 0);