tor-browser

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

Environment-variables.js (3035B)


      1 // Comprehensive test of get/setVariable on many kinds of environments and
      2 // bindings.
      3 
      4 load(libdir + "asserts.js");
      5 
      6 var cases = [
      7    // global bindings and bindings on the global prototype chain
      8    "x = VAL; @@",
      9    "var x = VAL; @@",
     10    "Object.prototype.x = VAL; @@",
     11 
     12    // let and catch bindings
     13    "let x = VAL; @@",
     14    "{ let x = VAL; @@ }",
     15    "try { throw VAL; } catch (x) { @@ }",
     16    "try { throw VAL; } catch (x) { @@ }",
     17    "for (let x of [VAL]) { @@ }",
     18    "switch (0) { default: let x = VAL; @@ }",
     19 
     20    // arguments
     21    "function f(x) { @@ } f(VAL);",
     22    "function f([w, x]) { @@ } f([0, VAL]);",
     23    "function f({v: x}) { @@ } f({v: VAL});",
     24    "function f([w, {v: x}]) { @@ } f([0, {v: VAL}]);",
     25 
     26    // bindings in functions
     27    "function f() { var x = VAL; @@ } f();",
     28    "function f() { let x = VAL; @@ } f();",
     29    "function f() { function x() {} x = VAL; @@ } f();",
     30 
     31    // dynamic bindings
     32    "function f(s) { eval(s); @@ } f('var x = VAL');",
     33    "var x = VAL; function f(s) { eval('var x = 0;'); eval(s); @@ } f('delete x;');",
     34    "function f(obj) { with (obj) { @@ } } f({x: VAL});",
     35    "function f(obj) { with (obj) { @@ } } f(Object.create({x: VAL}));",
     36    "function f(b) { if (b) { function x(){} } x = VAL; @@ } f(1);",
     37 ];
     38 
     39 var nextval = 1000;
     40 
     41 function test(code, debugStmts, followupStmts) {
     42    var val = nextval++;
     43    var hits = 0;
     44 
     45    var g = newGlobal({newCompartment: true});
     46    g.eval("function debugMe() { var x = 'wrong-x'; eval(\"\"); debugger; }");
     47    g.capture = null;
     48 
     49    var dbg = Debugger(g);
     50    dbg.onDebuggerStatement = function (frame) {
     51        if (frame.callee !== null && frame.callee.name == 'debugMe')
     52            frame = frame.older;
     53        var env = frame.environment.find("x");
     54        assertEq(env.getVariable("x"), val)
     55        assertEq(env.setVariable("x", 'ok'), undefined);
     56        assertEq(env.getVariable("x"), 'ok');
     57 
     58        // setVariable cannot create new variables.
     59        assertThrowsInstanceOf(function () { env.setVariable("newVar", 0); }, TypeError);
     60        hits++;
     61    };
     62 
     63    code = code.replace("@@", debugStmts);
     64    if (followupStmts !== undefined)
     65        code += " " + followupStmts;
     66    code = code.replace(/VAL/g, String(val));
     67    g.eval(code);
     68    assertEq(hits, 1);
     69 }
     70 
     71 for (var s of cases) {
     72    // Test triggering the debugger right in the scope in which x is bound.
     73    test(s, "eval(\"\"); debugger; assertEq(x, 'ok');");
     74 
     75    // Test calling a function that triggers the debugger.
     76    test(s, "debugMe(); assertEq(x, 'ok');");
     77 
     78    // Test triggering the debugger from a scope nested in x's scope.
     79    test(s, "{ let y = 'irrelevant'; (function (z) { { let zz = y; eval(\"\"); debugger; } })(); } assertEq(x, 'ok');"),
     80 
     81    // Test closing over the variable and triggering the debugger later, after
     82    // leaving the variable's scope.
     83    test(s, "capture = {dbg: function () { eval(\"\"); debugger; }, get x() { return x; }};",
     84            "assertEq(capture.x, VAL); capture.dbg(); assertEq(capture.x, 'ok');");
     85 }