tor-browser

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

serialize_child.html (7763B)


      1 <!doctype html>
      2 <script src="/resources/channel.sub.js"></script>
      3 <script src="serialize-data.js"></script>
      4 <script>
      5 
      6 let lastData;
      7 
      8 // Hack: these will be converted into testharness AssertionError instances in the test
      9 // This means they will be treated identically to asserts raised by `assert_` in the harness
     10 // In the long term we want to be able to use parts of testharness.js directly in remote
     11 // contexts and automatically send the results over a channel.
     12 function AssertionError(message) {
     13    this.message = message;
     14 }
     15 AssertionError.prototype = Object.create(Error.prototype);
     16 
     17 function compareResult(name, actual) {
     18    let obj = objects[name];
     19    // If there's an output property use that, otherwise assume the output is equal to the input
     20    let expected = obj.hasOwnProperty("output") ? obj.output : obj.input;
     21    seen = new Set();
     22    try {
     23        compareValue(actual, expected, seen);
     24    } catch(e) {
     25        throw new AssertionError(e.message);
     26    }
     27    return true;
     28 }
     29 
     30 function compareValue(actualValue, expectedValue, seen) {
     31    let seenActual;
     32    if (typeof actualValue != typeof expectedValue) {
     33        throw new Error(`Types differ, expected ${typeof expectedValue}, got ${typeof actualValue}`);
     34    }
     35    if (["undefined", "string", "boolean", "number", "bigint"].includes(typeof expectedValue) ||
     36        actualValue === null) {
     37        if (!Object.is(actualValue, expectedValue)) {
     38            throw new Error(`Expected ${typeof expected} ${expected}, got ${actual}`);
     39        }
     40        return;
     41    }
     42 
     43    if (expectedValue.constructor && actualValue.constructor && expectedValue.constructor.name !== actualValue.constructor.name) {
     44        throw new Error(`Constructors differ, expected ${expectedValue.constructor.name}, got ${actualValue.constructor.name}`);
     45    }
     46    if (expectedValue.constructor && expectedValue.constructor.name === "SendChannel") {
     47        if (expectedValue.uuid !== actualValue.uuid) {
     48            throw new Error(`SendChannels differ, expected uuid ${expectedValue.uuid}, got ${actualValue.uuid}`);
     49        }
     50    }
     51    else if (expectedValue.constructor && expectedValue.constructor.name === "RegExp") {
     52        if (expectedValue.source !== actualValue.source ||
     53            expectedValue.flags !== actualValue.flags) {
     54            throw new Error(`RegExps differ, expected ${expectedValue}, got ${actualValue}`);
     55        }
     56    } else if (expectedValue.constructor && expectedValue.constructor.name == "Date") {
     57        if (expectedValue.valueOf() !== actualValue.valueOf()) {
     58            throw new Error(`Dates differ, expected ${expectedValue.valueOf()} (${expectedValue.toDateString()}), `
     59                            `got ${actualValue.valueOf()} (${actualValue.toDateString()})`);
     60        }
     61    } else if (expectedValue instanceof Error) {
     62        if (expectedValue.message !== actualValue.message ||
     63            expectedValue.lineNumber !== actualValue.lineNumber ||
     64            expectedValue.columnNumber !== actualValue.columnNumber ||
     65            expectedValue.fileName !== actualValue.fileName) {
     66            throw new Error(`Errors differ, expected ${expectedValue}, got ${actualValue}`);
     67        }
     68    } else if (Array.isArray(expectedValue)) {
     69        seenActual = seen.has(actualValue);
     70        seenExpected = seen.has(expectedValue)
     71        if (seenActual && seenExpected) {
     72            return;
     73        } else if (seenExpected && !seenActual) {
     74            throw new Error(`Expected cyclic array`);
     75        } else if (!seenExpected && seenActual) {
     76            throw new Error(`Got unexpected cyclic array`);
     77        }
     78        seen.add(actualValue);
     79        seen.add(expectedValue);
     80 
     81        if (actualValue.length !== expectedValue.length) {
     82            throw new Error(`Array lengths differ, expected ${expectedValue.length}, got ${actualValue.length}`);
     83        }
     84        for (let i=0; i<actualValue.length; i++) {
     85            compareValue(actualValue[i], expectedValue[i], seen);
     86        }
     87    } else if (expectedValue.constructor && expectedValue.constructor.name === "Set") {
     88        seenActual = seen.has(actualValue);
     89        seenExpected = seen.has(expectedValue)
     90        if (seenActual && seenExpected) {
     91            return;
     92        } else if (seenExpected && !seenActual) {
     93            throw new Error(`Expected cyclic set`);
     94        } else if (!seenExpected && seenActual) {
     95            throw new Error(`Got unexpected cyclic set`);
     96        }
     97        seen.add(actualValue);
     98        seen.add(expectedValue);
     99 
    100 
    101        if (actualValue.size !== expectedValue.size) {
    102            throw new Error(`Set sizes differ, expected ${expectedValue.size}, got ${actualValue.size}`);
    103        }
    104        // For an arbitary set it's complex to check if two sets are equivalent, since
    105        // we'd need to compare every object in one set with every object in the
    106        // other set, so we end up with quadratic complexity. Instead, just support sets
    107        // containing primitives and rely on the other tests for correct handling of
    108        // objects.
    109        for (let entry of expectedValue) {
    110            if (["undefined", "string", "boolean", "number", "bigint"].includes(typeof entry) || entry === null) {
    111                if(!actualValue.has(entry)) {
    112                    throw new Error(`Set missing entry, expected ${entry}`);
    113                }
    114            } else {
    115                throw new Error(`Can't compare non-primitive value ${entry} inside sets`);
    116            }
    117        }
    118    } else if (expectedValue.constructor && expectedValue.constructor.name === "Map") {
    119        seenActual = seen.has(actualValue);
    120        seenExpected = seen.has(expectedValue)
    121        if (seenActual && seenExpected) {
    122            return;
    123        } else if (seenExpected && !seenActual) {
    124            throw new Error(`Expected cyclic map`);
    125        } else if (!seenExpected && seenActual) {
    126            throw new Error(`Got unexpected cyclic map`);
    127        }
    128        seen.add(actualValue);
    129        seen.add(expectedValue);
    130 
    131        if (actualValue.size !== expectedValue.size) {
    132            throw new Error(`Map sizes differ, expected ${expectedValue.size}, got ${actualValue.size}`);
    133        }
    134        // So for a set we can't really check if the values are the same
    135        // except where they're primitives
    136        for (let [key, value] of expectedValue.entries()) {
    137            if(!actualValue.has(key)) {
    138                throw new Error(`Map missing key, expected key ${key} with value ${value}`);
    139            }
    140            compareValue(actualValue.get(key), value, seen);
    141        }
    142    } else {
    143        seenActual = seen.has(actualValue);
    144        seenExpected = seen.has(expectedValue)
    145        if (seenActual && seenExpected) {
    146            return;
    147        } else if (seenExpected && !seenActual) {
    148            throw new Error(`Expected cyclic object`);
    149        } else if (!seenExpected && seenActual) {
    150            throw new Error(`Got unexpected cyclic object`);
    151        }
    152        seen.add(actualValue);
    153        seen.add(expectedValue);
    154 
    155 
    156        // Compare as a general Object
    157        let expectedEntries = Object.entries(expectedValue);
    158        if (Object.keys(actualValue).length !== expectedEntries.length) {
    159            throw new Error(`Object keys differ, expected [${Object.keys(expectedValue).join(",")}], got [${Object.keys(actualValue).join(",")}]`);
    160        }
    161        // So for a set we can't really check if the values are the same
    162        // except where they're primitives
    163        for (let [name, entry] of expectedEntries) {
    164            if(!actualValue.hasOwnProperty(name)) {
    165                throw new Error(`Object missing key ${name}`);
    166            }
    167            compareValue(actualValue[name], entry, seen);
    168        }
    169    }
    170 }
    171 
    172 ctx = start_global_channel();
    173 </script>