|
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