Skip to content

Commit

Permalink
Merge pull request #11412 from Uzlopak/isSimpleValidator
Browse files Browse the repository at this point in the history
perf: add isSimpleValidator
  • Loading branch information
vkarpov15 committed Mar 7, 2022
2 parents 7eaf775 + aaa446f commit 029b786
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 14 deletions.
30 changes: 30 additions & 0 deletions lib/helpers/isSimpleValidator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
'use strict';

/*!
* Determines if `arg` is a flat object.
*
* @param {Object|Array|String|Function|RegExp|any} arg
* @api private
* @return {Boolean}
*/
const isSimpleValidatorCache = new WeakMap();

module.exports = function isSimpleValidator(obj) {
if (!isSimpleValidatorCache.has(obj)) {
isSimpleValidatorCache.set(obj, _isSimpleValidator(obj));
}
return isSimpleValidatorCache.get(obj);
};

function _isSimpleValidator(obj) {
const keys = Object.keys(obj);
let result = true;
for (let i = 0, len = keys.length; i < len; ++i) {
if (typeof obj[keys[i]] === 'object' && obj[keys[i]] !== null) {
result = false;
break;
}
}

return result;
}
29 changes: 15 additions & 14 deletions lib/schematype.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const $exists = require('./schema/operators/exists');
const $type = require('./schema/operators/type');
const handleImmutable = require('./helpers/schematype/handleImmutable');
const isAsyncFunction = require('./helpers/isAsyncFunction');
const isSimpleValidator = require('./helpers/isSimpleValidator');
const immediate = require('./helpers/immediate');
const schemaTypeSymbol = require('./helpers/symbols').schemaTypeSymbol;
const utils = require('./utils');
Expand Down Expand Up @@ -886,7 +887,7 @@ SchemaType.prototype.validate = function(obj, message, type) {
properties = { validator: obj, message: message };
properties.type = type || 'user defined';
} else if (message instanceof Object && !type) {
properties = utils.clone(message);
properties = isSimpleValidator(message) ? Object.assign({}, message) : utils.clone(message);
if (!properties.message) {
properties.message = properties.msg;
}
Expand Down Expand Up @@ -914,8 +915,8 @@ SchemaType.prototype.validate = function(obj, message, type) {
arg = arguments[i];
if (!utils.isPOJO(arg)) {
const msg = 'Invalid validator. Received (' + typeof arg + ') '
+ arg
+ '. See https://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
+ arg
+ '. See https://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';

throw new Error(msg);
}
Expand Down Expand Up @@ -1242,7 +1243,7 @@ SchemaType.prototype.doValidate = function(value, fn, scope, options) {

// Avoid non-object `validators`
const validators = this.validators.
filter(v => v != null && typeof v === 'object');
filter(v => typeof v === 'object' && v !== null);

let count = validators.length;

Expand All @@ -1251,15 +1252,15 @@ SchemaType.prototype.doValidate = function(value, fn, scope, options) {
}

for (let i = 0, len = validators.length; i < len; ++i) {
const v = validators[i];
if (err) {
break;
}

const v = validators[i];
const validator = v.validator;
let ok;

const validatorProperties = utils.clone(v);
const validatorProperties = isSimpleValidator(v) ? Object.assign({}, v) : utils.clone(v);
validatorProperties.path = options && options.path ? options.path : path;
validatorProperties.value = value;

Expand Down Expand Up @@ -1373,12 +1374,12 @@ SchemaType.prototype.doValidateSync = function(value, scope, options) {

const v = validators[i];

if (v == null || typeof v !== 'object') {
if (v === null || typeof v !== 'object') {
continue;
}

const validator = v.validator;
const validatorProperties = utils.clone(v);
const validatorProperties = isSimpleValidator(v) ? Object.assign({}, v) : utils.clone(v);
validatorProperties.path = options && options.path ? options.path : path;
validatorProperties.value = value;
let ok = false;
Expand Down Expand Up @@ -1453,8 +1454,8 @@ SchemaType._isRef = function(self, value, doc, init) {
return true;
}
if (!Buffer.isBuffer(value) && // buffers are objects too
value._bsontype !== 'Binary' // raw binary value from the db
&& utils.isObject(value) // might have deselected _id in population query
value._bsontype !== 'Binary' // raw binary value from the db
&& utils.isObject(value) // might have deselected _id in population query
) {
return true;
}
Expand Down Expand Up @@ -1495,10 +1496,10 @@ SchemaType.prototype._castRef = function _castRef(value, doc, init) {
const pop = owner.$populated(path, true);
let ret = value;
if (!doc.$__.populated ||
!doc.$__.populated[path] ||
!doc.$__.populated[path].options ||
!doc.$__.populated[path].options.options ||
!doc.$__.populated[path].options.options.lean) {
!doc.$__.populated[path] ||
!doc.$__.populated[path].options ||
!doc.$__.populated[path].options.options ||
!doc.$__.populated[path].options.options.lean) {
ret = new pop.options[populateModelSymbol](value);
ret.$__.wasPopulated = true;
}
Expand Down
39 changes: 39 additions & 0 deletions test/helpers/isSimpleValidator.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'use strict';

const assert = require('assert');
const isSimpleValidator = require('../../lib/helpers/isSimpleValidator');
const MongooseDocumentArray = require('../../lib/types/DocumentArray');

describe('isSimpleValidator', function() {
it('empty object', function() {
assert.ok(isSimpleValidator({}));
});
it('object with one primitive attribute', function() {
assert.ok(isSimpleValidator({ a: 1 }));
assert.ok(isSimpleValidator({ a: 1n }));
assert.ok(isSimpleValidator({ a: 'primitive' }));
assert.ok(isSimpleValidator({ a: true }));
});
it('object with one simple array attribute', function() {
assert.ok(!isSimpleValidator({ a: [1] }));
assert.ok(!isSimpleValidator({ a: [1n] }));
assert.ok(!isSimpleValidator({ a: ['primitive'] }));
assert.ok(!isSimpleValidator({ a: ['primitive'] }));
assert.ok(!isSimpleValidator({ a: ['primitive', 'primitive'] }));
assert.ok(!isSimpleValidator({ a: [new Date()] }));
assert.ok(!isSimpleValidator({ a: [true] }));
});
it('object with some native objects', function() {
assert.ok(!isSimpleValidator({ a: /a/g }));
assert.ok(!isSimpleValidator({ a: new Date() }));
});
it('object with one sub object', function() {
assert.ok(!isSimpleValidator({ a: {} }));
assert.ok(!isSimpleValidator({ a: [{}] }));
assert.ok(!isSimpleValidator({ a: { b: 1 } }));
});
it('object with one attribute of type MongooseDocumentArray', function() {
assert.ok(!isSimpleValidator({ a: new MongooseDocumentArray(['a']) }));
assert.ok(!isSimpleValidator({ a: new MongooseDocumentArray([{}]) }));
});
});

0 comments on commit 029b786

Please sign in to comment.