tor-browser

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

iterator-close.js (6613B)


      1 // |reftest| skip-if(!xulRuntime.shell) -- needs drainJobQueue
      2 
      3 var BUGNUMBER = 1180306;
      4 var summary = 'Promise.{all,race} should close iterator on error';
      5 
      6 print(BUGNUMBER + ": " + summary);
      7 
      8 function test(ctor, props, { nextVal=undefined,
      9                             nextThrowVal=undefined,
     10                             modifier=undefined,
     11                             rejectReason=undefined,
     12                             rejectType=undefined,
     13                             closed=true }) {
     14    function getIterable() {
     15        let iterable = {
     16            closed: false,
     17            [Symbol.iterator]() {
     18                let iterator = {
     19                    first: true,
     20                    next() {
     21                        if (this.first) {
     22                            this.first = false;
     23                            if (nextThrowVal)
     24                                throw nextThrowVal;
     25                            return nextVal;
     26                        }
     27                        return { value: undefined, done: true };
     28                    },
     29                    return() {
     30                        iterable.closed = true;
     31                        return {};
     32                    }
     33                };
     34                if (modifier)
     35                    modifier(iterator, iterable);
     36 
     37                return iterator;
     38            }
     39        };
     40        return iterable;
     41    }
     42    for (let prop of props) {
     43        let iterable = getIterable();
     44        let e;
     45        ctor[prop](iterable).catch(e_ => { e = e_; });
     46        drainJobQueue();
     47        if(rejectType)
     48            assertEq(e instanceof rejectType, true);
     49        else
     50            assertEq(e, rejectReason);
     51        assertEq(iterable.closed, closed);
     52    }
     53 }
     54 
     55 // == Error cases with close ==
     56 
     57 // ES 2017 draft 25.4.4.1.1 step 6.i.
     58 // ES 2017 draft 25.4.4.3.1 step 3.h.
     59 class MyPromiseStaticResolveGetterThrows extends Promise {
     60    static get resolve() {
     61        throw "static resolve getter throws";
     62    }
     63 };
     64 test(MyPromiseStaticResolveGetterThrows, ["all", "race"], {
     65    nextVal: { value: Promise.resolve(1), done: false },
     66    rejectReason: "static resolve getter throws",
     67    closed: false,
     68 });
     69 
     70 class MyPromiseStaticResolveThrows extends Promise {
     71    static resolve() {
     72        throw "static resolve throws";
     73    }
     74 };
     75 test(MyPromiseStaticResolveThrows, ["all", "race"], {
     76    nextVal: { value: Promise.resolve(1), done: false },
     77    rejectReason: "static resolve throws",
     78    closed: true,
     79 });
     80 
     81 // ES 2017 draft 25.4.4.1.1 step 6.q.
     82 // ES 2017 draft 25.4.4.3.1 step 3.i.
     83 class MyPromiseThenGetterThrows extends Promise {
     84    static resolve() {
     85        return {
     86            get then() {
     87                throw "then getter throws";
     88            }
     89        };
     90    }
     91 };
     92 test(MyPromiseThenGetterThrows, ["all", "race"], {
     93    nextVal: { value: Promise.resolve(1), done: false },
     94    rejectReason: "then getter throws",
     95    closed: true,
     96 });
     97 
     98 class MyPromiseThenThrows extends Promise {
     99    static resolve() {
    100        return {
    101            then() {
    102                throw "then throws";
    103            }
    104        };
    105    }
    106 };
    107 test(MyPromiseThenThrows, ["all", "race"], {
    108    nextVal: { value: Promise.resolve(1), done: false },
    109    rejectReason: "then throws",
    110    closed: true,
    111 });
    112 
    113 // ES 2017 draft 7.4.6 step 3.
    114 // if GetMethod fails, the thrown value should be used.
    115 test(MyPromiseThenThrows, ["all", "race"], {
    116    nextVal: { value: Promise.resolve(1), done: false },
    117    modifier: (iterator, iterable) => {
    118        Object.defineProperty(iterator, "return", {
    119            get: function() {
    120                iterable.closed = true;
    121                throw "return getter throws";
    122            }
    123        });
    124    },
    125    rejectReason: "then throws",
    126    closed: true,
    127 });
    128 test(MyPromiseThenThrows, ["all", "race"], {
    129    nextVal: { value: Promise.resolve(1), done: false },
    130    modifier: (iterator, iterable) => {
    131        Object.defineProperty(iterator, "return", {
    132            get: function() {
    133                iterable.closed = true;
    134                return "non object";
    135            }
    136        });
    137    },
    138    rejectReason: "then throws",
    139    closed: true,
    140 });
    141 test(MyPromiseThenThrows, ["all", "race"], {
    142    nextVal: { value: Promise.resolve(1), done: false },
    143    modifier: (iterator, iterable) => {
    144        Object.defineProperty(iterator, "return", {
    145            get: function() {
    146                iterable.closed = true;
    147                // Non callable.
    148                return {};
    149            }
    150        });
    151    },
    152    rejectReason: "then throws",
    153    closed: true,
    154 });
    155 
    156 // ES 2017 draft 7.4.6 steps 6.
    157 // if return method throws, the thrown value should be ignored.
    158 test(MyPromiseThenThrows, ["all", "race"], {
    159    nextVal: { value: Promise.resolve(1), done: false },
    160    modifier: (iterator, iterable) => {
    161        iterator.return = function() {
    162            iterable.closed = true;
    163            throw "return throws";
    164        };
    165    },
    166    rejectReason: "then throws",
    167    closed: true,
    168 });
    169 
    170 test(MyPromiseThenThrows, ["all", "race"], {
    171    nextVal: { value: Promise.resolve(1), done: false },
    172    modifier: (iterator, iterable) => {
    173        iterator.return = function() {
    174            iterable.closed = true;
    175            return "non object";
    176        };
    177    },
    178    rejectReason: "then throws",
    179    closed: true,
    180 });
    181 
    182 // == Error cases without close ==
    183 
    184 // ES 2017 draft 25.4.4.1.1 step 6.a.
    185 test(Promise, ["all", "race"], {
    186    nextThrowVal: "next throws",
    187    rejectReason: "next throws",
    188    closed: false,
    189 });
    190 
    191 test(Promise, ["all", "race"], {
    192    nextVal: { value: {}, get done() { throw "done getter throws"; } },
    193    rejectReason: "done getter throws",
    194    closed: false,
    195 });
    196 
    197 // ES 2017 draft 25.4.4.1.1 step 6.e.
    198 test(Promise, ["all", "race"], {
    199    nextVal: { get value() { throw "value getter throws"; }, done: false },
    200    rejectReason: "value getter throws",
    201    closed: false,
    202 });
    203 
    204 // ES 2017 draft 25.4.4.1.1 step 6.d.iii.2.
    205 let first = true;
    206 class MyPromiseResolveThrows extends Promise {
    207    constructor(executer) {
    208        if (first) {
    209            first = false;
    210            super((resolve, reject) => {
    211                executer(() => {
    212                    throw "resolve throws";
    213                }, reject);
    214            });
    215            return;
    216        }
    217        super(executer);
    218    }
    219 };
    220 test(MyPromiseResolveThrows, ["all"], {
    221    nextVal: { value: undefined, done: true },
    222    rejectReason: "resolve throws",
    223    closed: false,
    224 });
    225 
    226 // == Successful cases ==
    227 
    228 test(Promise, ["all", "race"], {
    229    nextVal: { value: Promise.resolve(1), done: false },
    230    closed: false,
    231 });
    232 
    233 if (typeof reportCompare === 'function')
    234  reportCompare(true, true);