Skip to content

Commit

Permalink
perf: memoize default toObject options on a per-schema basis re: #14394
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed May 31, 2024
1 parent a40706b commit 75c6f88
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 19 deletions.
21 changes: 2 additions & 19 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const clone = require('./helpers/clone');
const compile = require('./helpers/document/compile').compile;
const defineKey = require('./helpers/document/compile').defineKey;
const flatten = require('./helpers/common').flatten;
const get = require('./helpers/get');
const getEmbeddedDiscriminatorPath = require('./helpers/document/getEmbeddedDiscriminatorPath');
const getKeysInSchemaOrder = require('./helpers/schema/getKeysInSchemaOrder');
const getSubdocumentStrictValue = require('./helpers/schema/getSubdocumentStrictValue');
Expand Down Expand Up @@ -3798,15 +3797,7 @@ Document.prototype.$__handleReject = function handleReject(err) {
*/

Document.prototype.$toObject = function(options, json) {
const path = json ? 'toJSON' : 'toObject';
const baseOptions = this.constructor &&
this.constructor.base &&
this.constructor.base.options &&
get(this.constructor.base.options, path) || {};
const schemaOptions = this.$__schema && this.$__schema.options || {};
// merge base default options with Schema's set default options if available.
// `clone` is necessary here because `utils.options` directly modifies the second input.
const defaultOptions = Object.assign({}, baseOptions, schemaOptions[path]);
const defaultOptions = this.$__schema._getDefaultToObjectOptions();

// If options do not exist or is not an object, set it to empty object
options = utils.isPOJO(options) ? { ...options } : {};
Expand All @@ -3815,10 +3806,8 @@ Document.prototype.$toObject = function(options, json) {
let _minimize;
if (options._calledWithOptions.minimize != null) {
_minimize = options.minimize;
} else if (defaultOptions.minimize != null) {
_minimize = defaultOptions.minimize;
} else {
_minimize = schemaOptions.minimize;
_minimize = defaultOptions.minimize;
}

options.minimize = _minimize;
Expand All @@ -3842,14 +3831,8 @@ Document.prototype.$toObject = function(options, json) {
}
options._isNested = true;
options.json = json;
options.minimize = _minimize;

options._parentOptions = options;

options._skipSingleNestedGetters = false;
// remember the root transform function
// to save it from being overwritten by sub-transform functions
// const originalTransform = options.transform;

let ret = clone(this._doc, options) || {};

Expand Down
28 changes: 28 additions & 0 deletions lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ function Schema(obj, options) {
// For internal debugging. Do not use this to try to save a schema in MDB.
this.$id = ++id;
this.mapPaths = [];
this._defaultToObjectOptions = null;

this.s = {
hooks: new Kareem()
Expand Down Expand Up @@ -2597,6 +2598,33 @@ Schema.prototype.loadClass = function(model, virtualsOnly) {
return this;
};

/**
* Returns default `toObject` / `toJSON` options for this schema,
* combining the associated
*
* @param {Boolean} json
* @returns object
*/

Schema.prototype._getDefaultToObjectOptions = function _getDefaultToObjectOptions(json) {
const path = json ? 'toJSON' : 'toObject';

if (this._defaultToObjectOptions && this._defaultToObjectOptions[path]) {
return this._defaultToObjectOptions[path];
}

const baseOptions = this.base && this.base.options && this.base.options[path];
const schemaOptions = this.options && this.options[path];
const defaultOptions = Object.assign(
{},
baseOptions,
schemaOptions
);
this._defaultToObjectOptions = this._defaultToObjectOptions || {};
this._defaultToObjectOptions[path] = defaultOptions;
return defaultOptions;
};

/*!
* ignore
*/
Expand Down

0 comments on commit 75c6f88

Please sign in to comment.