tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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);