tor-browser

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

Environment-identity-03.js (3720B)


      1 // |jit-test| skip-if: getBuildConfiguration("wasi")
      2 //
      3 // Two Environments nested in the same runtime scope share the correct tail of their parent chains.
      4 
      5 // The compiler must be allowed to elide empty scopes and so forth, so this
      6 // test does not check the number of unshared Environments. Instead, each test
      7 // case identifies the expected innermost shared scope by the name of a
      8 // variable in it.
      9 
     10 var g = newGlobal({newCompartment: true});
     11 g.eval("function h() { debugger; }");
     12 var dbg = Debugger(g);
     13 var hits, name, shared, unshared;
     14 dbg.onDebuggerStatement = function (hframe) {
     15    var frame = hframe.older;
     16 
     17    // Find name in frame.environment.
     18    var env, child = null;
     19    for (env = frame.environment; env !== null; env = env.parent) {
     20        if (env.names().indexOf(name) != -1)
     21            break;
     22        child = env;
     23    }
     24    assertEq(env !== null, true, "expected '" + name + "' to be in scope");
     25    assertEq(env, frame.environment.find(name),
     26             "env.find should find the same frame as the written out search");
     27 
     28    if (hits === 0) {
     29        // First hit.
     30        shared = env;
     31        unshared = child;
     32    } else {
     33        // Subsequent hit.
     34        assertEq(env, shared, "the environment containing '" + name + "' should be shared");
     35        assertEq(child === null || unshared === null || unshared !== child, true,
     36                "environments nested within the one containing '" + name + "' should not be shared");
     37    }
     38    hits++;
     39 };
     40 
     41 function test(sharedName, expectedHits, code) {
     42    hits = 0;
     43    name = sharedName;
     44    shared = unshared = undefined;
     45    g.eval(code);
     46    assertEq(hits, expectedHits);
     47 }
     48 
     49 // Basic test cases.
     50 //
     51 // (The stray "a = b" assignments in these tests are to inhibit the flat closure
     52 // optimization, which Environments expose. There's nothing really wrong with
     53 // the optimization or with the debugger exposing it, but that's not what we
     54 // want to test here.)
     55 
     56 test("q", 2, "let q = function (a) { h(); }; q(1); q(2);");
     57 test("a", 2, "q = function (a) { (function (b) { h(); a = b; })(2); h(); }; q(1);");
     58 test("a", 2, "q = function (a) { h(); return function (b) { h(); a = b; }; }; q(1)(2);");
     59 test("n", 3, "q = function (n) { for (var i = 0; i < n; i++) { { let j = i; h(); } } }; q(3);");
     60 
     61 // A function with long dynamic and static chains.
     62 var N = 80;
     63 
     64 var code = "function f" + N + "(a" + N + ") {\neval('a0 + a1'); h();\n}\n";
     65 for (var i = N; --i >= 0;) {
     66    var call = "f" + (i + 1) + "(a" + i + " - 1);\n";
     67    code = ("function f" + i + "(a" + i + ") {\n" +
     68            code +
     69            call +
     70            "if (a" + i + " === 0) " + call +
     71            "}\n");
     72 }
     73 
     74 g.eval(code);
     75 test("a0", 2, "f0(0);");
     76 test("a17", 2, "f0(17);");
     77 test("a" + (N-2), 2, "f0(" + (N-2) + ");");
     78 test("a" + (N-1), 2, "f0(" + (N-1) + ");");
     79 
     80 // A function with a short dynamic chain and a long static chain.
     81 N = 60;
     82 
     83 function DeepStaticShallowDynamic(i, n) {
     84    var code = "function f" + i + "(a" + i + ") {\n";
     85    if (i >= n)
     86        code += "eval('a1 + a2'); h();\n";
     87    else
     88        code += "return " + DeepStaticShallowDynamic(i+1, n) + ";\n";
     89    code += "}";
     90    return code;
     91 }
     92 g.eval(DeepStaticShallowDynamic(1, N));
     93 
     94 function* range(start, stop) {
     95    for (var i = start; i < stop; i++)
     96        yield i;
     97 }
     98 
     99 function DSSDsplit(s) {
    100    return ("var mid = f1" + [...range(0, s)].map((i) => "(" + i + ")").join("") + ";\n" +
    101            "mid" +          [...range(s, N)].map((i) => "(" + i + ")").join("") + ";\n" +
    102            "mid" +          [...range(s, N)].map((i) => "(" + i + ")").join("") + ";\n");
    103 }
    104 
    105 test("a1", 2, DSSDsplit(1));
    106 test("a17", 2, DSSDsplit(17));
    107 test("a" + (N-2), 2, DSSDsplit(N-2));
    108 test("a" + (N-1), 2, DSSDsplit(N-1));