summaryrefslogtreecommitdiffstats
path: root/js/xpconnect/tests/unit/test_onGarbageCollection-02.js
blob: fc3bf685ef2279ff7870d284bb7a3f26dd6ec97c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Test multiple debuggers, GCs, and zones interacting with each other.
//
// Note: when observing both globals, but GC'ing in only one, we don't test that
// we *didn't* GC in the other zone because GCs are finicky and unreliable. That
// used to work when this was a jit-test, but in the process of migrating to
// xpcshell, we lost some amount of reliability and determinism.

const root1 = newGlobal();
const dbg1 = new Debugger();
dbg1.addDebuggee(root1)

const root2 = newGlobal();
const dbg2 = new Debugger();
dbg2.addDebuggee(root2)

let fired1 = false;
let fired2 = false;
dbg1.memory.onGarbageCollection = _ => fired1 = true;
dbg2.memory.onGarbageCollection = _ => fired2 = true;

Services.prefs.setBoolPref("security.allow_eval_with_system_principal", true);
registerCleanupFunction(() => {
  Services.prefs.clearUserPref("security.allow_eval_with_system_principal");
});

function reset() {
  fired1 = false;
  fired2 = false;
}

function run_test() {
  do_test_pending();

  gc();
  executeSoon(() => {
    reset();

    // GC 1 only
    root1.eval(`gc(this)`);
    executeSoon(() => {
      equal(fired1, true);

      // GC 2 only
      reset();
      root2.eval(`gc(this)`);
      executeSoon(() => {
        equal(fired2, true);

        // Full GC
        reset();
        gc();
        executeSoon(() => {
          equal(fired1, true);
          equal(fired2, true);

          // Full GC with no debuggees
          reset();
          dbg1.removeAllDebuggees();
          dbg2.removeAllDebuggees();
          gc();
          executeSoon(() => {
            equal(fired1, false);
            equal(fired2, false);

            // One debugger with multiple debuggees in different zones.

            dbg1.addDebuggee(root1);
            dbg1.addDebuggee(root2);

            // Just debuggee 1
            reset();
            root1.eval(`gc(this)`);
            executeSoon(() => {
              equal(fired1, true);
              equal(fired2, false);

              // Just debuggee 2
              reset();
              root2.eval(`gc(this)`);
              executeSoon(() => {
                equal(fired1, true);
                equal(fired2, false);

                // All debuggees
                reset();
                gc();
                executeSoon(() => {
                  equal(fired1, true);
                  equal(fired2, false);
                  do_test_finished();
                });
              });
            });
          });
        });
      });
    });
  });
}