Skip to content

Commit 1af762a

Browse files
authored
Merge pull request #15345 from Automattic/vkarpov15/gh-15194
feat: add skipOriginalStackTraces option to avoid stack trace performance overhead
2 parents 7e7dc1a + 1f0d3e4 commit 1af762a

File tree

5 files changed

+30
-12
lines changed

5 files changed

+30
-12
lines changed

lib/document.js

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2620,7 +2620,6 @@ Document.prototype.validate = async function validate(pathsToValidate, options)
26202620
if (typeof pathsToValidate === 'function' || typeof options === 'function' || typeof arguments[2] === 'function') {
26212621
throw new MongooseError('Document.prototype.validate() no longer accepts a callback');
26222622
}
2623-
let parallelValidate;
26242623
this.$op = 'validate';
26252624

26262625
if (arguments.length === 1) {
@@ -2638,16 +2637,9 @@ Document.prototype.validate = async function validate(pathsToValidate, options)
26382637
if (this.$isSubdocument != null) {
26392638
// Skip parallel validate check for subdocuments
26402639
} else if (this.$__.validating && !_skipParallelValidateCheck) {
2641-
parallelValidate = new ParallelValidateError(this, {
2642-
parentStack: options && options.parentStack,
2643-
conflictStack: this.$__.validating.stack
2644-
});
2640+
throw new ParallelValidateError(this);
26452641
} else if (!_skipParallelValidateCheck) {
2646-
this.$__.validating = new ParallelValidateError(this, { parentStack: options && options.parentStack });
2647-
}
2648-
2649-
if (parallelValidate != null) {
2650-
throw parallelValidate;
2642+
this.$__.validating = true;
26512643
}
26522644

26532645
return new Promise((resolve, reject) => {

lib/query.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4431,10 +4431,12 @@ Query.prototype.exec = async function exec(op) {
44314431
str = str.slice(0, 60) + '...';
44324432
}
44334433
const err = new MongooseError('Query was already executed: ' + str);
4434-
err.originalStack = this._executionStack;
4434+
if (!this.model.base.options.skipOriginalStackTraces) {
4435+
err.originalStack = this._executionStack;
4436+
}
44354437
throw err;
44364438
} else {
4437-
this._executionStack = new Error().stack;
4439+
this._executionStack = this.model.base.options.skipOriginalStackTraces ? true : new Error().stack;
44384440
}
44394441

44404442
let skipWrappedFunction = null;

lib/validOptions.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const VALID_OPTIONS = Object.freeze([
2929
'sanitizeProjection',
3030
'selectPopulatedPaths',
3131
'setDefaultsOnInsert',
32+
'skipOriginalStackTraces',
3233
'strict',
3334
'strictPopulate',
3435
'strictQuery',

test/index.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,4 +1228,19 @@ describe('mongoose module:', function() {
12281228
assert.equal(m.connection.readyState, 1);
12291229
});
12301230
});
1231+
1232+
it('supports skipOriginalStackTraces option (gh-15194)', async function() {
1233+
const schema = new Schema({ name: { type: String, required: true } });
1234+
const m = new mongoose.Mongoose();
1235+
m.set('skipOriginalStackTraces', true);
1236+
await m.connect(start.uri);
1237+
1238+
const TestModel = m.model('Test', schema);
1239+
const q = TestModel.find({});
1240+
await q.exec();
1241+
assert.strictEqual(q._executionStack, true);
1242+
1243+
const err = await q.exec().then(() => null, err => err);
1244+
assert.strictEqual(err.originalStack, undefined);
1245+
});
12311246
});

types/mongooseoptions.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,5 +215,13 @@ declare module 'mongoose' {
215215
* to their database property names. Defaults to false.
216216
*/
217217
translateAliases?: boolean;
218+
219+
/**
220+
* Mongoose queries currently store an `_executionStack` property that stores the stack trace
221+
* of where the query was originally executed for debugging `Query was already executed` errors.
222+
* This behavior can cause performance issues with bundlers and source maps. Set this option to
223+
* `true` to disable Mongoose query stack trace collection.
224+
*/
225+
skipOriginalStackTraces?: boolean;
218226
}
219227
}

0 commit comments

Comments
 (0)