tor-browser

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

errors.js (4263B)


      1 /*
      2 * Any copyright is dedicated to the Public Domain.
      3 * http://creativecommons.org/licenses/publicdomain/
      4 */
      5 
      6 load(libdir + "asserts.js");
      7 
      8 function roundtrip(error) {
      9  return deserialize(serialize(error, []));
     10 }
     11 
     12 // Basic
     13 {
     14  let error = new Error("hello world");
     15  let cloned = roundtrip(error);
     16 
     17  assertDeepEq(cloned, error);
     18  assertEq(cloned.name, "Error");
     19  assertEq(cloned.message, "hello world");
     20  assertEq(cloned.stack, error.stack);
     21 }
     22 
     23 let constructors = [Error, EvalError, RangeError, ReferenceError,
     24                    SyntaxError, TypeError, URIError];
     25 for (let constructor of constructors) {
     26  // With message
     27  let error = new constructor("hello");
     28  let cloned = roundtrip(error);
     29  assertDeepEq(cloned, error);
     30  assertEq(cloned.hasOwnProperty('message'), true);
     31  assertEq(cloned instanceof constructor, true);
     32 
     33  // Without message
     34  error = new constructor();
     35  cloned = roundtrip(error);
     36  assertDeepEq(cloned, error);
     37  assertEq(cloned.hasOwnProperty('message'), false);
     38  assertEq(cloned instanceof constructor, true);
     39 
     40  // Custom name
     41  error = new constructor("hello");
     42  error.name = "MyError";
     43  cloned = roundtrip(error);
     44  assertEq(cloned.name, "Error");
     45  assertEq(cloned.message, "hello");
     46  assertEq(cloned.stack, error.stack);
     47  if (constructor !== Error) {
     48    assertEq(cloned instanceof constructor, false);
     49  }
     50 
     51  // |cause| property
     52  error = new constructor("hello", { cause: new Error("foobar") });
     53  cloned = roundtrip(error);
     54  assertDeepEq(cloned, error);
     55  assertEq(cloned.hasOwnProperty('message'), true);
     56  assertEq(cloned instanceof constructor, true);
     57  assertEq(cloned.stack, error.stack);
     58  assertEq(cloned.stack === undefined, false);
     59 
     60  // |cause| property, manually added after construction.
     61  error = new constructor("hello");
     62  error.cause = new Error("foobar");
     63  assertDeepEq(Object.getOwnPropertyDescriptor(error, "cause"), {
     64    value: error.cause,
     65    writable: true,
     66    enumerable: true,
     67    configurable: true,
     68  });
     69  cloned = roundtrip(error);
     70  assertDeepEq(Object.getOwnPropertyDescriptor(cloned, "cause"), {
     71    value: cloned.cause,
     72    writable: true,
     73    enumerable: false,  // Non-enumerable in the cloned object!
     74    configurable: true,
     75  });
     76  assertEq(cloned.hasOwnProperty('message'), true);
     77  assertEq(cloned instanceof constructor, true);
     78  assertEq(cloned.stack, error.stack);
     79  assertEq(cloned.stack === undefined, false);
     80 
     81  // Subclassing
     82  error = new (class MyError extends constructor {});
     83  cloned = roundtrip(error);
     84  assertEq(cloned.name, constructor.name);
     85  assertEq(cloned.hasOwnProperty('message'), false);
     86  assertEq(cloned.stack, error.stack);
     87  assertEq(cloned instanceof Error, true);
     88 
     89  // Cross-compartment
     90  error = evalcx(`new ${constructor.name}("hello")`);
     91  cloned = roundtrip(error);
     92  assertEq(cloned.name, constructor.name);
     93  assertEq(cloned.message, "hello");
     94  assertEq(cloned.stack, error.stack);
     95  assertEq(cloned instanceof constructor, true);
     96 }
     97 
     98 // Non-string message
     99 {
    100  let error = new Error("hello world");
    101  error.message = 123;
    102  let cloned = roundtrip(error);
    103  assertEq(cloned.message, "123");
    104  assertEq(cloned.hasOwnProperty('message'), true);
    105 
    106  error = new Error();
    107  Object.defineProperty(error, 'message', { get: () => {} });
    108  cloned = roundtrip(error);
    109  assertEq(cloned.message, "");
    110  assertEq(cloned.hasOwnProperty('message'), false);
    111 }
    112 
    113 // AggregateError
    114 {
    115  // With message
    116  let error = new AggregateError([{a: 1}, {b: 2}], "hello");
    117  let cloned = roundtrip(error);
    118  assertDeepEq(cloned, error);
    119  assertEq(cloned.hasOwnProperty('message'), true);
    120  assertEq(cloned instanceof AggregateError, true);
    121 
    122  // Without message
    123  error = new AggregateError([{a: 1}, {b: 2}]);
    124  cloned = roundtrip(error);
    125  assertDeepEq(cloned, error);
    126  assertEq(cloned.hasOwnProperty('message'), false);
    127  assertEq(cloned instanceof AggregateError, true);
    128 
    129  // Custom name breaks this!
    130  error = new AggregateError([{a: 1}, {b: 2}]);
    131  error.name = "MyError";
    132  cloned = roundtrip(error);
    133  assertEq(cloned.name, "Error");
    134  assertEq(cloned.message, "");
    135  assertEq(cloned.stack, error.stack);
    136  assertEq(cloned instanceof AggregateError, false);
    137  assertEq(cloned.errors, undefined);
    138  assertEq(cloned.hasOwnProperty('errors'), false);
    139 }