|
3 | 3 | const wait = require('timers/promises').setTimeout;
|
4 | 4 | const assert = require('assert');
|
5 | 5 | const common = require('../common');
|
| 6 | +// TODO(joyeecheung): rewrite checkIfCollectable to use this too. |
| 7 | +const { setImmediate: setImmediatePromisified } = require('timers/promises'); |
6 | 8 | const gcTrackerMap = new WeakMap();
|
7 | 9 | const gcTrackerTag = 'NODE_TEST_COMMON_GC_TRACKER';
|
8 | 10 |
|
@@ -40,32 +42,26 @@ function onGC(obj, gcListener) {
|
40 | 42 |
|
41 | 43 | /**
|
42 | 44 | * Repeatedly triggers garbage collection until a specified condition is met or a maximum number of attempts is reached.
|
| 45 | + * This utillity must be run in a Node.js instance that enables --expose-gc. |
43 | 46 | * @param {string|Function} [name] - Optional name, used in the rejection message if the condition is not met.
|
44 | 47 | * @param {Function} condition - A function that returns true when the desired condition is met.
|
| 48 | + * @param {number} maxCount - Maximum number of garbage collections that should be tried. |
| 49 | + * @param {object} gcOptions - Options to pass into the global gc() function. |
45 | 50 | * @returns {Promise} A promise that resolves when the condition is met, or rejects after 10 failed attempts.
|
46 | 51 | */
|
47 |
| -function gcUntil(name, condition) { |
48 |
| - if (typeof name === 'function') { |
49 |
| - condition = name; |
50 |
| - name = undefined; |
51 |
| - } |
52 |
| - return new Promise((resolve, reject) => { |
53 |
| - let count = 0; |
54 |
| - function gcAndCheck() { |
55 |
| - setImmediate(() => { |
56 |
| - count++; |
57 |
| - global.gc(); |
58 |
| - if (condition()) { |
59 |
| - resolve(); |
60 |
| - } else if (count < 10) { |
61 |
| - gcAndCheck(); |
62 |
| - } else { |
63 |
| - reject(name === undefined ? undefined : 'Test ' + name + ' failed'); |
64 |
| - } |
65 |
| - }); |
| 52 | +async function gcUntil(name, condition, maxCount = 10, gcOptions) { |
| 53 | + for (let count = 0; count < maxCount; ++count) { |
| 54 | + await setImmediatePromisified(); |
| 55 | + if (gcOptions) { |
| 56 | + await global.gc(gcOptions); |
| 57 | + } else { |
| 58 | + await global.gc(); // Passing in undefined is not the same as empty. |
66 | 59 | }
|
67 |
| - gcAndCheck(); |
68 |
| - }); |
| 60 | + if (condition()) { |
| 61 | + return; |
| 62 | + } |
| 63 | + } |
| 64 | + throw new Error(`Test ${name} failed`); |
69 | 65 | }
|
70 | 66 |
|
71 | 67 | // This function can be used to check if an object factor leaks or not,
|
|
0 commit comments