Skip to content

Commit

Permalink
Add unit test and fix longStackTraces=true case
Browse files Browse the repository at this point in the history
  • Loading branch information
Shingyx committed Aug 31, 2018
1 parent ff9ef54 commit 15fbdb9
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 7 deletions.
14 changes: 7 additions & 7 deletions src/async.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,15 @@ if (!util.hasDevTools) {
};
}

Async.prototype._drainQueue = function(queue) {
function _drainQueue(queue) {
while (queue.length() > 0) {
this._drainQueueStep(queue);
_drainQueueStep(queue);
}
};
}

// Shift the queue in a separate function to allow
// garbage collection after each step
Async.prototype._drainQueueStep = function (queue) {
function _drainQueueStep(queue) {
var fn = queue.shift();
if (typeof fn !== "function") {
fn._settlePromises();
Expand All @@ -149,14 +149,14 @@ Async.prototype._drainQueueStep = function (queue) {
var arg = queue.shift();
fn.call(receiver, arg);
}
};
}

Async.prototype._drainQueues = function () {
ASSERT(this._isTickUsed);
this._drainQueue(this._normalQueue);
_drainQueue(this._normalQueue);
this._reset();
this._haveDrainedQueues = true;
this._drainQueue(this._lateQueue);
_drainQueue(this._lateQueue);
};

Async.prototype._queueTick = function () {
Expand Down
8 changes: 8 additions & 0 deletions src/debuggability.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,19 +127,22 @@ Promise.longStackTraces = function () {
if (!config.longStackTraces && longStackTracesIsSupported()) {
var Promise_captureStackTrace = Promise.prototype._captureStackTrace;
var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace;
var Promise_dereferenceTrace = Promise.prototype._dereferenceTrace;
config.longStackTraces = true;
disableLongStackTraces = function() {
if (async.haveItemsQueued() && !config.longStackTraces) {
throw new Error(LONG_STACK_TRACES_ERROR);
}
Promise.prototype._captureStackTrace = Promise_captureStackTrace;
Promise.prototype._attachExtraTrace = Promise_attachExtraTrace;
Promise.prototype._dereferenceTrace = Promise_dereferenceTrace;
Context.deactivateLongStackTraces();
async.enableTrampoline();
config.longStackTraces = false;
};
Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace;
Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace;
Promise.prototype._dereferenceTrace = longStackTracesDereferenceTrace;
Context.activateLongStackTraces();
async.disableTrampolineIfNecessary();
}
Expand Down Expand Up @@ -325,6 +328,7 @@ Promise.prototype._attachCancellationCallback = function(onCancel) {
};
Promise.prototype._captureStackTrace = function () {};
Promise.prototype._attachExtraTrace = function () {};
Promise.prototype._dereferenceTrace = function () {};
Promise.prototype._clearCancellationData = function() {};
Promise.prototype._propagateFrom = function (parent, flags) {
USE(parent);
Expand Down Expand Up @@ -435,6 +439,10 @@ function longStackTracesAttachExtraTrace(error, ignoreSelf) {
}
}

function longStackTracesDereferenceTrace() {
this._trace = undefined;
}

function checkForgottenReturns(returnValue, promiseCreated, name, promise,
parent) {
if (returnValue === undefined && promiseCreated !== null &&
Expand Down
1 change: 1 addition & 0 deletions src/promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -681,6 +681,7 @@ Promise.prototype._fulfill = function (value) {
} else {
async.settlePromises(this);
}
this._dereferenceTrace();
}
};

Expand Down
94 changes: 94 additions & 0 deletions test/mocha/async.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,4 +152,98 @@ describe("Async requirement", function() {
});
});
}

if (testUtils.isNodeJS) {
describe("Frees memory of old values in promise chain", function () {
if (typeof global.gc !== "function") {
var v8 = require("v8");
var vm = require("vm");
v8.setFlagsFromString("--expose_gc");
global.gc = vm.runInNewContext("gc");
}

function getHeapUsed() {
global.gc();
return process.memoryUsage().heapUsed;
}

var initialHeapUsed;

beforeEach(function () {
initialHeapUsed = getHeapUsed();
});

specify(".then", function () {
return Promise.resolve()
.then(function () {
assert.ok(
getHeapUsed() < initialHeapUsed * 1.1,
"Promise.resolve uses minimal memory"
);
const rows = [];
for (let i = 0; i < 1e6; i++) {
rows.push(["Example " + i, i, i * 2]);
}
return rows;
})
.then(function (rows) {
assert.ok(
getHeapUsed() > initialHeapUsed * 15,
"large array uses a large amount of memory"
);
return { len: rows.length };
})
.then(function (x) {
// work around cancellation retaining previous result
return x;
})
.then(function (summaryResult) {
assert.ok(
getHeapUsed() < initialHeapUsed * 1.1,
"memory used by large array is freed"
);
assert.strictEqual(summaryResult.len, 1e6, "result");
});
});

specify(".catch", function () {
return Promise.reject(new Error("error 1"))
.catch(function () {
assert.ok(
getHeapUsed() < initialHeapUsed * 1.1,
"Promise.resolve uses minimal memory"
);
const rows = [];
for (let i = 0; i < 1e6; i++) {
rows.push(["Example " + i, i, i * 2]);
}
var error = new Error("error 2");
error.result = rows;
throw error;
})
.catch(function (err) {
assert.ok(
getHeapUsed() > initialHeapUsed * 15,
"large array uses a large amount of memory"
);
var rows = err.result;
var error = new Error("error 3");
error.result = { len: rows.length };
throw error;
})
.catch(function (err) {
// work around cancellation retaining previous result
throw err;
})
.catch(function (err) {
assert.ok(
getHeapUsed() < initialHeapUsed * 1.1,
"memory used by large array is freed"
);
var summaryResult = err.result;
assert.strictEqual(summaryResult.len, 1e6, "result");
});
});
});
}
});

0 comments on commit 15fbdb9

Please sign in to comment.