Skip to content

Commit

Permalink
Fix potentially massive memory leak
Browse files Browse the repository at this point in the history
The logic for choosing between the Map and WeakMap for completed operation tracking wasn't right, and the result was that everything was being added to the Map, leaking every token. For waitForPromise() the token is the promise itself, meaning the resolved values were also leaking, which can easily add up to a memory leak of epic proportions.
  • Loading branch information
bendemboski committed Feb 25, 2021
1 parent be46eae commit 3494e8f
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 3 deletions.
8 changes: 5 additions & 3 deletions addon/@ember/test-waiters/build-waiter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,11 @@ class TestWaiterImpl<T extends object | Primitive = Token> implements TestWaiter
private _getCompletedOperations(token: T) {
let type = typeof token;

return token !== null || (type !== 'function' && type !== 'object')
? this.completedOperationsForPrimitives
: this.completedOperationsForTokens;
let isFunction = type === 'function';
let isObject = token !== null && type === 'object';
let isPrimitive = !isFunction && !isObject;

return isPrimitive ? this.completedOperationsForPrimitives : this.completedOperationsForTokens;
}
}

Expand Down
12 changes: 12 additions & 0 deletions tests/unit/build-waiter-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,4 +276,16 @@ module('build-waiter', function(hooks) {

assert.equal((waiter as any).items.size, 0);
});

test('completed operations tracking does not leak non-primitive tokens', function(assert) {
let waiter = buildWaiter('@ember/test-waiters:my-waiter');

const tokens = [undefined, {}, function() {}, Promise.resolve()];

for (let token of tokens) {
waiter.endAsync(waiter.beginAsync(token));
}

assert.equal((waiter as any).completedOperationsForPrimitives.size, 0);
});
});

0 comments on commit 3494e8f

Please sign in to comment.