From e027e4fd02bcd91da3e35ada56e6d0461bb931c5 Mon Sep 17 00:00:00 2001 From: Hafez Date: Fri, 5 Dec 2025 03:54:16 +0100 Subject: [PATCH] refactor: use Object.hasOwn instead of Object#hasOwnProperty --- lib/aggregate.js | 2 +- lib/cast.js | 2 +- lib/connection.js | 18 ++++---- lib/document.js | 39 +++++++++-------- lib/drivers/node-mongodb-native/connection.js | 4 +- lib/helpers/common.js | 2 +- lib/helpers/indexes/applySchemaCollation.js | 2 +- lib/helpers/indexes/isDefaultIdIndex.js | 2 +- lib/helpers/model/applyMethods.js | 2 +- lib/helpers/model/castBulkWrite.js | 2 +- .../populate/getModelsMapForPopulate.js | 6 +-- lib/helpers/populate/modelNamesFromRefPath.js | 2 +- .../populate/removeDeselectedForeignField.js | 2 +- lib/helpers/projection/applyProjection.js | 4 +- .../query/getEmbeddedDiscriminatorPath.js | 2 +- lib/helpers/setDefaultsOnInsert.js | 4 +- lib/helpers/timestamps/setupTimestamps.js | 2 +- lib/helpers/update/applyTimestampsToUpdate.js | 2 +- .../update/decorateUpdateWithVersionKey.js | 2 +- lib/model.js | 14 +++---- lib/mongoose.js | 7 ++-- lib/query.js | 6 +-- lib/schema.js | 42 +++++++++---------- lib/schema/array.js | 2 +- lib/schemaType.js | 16 +++---- lib/types/array/index.js | 10 ++--- lib/types/documentArray/index.js | 12 +++--- lib/types/objectid.js | 2 +- lib/utils.js | 16 +------ lib/virtualType.js | 2 +- 30 files changed, 110 insertions(+), 120 deletions(-) diff --git a/lib/aggregate.js b/lib/aggregate.js index e475736da2e..55bddc7ca79 100644 --- a/lib/aggregate.js +++ b/lib/aggregate.js @@ -103,7 +103,7 @@ Aggregate.prototype._optionsForExec = function() { const options = this.options || {}; const asyncLocalStorage = this.model()?.db?.base.transactionAsyncLocalStorage?.getStore(); - if (!options.hasOwnProperty('session') && asyncLocalStorage?.session != null) { + if (!Object.hasOwn(options, 'session') && asyncLocalStorage?.session != null) { options.session = asyncLocalStorage.session; } diff --git a/lib/cast.js b/lib/cast.js index 6f75d9bfe37..74ee2d516e2 100644 --- a/lib/cast.js +++ b/lib/cast.js @@ -107,7 +107,7 @@ module.exports = function cast(schema, obj, options, context) { val = cast(schema, val, options, context); } else if (path === '$text') { val = castTextSearch(val, path); - } else if (path === '$comment' && !schema.paths.hasOwnProperty('$comment')) { + } else if (path === '$comment' && !Object.hasOwn(schema.paths, '$comment')) { val = castString(val, path); obj[path] = val; } else { diff --git a/lib/connection.js b/lib/connection.js index 1b1d6bdff04..7fbf3dd7a02 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -164,7 +164,7 @@ Object.defineProperty(Connection.prototype, 'readyState', { */ Connection.prototype.get = function getOption(key) { - if (this.config.hasOwnProperty(key)) { + if (Object.hasOwn(this.config, key)) { return this.config[key]; } @@ -192,7 +192,7 @@ Connection.prototype.get = function getOption(key) { */ Connection.prototype.set = function setOption(key, val) { - if (this.config.hasOwnProperty(key)) { + if (Object.hasOwn(this.config, key)) { this.config[key] = val; return val; } @@ -459,7 +459,7 @@ Connection.prototype.bulkWrite = async function bulkWrite(ops, options) { const ordered = options.ordered == null ? true : options.ordered; const asyncLocalStorage = this.base.transactionAsyncLocalStorage?.getStore(); - if ((!options || !options.hasOwnProperty('session')) && asyncLocalStorage?.session != null) { + if ((!options || !Object.hasOwn(options, 'session')) && asyncLocalStorage?.session != null) { options = { ...options, session: asyncLocalStorage.session }; } @@ -477,7 +477,7 @@ Connection.prototype.bulkWrite = async function bulkWrite(ops, options) { if (op.name == null) { throw new MongooseError('Must specify operation name in Connection.prototype.bulkWrite()'); } - if (!castBulkWrite.cast.hasOwnProperty(op.name)) { + if (!Object.hasOwn(castBulkWrite.cast, op.name)) { throw new MongooseError(`Unrecognized bulkWrite() operation name ${op.name}`); } @@ -513,7 +513,7 @@ Connection.prototype.bulkWrite = async function bulkWrite(ops, options) { results[i] = error; continue; } - if (!castBulkWrite.cast.hasOwnProperty(op.name)) { + if (!Object.hasOwn(castBulkWrite.cast, op.name)) { const error = new MongooseError(`Unrecognized bulkWrite() operation name ${op.name}`); validationErrors.push({ index: i, error: error }); results[i] = error; @@ -772,10 +772,10 @@ async function _wrapUserTransaction(fn, session, mongoose) { function _resetSessionDocuments(session) { for (const doc of session[sessionNewDocuments].keys()) { const state = session[sessionNewDocuments].get(doc); - if (state.hasOwnProperty('isNew')) { + if (Object.hasOwn(state, 'isNew')) { doc.$isNew = state.isNew; } - if (state.hasOwnProperty('versionKey')) { + if (Object.hasOwn(state, 'versionKey')) { doc.set(doc.schema.options.versionKey, state.versionKey); } @@ -1013,7 +1013,7 @@ Connection.prototype.onOpen = function() { // avoid having the collection subscribe to our event emitter // to prevent 0.3 warning for (const i in this.collections) { - if (utils.object.hasOwnProperty(this.collections, i)) { + if (Object.hasOwn(this.collections, i)) { this.collections[i].onOpen(); } } @@ -1321,7 +1321,7 @@ Connection.prototype.onClose = function onClose(force) { // avoid having the collection subscribe to our event emitter // to prevent 0.3 warning for (const i in this.collections) { - if (utils.object.hasOwnProperty(this.collections, i)) { + if (Object.hasOwn(this.collections, i)) { this.collections[i].onClose(force); } } diff --git a/lib/document.js b/lib/document.js index e9b1e63e90b..042a9a55803 100644 --- a/lib/document.js +++ b/lib/document.js @@ -780,7 +780,7 @@ function init(self, obj, doc, opts, prefix) { } } else { // Retain order when overwriting defaults - if (doc.hasOwnProperty(i) && value !== void 0 && !opts.hydratedPopulatedDocs) { + if (Object.hasOwn(doc, i) && value !== void 0 && !opts.hydratedPopulatedDocs) { delete doc[i]; } if (value === null) { @@ -1156,7 +1156,7 @@ Document.prototype.$set = function $set(path, val, type, options) { const orderedKeys = Object.keys(this.$__schema.tree); for (let i = 0, len = orderedKeys.length; i < len; ++i) { (key = orderedKeys[i]) && - (this._doc.hasOwnProperty(key)) && + (Object.hasOwn(this._doc, key)) && (orderedDoc[key] = undefined); } this._doc = Object.assign(orderedDoc, this._doc); @@ -1206,8 +1206,8 @@ Document.prototype.$set = function $set(path, val, type, options) { return this; } const wasModified = this.$isModified(path); - const hasInitialVal = this.$__.savedState != null && this.$__.savedState.hasOwnProperty(path); - if (this.$__.savedState != null && !this.$isNew && !this.$__.savedState.hasOwnProperty(path)) { + const hasInitialVal = this.$__.savedState != null && Object.hasOwn(this.$__.savedState, path); + if (this.$__.savedState != null && !this.$isNew && !Object.hasOwn(this.$__.savedState, path)) { const initialVal = this.$__getValue(path); this.$__.savedState[path] = initialVal; @@ -1512,7 +1512,7 @@ Document.prototype.$set = function $set(path, val, type, options) { this.$__.session[sessionNewDocuments].get(this).modifiedPaths && !this.$__.session[sessionNewDocuments].get(this).modifiedPaths.has(savedStatePath); if (savedState != null && - savedState.hasOwnProperty(savedStatePath) && + Object.hasOwn(savedState, savedStatePath) && (!isInTransaction || isModifiedWithinTransaction) && utils.deepEqual(val, savedState[savedStatePath])) { this.unmarkModified(path); @@ -1994,7 +1994,7 @@ Document.prototype.$get = Document.prototype.get; Document.prototype.$__path = function(path) { const adhocs = this.$__.adhocPaths; - const adhocType = adhocs && adhocs.hasOwnProperty(path) ? adhocs[path] : null; + const adhocType = adhocs && Object.hasOwn(adhocs, path) ? adhocs[path] : null; if (adhocType) { return adhocType; @@ -2038,7 +2038,7 @@ Document.prototype.$__saveInitialState = function $__saveInitialState(path) { if (savedState != null) { const firstDot = savedStatePath.indexOf('.'); const topLevelPath = firstDot === -1 ? savedStatePath : savedStatePath.slice(0, firstDot); - if (!savedState.hasOwnProperty(topLevelPath)) { + if (!Object.hasOwn(savedState, topLevelPath)) { savedState[topLevelPath] = clone(this.$__getValue(topLevelPath)); } } @@ -2349,7 +2349,7 @@ Document.prototype.$isDefault = function(path) { } if (typeof path === 'string' && path.indexOf(' ') === -1) { - return this.$__.activePaths.getStatePaths('default').hasOwnProperty(path); + return Object.hasOwn(this.$__.activePaths.getStatePaths('default'), path); } let paths = path; @@ -2357,7 +2357,7 @@ Document.prototype.$isDefault = function(path) { paths = paths.split(' '); } - return paths.some(path => this.$__.activePaths.getStatePaths('default').hasOwnProperty(path)); + return paths.some(path => Object.hasOwn(this.$__.activePaths.getStatePaths('default'), path)); }; /** @@ -2411,7 +2411,7 @@ Document.prototype.isDirectModified = function(path) { } if (typeof path === 'string' && path.indexOf(' ') === -1) { - const res = this.$__.activePaths.getStatePaths('modify').hasOwnProperty(path); + const res = Object.hasOwn(this.$__.activePaths.getStatePaths('modify'), path); if (res || path.indexOf('.') === -1) { return res; } @@ -2450,7 +2450,7 @@ Document.prototype.isInit = function(path) { } if (typeof path === 'string' && path.indexOf(' ') === -1) { - return this.$__.activePaths.getStatePaths('init').hasOwnProperty(path); + return Object.hasOwn(this.$__.activePaths.getStatePaths('init'), path); } let paths = path; @@ -2458,7 +2458,7 @@ Document.prototype.isInit = function(path) { paths = paths.split(' '); } - return paths.some(path => this.$__.activePaths.getStatePaths('init').hasOwnProperty(path)); + return paths.some(path => Object.hasOwn(this.$__.activePaths.getStatePaths('init'), path)); }; /** @@ -2596,7 +2596,7 @@ Document.prototype.isDirectSelected = function isDirectSelected(path) { return true; } - if (this.$__.selected.hasOwnProperty(path)) { + if (Object.hasOwn(this.$__.selected, path)) { return inclusive; } @@ -2772,7 +2772,7 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate if (doc.$isModified(fullPathToSubdoc, null, modifiedPaths) && // Avoid using isDirectModified() here because that does additional checks on whether the parent path // is direct modified, which can cause performance issues re: gh-14897 - !subdocParent.$__.activePaths.getStatePaths('modify').hasOwnProperty(fullPathToSubdoc) && + !Object.hasOwn(subdocParent.$__.activePaths.getStatePaths('modify'), fullPathToSubdoc) && !subdocParent.$isDefault(fullPathToSubdoc)) { paths.add(fullPathToSubdoc); @@ -2843,7 +2843,12 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip, isNestedValidate // Single nested paths (paths embedded under single nested subdocs) will // be validated on their own when we call `validate()` on the subdoc itself. // Re: gh-8468 - Object.keys(flat).filter(path => !doc.$__schema.singleNestedPaths.hasOwnProperty(path)).forEach(addToPaths); + const singleNestedPaths = doc.$__schema.singleNestedPaths; + for (const path of Object.keys(flat)) { + if (!Object.hasOwn(singleNestedPaths, path)) { + addToPaths(path); + } + } } } @@ -4184,7 +4189,7 @@ function applyVirtuals(self, json, options, toObjectOptions) { } // Allow skipping aliases with `toObject({ virtuals: true, aliases: false })` - if (!aliases && schema.aliases.hasOwnProperty(path)) { + if (!aliases && Object.hasOwn(schema.aliases, path)) { continue; } @@ -5097,7 +5102,7 @@ function checkDivergentArray(doc, path, array) { // would be similarly destructive as we never received all // elements of the array and potentially would overwrite data. const check = pop.options.match || - pop.options.options && utils.object.hasOwnProperty(pop.options.options, 'limit') || // 0 is not permitted + pop.options.options && Object.hasOwn(pop.options.options, 'limit') || // 0 is not permitted pop.options.options && pop.options.options.skip || // 0 is permitted pop.options.select && // deselected _id? (pop.options.select._id === 0 || diff --git a/lib/drivers/node-mongodb-native/connection.js b/lib/drivers/node-mongodb-native/connection.js index e45d22b0a08..c6108473df4 100644 --- a/lib/drivers/node-mongodb-native/connection.js +++ b/lib/drivers/node-mongodb-native/connection.js @@ -108,7 +108,7 @@ NativeConnection.prototype.useDb = function(name, options) { function wireup() { newConn.client = _this.client; const _opts = {}; - if (options.hasOwnProperty('noListener')) { + if (Object.hasOwn(options, 'noListener')) { _opts.noListener = options.noListener; } newConn.db = _this.client.db(name, _opts); @@ -515,7 +515,7 @@ function _setClient(conn, client, options, dbName) { conn.onOpen(); for (const i in conn.collections) { - if (utils.object.hasOwnProperty(conn.collections, i)) { + if (Object.hasOwn(conn.collections, i)) { conn.collections[i].onOpen(); } } diff --git a/lib/helpers/common.js b/lib/helpers/common.js index 5a1bee1c313..6b3d878f252 100644 --- a/lib/helpers/common.js +++ b/lib/helpers/common.js @@ -55,7 +55,7 @@ function flatten(update, path, options, schema) { if (isNested) { const paths = Object.keys(schema.paths); for (const p of paths) { - if (p.startsWith(path + key + '.') && !result.hasOwnProperty(p)) { + if (p.startsWith(path + key + '.') && !Object.hasOwn(result, p)) { result[p] = void 0; } } diff --git a/lib/helpers/indexes/applySchemaCollation.js b/lib/helpers/indexes/applySchemaCollation.js index 93a97a48bda..464210e10cf 100644 --- a/lib/helpers/indexes/applySchemaCollation.js +++ b/lib/helpers/indexes/applySchemaCollation.js @@ -7,7 +7,7 @@ module.exports = function applySchemaCollation(indexKeys, indexOptions, schemaOp return; } - if (schemaOptions.hasOwnProperty('collation') && !indexOptions.hasOwnProperty('collation')) { + if (Object.hasOwn(schemaOptions, 'collation') && !Object.hasOwn(indexOptions, 'collation')) { indexOptions.collation = schemaOptions.collation; } }; diff --git a/lib/helpers/indexes/isDefaultIdIndex.js b/lib/helpers/indexes/isDefaultIdIndex.js index 56d74346c6b..8123dfc7d3f 100644 --- a/lib/helpers/indexes/isDefaultIdIndex.js +++ b/lib/helpers/indexes/isDefaultIdIndex.js @@ -14,5 +14,5 @@ module.exports = function isDefaultIdIndex(index) { } const key = get(index, 'key', {}); - return Object.keys(key).length === 1 && key.hasOwnProperty('_id'); + return Object.keys(key).length === 1 && Object.hasOwn(key, '_id'); }; diff --git a/lib/helpers/model/applyMethods.js b/lib/helpers/model/applyMethods.js index e864bb1f12a..f0c0ffb1431 100644 --- a/lib/helpers/model/applyMethods.js +++ b/lib/helpers/model/applyMethods.js @@ -28,7 +28,7 @@ module.exports = function applyMethods(model, schema) { } for (const method of Object.keys(schema.methods)) { const fn = schema.methods[method]; - if (schema.tree.hasOwnProperty(method)) { + if (Object.hasOwn(schema.tree, method)) { throw new Error('You have a method and a property in your schema both ' + 'named "' + method + '"'); } diff --git a/lib/helpers/model/castBulkWrite.js b/lib/helpers/model/castBulkWrite.js index 9dfe292a4a5..b6cdec2a517 100644 --- a/lib/helpers/model/castBulkWrite.js +++ b/lib/helpers/model/castBulkWrite.js @@ -295,7 +295,7 @@ function _addDiscriminatorToObject(schema, obj) { function decideModelByObject(model, object) { const discriminatorKey = model.schema.options.discriminatorKey; - if (object != null && object.hasOwnProperty(discriminatorKey)) { + if (object != null && Object.hasOwn(object, discriminatorKey)) { model = getDiscriminatorByValue(model.discriminators, object[discriminatorKey]) || model; } return model; diff --git a/lib/helpers/populate/getModelsMapForPopulate.js b/lib/helpers/populate/getModelsMapForPopulate.js index f90bd0e8f33..bad3637b3f5 100644 --- a/lib/helpers/populate/getModelsMapForPopulate.js +++ b/lib/helpers/populate/getModelsMapForPopulate.js @@ -386,13 +386,13 @@ function _virtualPopulate(model, docs, options, _virtualRes) { } data.count = virtual.options.count; - if (virtual.options.skip != null && !options.hasOwnProperty('skip')) { + if (virtual.options.skip != null && !Object.hasOwn(options, 'skip')) { options.skip = virtual.options.skip; } - if (virtual.options.limit != null && !options.hasOwnProperty('limit')) { + if (virtual.options.limit != null && !Object.hasOwn(options, 'limit')) { options.limit = virtual.options.limit; } - if (virtual.options.perDocumentLimit != null && !options.hasOwnProperty('perDocumentLimit')) { + if (virtual.options.perDocumentLimit != null && !Object.hasOwn(options, 'perDocumentLimit')) { options.perDocumentLimit = virtual.options.perDocumentLimit; } let foreignField = virtual.options.foreignField; diff --git a/lib/helpers/populate/modelNamesFromRefPath.js b/lib/helpers/populate/modelNamesFromRefPath.js index a5b02859346..875010dccb1 100644 --- a/lib/helpers/populate/modelNamesFromRefPath.js +++ b/lib/helpers/populate/modelNamesFromRefPath.js @@ -56,7 +56,7 @@ module.exports = function modelNamesFromRefPath(refPath, doc, populatedPath, mod const refValue = mpath.get(refPath, doc, lookupLocalFields); let modelNames; - if (modelSchema != null && modelSchema.virtuals.hasOwnProperty(refPath)) { + if (modelSchema != null && Object.hasOwn(modelSchema.virtuals, refPath)) { modelNames = [modelSchema.virtuals[refPath].applyGetters(void 0, doc)]; } else { modelNames = Array.isArray(refValue) ? refValue : [refValue]; diff --git a/lib/helpers/populate/removeDeselectedForeignField.js b/lib/helpers/populate/removeDeselectedForeignField.js index a86e6e3e9f1..069adec7e81 100644 --- a/lib/helpers/populate/removeDeselectedForeignField.js +++ b/lib/helpers/populate/removeDeselectedForeignField.js @@ -16,7 +16,7 @@ module.exports = function removeDeselectedForeignField(foreignFields, options, d return; } for (const foreignField of foreignFields) { - if (!projection.hasOwnProperty('-' + foreignField)) { + if (!Object.hasOwn(projection, '-' + foreignField)) { continue; } diff --git a/lib/helpers/projection/applyProjection.js b/lib/helpers/projection/applyProjection.js index 7a35b128b24..7b8b1a3d772 100644 --- a/lib/helpers/projection/applyProjection.js +++ b/lib/helpers/projection/applyProjection.js @@ -43,7 +43,7 @@ function applyExclusiveProjection(doc, projection, hasIncludedChildren, projecti for (const key of Object.keys(ret)) { const fullPath = prefix ? prefix + '.' + key : key; - if (projection.hasOwnProperty(fullPath) || projectionLimb.hasOwnProperty(key)) { + if (Object.hasOwn(projection, fullPath) || Object.hasOwn(projectionLimb, key)) { if (isPOJO(projection[fullPath]) || isPOJO(projectionLimb[key])) { ret[key] = applyExclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath); } else { @@ -68,7 +68,7 @@ function applyInclusiveProjection(doc, projection, hasIncludedChildren, projecti for (const key of Object.keys(ret)) { const fullPath = prefix ? prefix + '.' + key : key; - if (projection.hasOwnProperty(fullPath) || projectionLimb.hasOwnProperty(key)) { + if (Object.hasOwn(projection, fullPath) || Object.hasOwn(projectionLimb, key)) { if (isPOJO(projection[fullPath]) || isPOJO(projectionLimb[key])) { ret[key] = applyInclusiveProjection(ret[key], projection, hasIncludedChildren, projectionLimb[key], fullPath); } diff --git a/lib/helpers/query/getEmbeddedDiscriminatorPath.js b/lib/helpers/query/getEmbeddedDiscriminatorPath.js index 60bad97f816..0a08bd57653 100644 --- a/lib/helpers/query/getEmbeddedDiscriminatorPath.js +++ b/lib/helpers/query/getEmbeddedDiscriminatorPath.js @@ -71,7 +71,7 @@ module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, p const schemaKey = updatedPathsByFilter[filterKey] + '.' + key; const arrayFilterKey = filterKey + '.' + key; if (schemaKey === discriminatorFilterPath) { - const filter = arrayFilters.find(filter => filter.hasOwnProperty(arrayFilterKey)); + const filter = arrayFilters.find(filter => Object.hasOwn(filter, arrayFilterKey)); if (filter != null) { discriminatorKey = filter[arrayFilterKey]; } diff --git a/lib/helpers/setDefaultsOnInsert.js b/lib/helpers/setDefaultsOnInsert.js index 6c963bc9b69..643ba968f99 100644 --- a/lib/helpers/setDefaultsOnInsert.js +++ b/lib/helpers/setDefaultsOnInsert.js @@ -136,14 +136,14 @@ function pathExistsInUpdate(update, targetPath, pathPieces) { } // Check exact match - if (update.hasOwnProperty(targetPath)) { + if (Object.hasOwn(update, targetPath)) { return true; } // Check if any parent path exists let cur = pathPieces[0]; for (let i = 1; i < pathPieces.length; ++i) { - if (update.hasOwnProperty(cur)) { + if (Object.hasOwn(update, cur)) { return true; } cur += '.' + pathPieces[i]; diff --git a/lib/helpers/timestamps/setupTimestamps.js b/lib/helpers/timestamps/setupTimestamps.js index f6ba12b98b6..ba6f041563e 100644 --- a/lib/helpers/timestamps/setupTimestamps.js +++ b/lib/helpers/timestamps/setupTimestamps.js @@ -23,7 +23,7 @@ module.exports = function setupTimestamps(schema, timestamps) { } const createdAt = handleTimestampOption(timestamps, 'createdAt'); const updatedAt = handleTimestampOption(timestamps, 'updatedAt'); - const currentTime = timestamps != null && timestamps.hasOwnProperty('currentTime') ? + const currentTime = timestamps != null && Object.hasOwn(timestamps, 'currentTime') ? timestamps.currentTime : null; const schemaAdditions = {}; diff --git a/lib/helpers/update/applyTimestampsToUpdate.js b/lib/helpers/update/applyTimestampsToUpdate.js index e8d3217fbb9..240dbe07087 100644 --- a/lib/helpers/update/applyTimestampsToUpdate.js +++ b/lib/helpers/update/applyTimestampsToUpdate.js @@ -74,7 +74,7 @@ function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, optio updates.$set[updatedAt] = now; } - if (updates.hasOwnProperty(updatedAt)) { + if (Object.hasOwn(updates, updatedAt)) { delete updates[updatedAt]; } } diff --git a/lib/helpers/update/decorateUpdateWithVersionKey.js b/lib/helpers/update/decorateUpdateWithVersionKey.js index ee46d8a699f..a982f730ebf 100644 --- a/lib/helpers/update/decorateUpdateWithVersionKey.js +++ b/lib/helpers/update/decorateUpdateWithVersionKey.js @@ -31,5 +31,5 @@ function hasKey(obj, key) { if (obj == null || typeof obj !== 'object') { return false; } - return Object.prototype.hasOwnProperty.call(obj, key); + return Object.hasOwn(obj, key); } diff --git a/lib/model.js b/lib/model.js index e7247344a55..189c8f808b9 100644 --- a/lib/model.js +++ b/lib/model.js @@ -351,7 +351,7 @@ Model.prototype.$__handleSave = function(options, callback) { const asyncLocalStorage = this[modelDbSymbol].base.transactionAsyncLocalStorage?.getStore(); if (session != null) { saveOptions.session = session; - } else if (!options.hasOwnProperty('session') && asyncLocalStorage?.session != null) { + } else if (!Object.hasOwn(options, 'session') && asyncLocalStorage?.session != null) { // Only set session from asyncLocalStorage if `session` option wasn't originally passed in options saveOptions.session = asyncLocalStorage.session; } @@ -615,7 +615,7 @@ Model.prototype.save = async function save(options) { } options = new SaveOptions(options); - if (options.hasOwnProperty('session')) { + if (Object.hasOwn(options, 'session')) { this.$session(options.session); } if (this.$__.timestamps != null) { @@ -780,7 +780,7 @@ Model.prototype.deleteOne = function deleteOne(options) { options = {}; } - if (options.hasOwnProperty('session')) { + if (Object.hasOwn(options, 'session')) { this.$session(options.session); } @@ -3028,7 +3028,7 @@ Model.$__insertMany = function(arr, options, callback) { const lean = !!options.lean; const asyncLocalStorage = this.db.base.transactionAsyncLocalStorage?.getStore(); - if ((!options || !options.hasOwnProperty('session')) && asyncLocalStorage?.session != null) { + if ((!options || !Object.hasOwn(options, 'session')) && asyncLocalStorage?.session != null) { options = { ...options, session: asyncLocalStorage.session }; } @@ -3424,7 +3424,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) { const validations = options?._skipCastBulkWrite ? [] : ops.map(op => castBulkWrite(this, op, options)); const asyncLocalStorage = this.db.base.transactionAsyncLocalStorage?.getStore(); - if ((!options || !options.hasOwnProperty('session')) && asyncLocalStorage?.session != null) { + if ((!options || !Object.hasOwn(options, 'session')) && asyncLocalStorage?.session != null) { options = { ...options, session: asyncLocalStorage.session }; } @@ -5184,10 +5184,10 @@ Model._applyQueryMiddleware = function _applyQueryMiddleware() { function _getContexts(hook) { const ret = {}; - if (hook.hasOwnProperty('query')) { + if (Object.hasOwn(hook, 'query')) { ret.query = hook.query; } - if (hook.hasOwnProperty('document')) { + if (Object.hasOwn(hook, 'document')) { ret.document = hook.document; } return ret; diff --git a/lib/mongoose.js b/lib/mongoose.js index fa57f202cef..b348361fe0c 100644 --- a/lib/mongoose.js +++ b/lib/mongoose.js @@ -600,12 +600,11 @@ Mongoose.prototype.model = function model(name, schema, collection, options) { // connection.model() may be passing a different schema for // an existing model name. in this case don't read from cache. - const overwriteModels = _mongoose.options.hasOwnProperty('overwriteModels') ? + const overwriteModels = Object.hasOwn(_mongoose.options, 'overwriteModels') ? _mongoose.options.overwriteModels : options.overwriteModels; - if (_mongoose.models.hasOwnProperty(name) && options.cache !== false && overwriteModels !== true) { - if (originalSchema && - originalSchema.instanceOfSchema && + if (Object.hasOwn(_mongoose.models, name) && options.cache !== false && overwriteModels !== true) { + if (originalSchema?.instanceOfSchema && originalSchema !== _mongoose.models[name].schema) { throw new _mongoose.Error.OverwriteModelError(name); } diff --git a/lib/query.js b/lib/query.js index 695b947b0f9..5ec664340e7 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2094,7 +2094,7 @@ Query.prototype._optionsForExec = function(model) { applyWriteConcern(model.schema, options); const asyncLocalStorage = this.model?.db?.base.transactionAsyncLocalStorage?.getStore(); - if (!this.options.hasOwnProperty('session') && asyncLocalStorage?.session != null) { + if (!Object.hasOwn(this.options, 'session') && asyncLocalStorage?.session != null) { options.session = asyncLocalStorage.session; } @@ -4590,7 +4590,7 @@ Query.prototype.exec = async function exec(op) { throw new MongooseError('Query has invalid `op`: "' + this.op + '"'); } - if (this.options && this.options.sort && typeof this.options.sort === 'object' && this.options.sort.hasOwnProperty('')) { + if (this.options && this.options.sort && typeof this.options.sort === 'object' && Object.hasOwn(this.options.sort, '')) { throw new Error('Invalid field "" passed to sort()'); } @@ -5039,7 +5039,7 @@ Query.prototype.cast = function(model, obj) { model = model || this.model; const discriminatorKey = model.schema.options.discriminatorKey; if (obj != null && - obj.hasOwnProperty(discriminatorKey)) { + Object.hasOwn(obj, discriminatorKey)) { model = getDiscriminatorByValue(model.discriminators, obj[discriminatorKey]) || model; } diff --git a/lib/schema.js b/lib/schema.js index 47e0412db26..ffb8535ae75 100644 --- a/lib/schema.js +++ b/lib/schema.js @@ -1441,17 +1441,17 @@ Schema.prototype._gatherChildSchemas = function _gatherChildSchemas() { */ function _getPath(schema, path, cleanPath) { - if (schema.paths.hasOwnProperty(path)) { + if (Object.hasOwn(schema.paths, path)) { return schema.paths[path]; } - if (schema.subpaths.hasOwnProperty(cleanPath)) { + if (Object.hasOwn(schema.subpaths, cleanPath)) { const subpath = schema.subpaths[cleanPath]; if (subpath === 'nested') { return undefined; } return subpath; } - if (schema.singleNestedPaths.hasOwnProperty(cleanPath) && typeof schema.singleNestedPaths[cleanPath] === 'object') { + if (Object.hasOwn(schema.singleNestedPaths, cleanPath) && typeof schema.singleNestedPaths[cleanPath] === 'object') { const singleNestedPath = schema.singleNestedPaths[cleanPath]; if (singleNestedPath === 'nested') { return undefined; @@ -1639,20 +1639,20 @@ Schema.prototype.interpretAsType = function(path, obj, options) { childSchemaOptions.typeKey = options.typeKey; } // propagate 'strict' option to child schema - if (options.hasOwnProperty('strict')) { + if (Object.hasOwn(options, 'strict')) { childSchemaOptions.strict = options.strict; } - if (options.hasOwnProperty('strictQuery')) { + if (Object.hasOwn(options, 'strictQuery')) { childSchemaOptions.strictQuery = options.strictQuery; } - if (options.hasOwnProperty('toObject')) { + if (Object.hasOwn(options, 'toObject')) { childSchemaOptions.toObject = utils.omit(options.toObject, ['transform']); } - if (options.hasOwnProperty('toJSON')) { + if (Object.hasOwn(options, 'toJSON')) { childSchemaOptions.toJSON = utils.omit(options.toJSON, ['transform']); } - if (this._userProvidedOptions.hasOwnProperty('_id')) { + if (Object.hasOwn(this._userProvidedOptions, '_id')) { childSchemaOptions._id = this._userProvidedOptions._id; } else if (Schema.Types.DocumentArray.defaultOptions._id != null) { childSchemaOptions._id = Schema.Types.DocumentArray.defaultOptions._id; @@ -1689,7 +1689,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) { `Could not determine the embedded type for array \`${path}\`. ` + 'See https://mongoosejs.com/docs/guide.html#definition for more info on supported schema syntaxes.'); } - if (!MongooseTypes.hasOwnProperty(name)) { + if (!Object.hasOwn(MongooseTypes, name)) { throw new TypeError('Invalid schema configuration: ' + `\`${name}\` is not a valid type within the array \`${path}\`.` + 'See https://bit.ly/mongoose-schematypes for a list of valid schema types.'); @@ -1850,24 +1850,24 @@ Schema.prototype.indexedPaths = function indexedPaths() { */ Schema.prototype.pathType = function(path) { - if (this.paths.hasOwnProperty(path)) { + if (Object.hasOwn(this.paths, path)) { return 'real'; } - if (this.virtuals.hasOwnProperty(path)) { + if (Object.hasOwn(this.virtuals, path)) { return 'virtual'; } - if (this.nested.hasOwnProperty(path)) { + if (Object.hasOwn(this.nested, path)) { return 'nested'; } // Convert to '.$' to check subpaths re: gh-6405 const cleanPath = _pathToPositionalSyntax(path); - if (this.subpaths.hasOwnProperty(cleanPath) || this.subpaths.hasOwnProperty(path)) { + if (Object.hasOwn(this.subpaths, cleanPath) || Object.hasOwn(this.subpaths, path)) { return 'real'; } - const singleNestedPath = this.singleNestedPaths.hasOwnProperty(cleanPath) || this.singleNestedPaths.hasOwnProperty(path); + const singleNestedPath = Object.hasOwn(this.singleNestedPaths, cleanPath) || Object.hasOwn(this.singleNestedPaths, path); if (singleNestedPath) { return singleNestedPath === 'nested' ? 'nested' : 'real'; } @@ -1897,7 +1897,7 @@ Schema.prototype.hasMixedParent = function(path) { path = ''; for (let i = 0; i < subpaths.length; ++i) { path = i > 0 ? path + '.' + subpaths[i] : subpaths[i]; - if (this.paths.hasOwnProperty(path) && + if (Object.hasOwn(this.paths, path) && this.paths[path] instanceof MongooseTypes.Mixed) { return this.paths[path]; } @@ -1926,7 +1926,7 @@ Schema.prototype.setupTimestamp = function(timestamps) { function getPositionalPathType(self, path, cleanPath) { const subpaths = path.split(/\.(\d+)\.|\.(\d+)$/).filter(Boolean); if (subpaths.length < 2) { - return self.paths.hasOwnProperty(subpaths[0]) ? + return Object.hasOwn(self.paths, subpaths[0]) ? self.paths[subpaths[0]] : 'adhocOrUndefined'; } @@ -2633,7 +2633,7 @@ Schema.prototype.virtual = function(name, options) { */ Schema.prototype.virtualpath = function(name) { - return this.virtuals.hasOwnProperty(name) ? this.virtuals[name] : null; + return Object.hasOwn(this.virtuals, name) ? this.virtuals[name] : null; }; /** @@ -2781,8 +2781,8 @@ Schema.prototype.loadClass = function(model, virtualsOnly) { // Stop copying when hit certain base classes if (model === Object.prototype || model === Function.prototype || - model.prototype.hasOwnProperty('$isMongooseModelPrototype') || - model.prototype.hasOwnProperty('$isMongooseDocumentPrototype')) { + Object.hasOwn(model.prototype, '$isMongooseModelPrototype') || + Object.hasOwn(model.prototype, '$isMongooseDocumentPrototype')) { return this; } @@ -2795,7 +2795,7 @@ Schema.prototype.loadClass = function(model, virtualsOnly) { return; } const prop = Object.getOwnPropertyDescriptor(model, name); - if (prop.hasOwnProperty('value')) { + if (Object.hasOwn(prop, 'value')) { this.static(name, prop.value); } }, this); @@ -3021,7 +3021,7 @@ Schema.prototype._transformDuplicateKeyError = function _transformDuplicateKeyEr return error; } const firstKey = keys[0]; - if (!this._duplicateKeyErrorMessagesByPath.hasOwnProperty(firstKey)) { + if (!Object.hasOwn(this._duplicateKeyErrorMessagesByPath, firstKey)) { return error; } return new MongooseError(this._duplicateKeyErrorMessagesByPath[firstKey], { cause: error }); diff --git a/lib/schema/array.js b/lib/schema/array.js index 2edf2f20dc7..4434cf3a792 100644 --- a/lib/schema/array.js +++ b/lib/schema/array.js @@ -81,7 +81,7 @@ function SchemaArray(key, cast, options, schemaOptions, parentSchema) { : utils.getFunctionName(cast); const Types = require('./index.js'); - const caster = Types.hasOwnProperty(name) ? Types[name] : cast; + const caster = Object.hasOwn(Types, name) ? Types[name] : cast; this.casterConstructor = caster; diff --git a/lib/schemaType.js b/lib/schemaType.js index f81e0816225..81f5baaac4b 100644 --- a/lib/schemaType.js +++ b/lib/schemaType.js @@ -47,10 +47,10 @@ function SchemaType(path, options, instance, parentSchema) { this.instance = instance; this.schemaName = this.constructor.schemaName; this.validators = []; - this.getters = this.constructor.hasOwnProperty('getters') ? + this.getters = Object.hasOwn(this.constructor, 'getters') ? this.constructor.getters.slice() : []; - this.setters = this.constructor.hasOwnProperty('setters') ? + this.setters = Object.hasOwn(this.constructor, 'setters') ? this.constructor.setters.slice() : []; @@ -63,7 +63,7 @@ function SchemaType(path, options, instance, parentSchema) { for (const option of defaultOptionsKeys) { if (option === 'validate') { this.validate(defaultOptions.validate); - } else if (defaultOptions.hasOwnProperty(option) && !Object.prototype.hasOwnProperty.call(options, option)) { + } else if (Object.hasOwn(defaultOptions, option) && !Object.hasOwn(options, option)) { options[option] = defaultOptions[option]; } } @@ -340,7 +340,7 @@ SchemaType.prototype.cast = function cast() { */ SchemaType.set = function set(option, value) { - if (!this.hasOwnProperty('defaultOptions')) { + if (!Object.hasOwn(this, 'defaultOptions')) { this.defaultOptions = Object.assign({}, this.defaultOptions); } this.defaultOptions[option] = value; @@ -363,7 +363,7 @@ SchemaType.set = function set(option, value) { */ SchemaType.get = function(getter) { - this.getters = this.hasOwnProperty('getters') ? this.getters : []; + this.getters = Object.hasOwn(this, 'getters') ? this.getters : []; this.getters.push(getter); }; @@ -504,7 +504,7 @@ SchemaType.prototype.unique = function unique(value, message) { 'false and `unique` set to true'); } - if (!this.options.hasOwnProperty('index') && value === false) { + if (!Object.hasOwn(this.options, 'index') && value === false) { return this; } @@ -543,7 +543,7 @@ SchemaType.prototype.text = function(bool) { 'false and `text` set to true'); } - if (!this.options.hasOwnProperty('index') && bool === false) { + if (!Object.hasOwn(this.options, 'index') && bool === false) { return this; } @@ -580,7 +580,7 @@ SchemaType.prototype.sparse = function(bool) { 'false and `sparse` set to true'); } - if (!this.options.hasOwnProperty('index') && bool === false) { + if (!Object.hasOwn(this.options, 'index') && bool === false) { return this; } diff --git a/lib/types/array/index.js b/lib/types/array/index.js index c08dbe6b9c3..1c7fb7b514d 100644 --- a/lib/types/array/index.js +++ b/lib/types/array/index.js @@ -79,13 +79,13 @@ function MongooseArray(values, path, doc, schematype) { const proxy = new Proxy(__array, { get: function(target, prop) { - if (internals.hasOwnProperty(prop)) { + if (Object.hasOwn(internals, prop)) { return internals[prop]; } - if (mongooseArrayMethods.hasOwnProperty(prop)) { + if (Object.hasOwn(mongooseArrayMethods, prop)) { return mongooseArrayMethods[prop]; } - if (schematype && schematype.virtuals && schematype.virtuals.hasOwnProperty(prop)) { + if (schematype && schematype.virtuals && Object.hasOwn(schematype.virtuals, prop)) { return schematype.virtuals[prop].applyGetters(undefined, target); } if (typeof prop === 'string' && numberRE.test(prop) && schematype?.$embeddedSchemaType != null) { @@ -97,9 +97,9 @@ function MongooseArray(values, path, doc, schematype) { set: function(target, prop, value) { if (typeof prop === 'string' && numberRE.test(prop)) { mongooseArrayMethods.set.call(proxy, prop, value, false); - } else if (internals.hasOwnProperty(prop)) { + } else if (Object.hasOwn(internals, prop)) { internals[prop] = value; - } else if (schematype && schematype.virtuals && schematype.virtuals.hasOwnProperty(prop)) { + } else if (schematype?.virtuals && Object.hasOwn(schematype.virtuals, prop)) { schematype.virtuals[prop].applySetters(value, target); } else { __array[prop] = value; diff --git a/lib/types/documentArray/index.js b/lib/types/documentArray/index.js index f43522659c4..a43890d1d7c 100644 --- a/lib/types/documentArray/index.js +++ b/lib/types/documentArray/index.js @@ -73,16 +73,16 @@ function MongooseDocumentArray(values, path, doc, schematype) { prop === 'isMongooseDocumentArrayProxy') { return true; } - if (internals.hasOwnProperty(prop)) { + if (Object.hasOwn(internals, prop)) { return internals[prop]; } - if (DocumentArrayMethods.hasOwnProperty(prop)) { + if (Object.hasOwn(DocumentArrayMethods, prop)) { return DocumentArrayMethods[prop]; } - if (schematype && schematype.virtuals && schematype.virtuals.hasOwnProperty(prop)) { + if (schematype && schematype.virtuals && Object.hasOwn(schematype.virtuals, prop)) { return schematype.virtuals[prop].applyGetters(undefined, target); } - if (ArrayMethods.hasOwnProperty(prop)) { + if (Object.hasOwn(ArrayMethods, prop)) { return ArrayMethods[prop]; } @@ -91,9 +91,9 @@ function MongooseDocumentArray(values, path, doc, schematype) { set: function(target, prop, value) { if (typeof prop === 'string' && numberRE.test(prop)) { DocumentArrayMethods.set.call(proxy, prop, value, false); - } else if (internals.hasOwnProperty(prop)) { + } else if (Object.hasOwn(internals, prop)) { internals[prop] = value; - } else if (schematype && schematype.virtuals && schematype.virtuals.hasOwnProperty(prop)) { + } else if (schematype?.virtuals && Object.hasOwn(schematype.virtuals, prop)) { schematype.virtuals[prop].applySetters(value, target); } else { __array[prop] = value; diff --git a/lib/types/objectid.js b/lib/types/objectid.js index d38c223659b..c66dc40a1a1 100644 --- a/lib/types/objectid.js +++ b/lib/types/objectid.js @@ -30,7 +30,7 @@ Object.defineProperty(ObjectId.prototype, '_id', { * Convenience `valueOf()` to allow comparing ObjectIds using double equals re: gh-7299 */ -if (!ObjectId.prototype.hasOwnProperty('valueOf')) { +if (!Object.hasOwn(ObjectId.prototype, 'valueOf')) { ObjectId.prototype.valueOf = function objectIdValueOf() { return this.toString(); }; diff --git a/lib/utils.js b/lib/utils.js index e0cc40fc94c..7d1af07dae2 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -708,18 +708,6 @@ exports.object.vals = function vals(o) { return ret; }; -const hop = Object.prototype.hasOwnProperty; - -/** - * Safer helper for hasOwnProperty checks - * - * @param {Object} obj - * @param {String} prop - */ - -exports.object.hasOwnProperty = function(obj, prop) { - return hop.call(obj, prop); -}; /** * Determine if `val` is null or undefined @@ -770,8 +758,6 @@ exports.array.flatten = function flatten(arr, filter, ret) { * ignore */ -const _hasOwnProperty = Object.prototype.hasOwnProperty; - exports.hasUserDefinedProperty = function(obj, key) { if (obj == null) { return false; @@ -786,7 +772,7 @@ exports.hasUserDefinedProperty = function(obj, key) { return false; } - if (_hasOwnProperty.call(obj, key)) { + if (Object.hasOwn(obj, key)) { return true; } if (typeof obj === 'object' && key in obj) { diff --git a/lib/virtualType.js b/lib/virtualType.js index 2008ebf8bb4..30cc35d5a8a 100644 --- a/lib/virtualType.js +++ b/lib/virtualType.js @@ -143,7 +143,7 @@ VirtualType.prototype.set = function(fn) { VirtualType.prototype.applyGetters = function(value, doc) { if (utils.hasUserDefinedProperty(this.options, ['ref', 'refPath']) && doc.$$populatedVirtuals && - doc.$$populatedVirtuals.hasOwnProperty(this.path)) { + Object.hasOwn(doc.$$populatedVirtuals, this.path)) { value = doc.$$populatedVirtuals[this.path]; }