From 1a030a9f7bf91c79ac065515e5235b33ffeb9e38 Mon Sep 17 00:00:00 2001
From: hasezoey <hasezoey@gmail.com>
Date: Wed, 20 Sep 2023 23:27:50 +0200
Subject: [PATCH 01/15] chore(workflows/test): update deno version to 1.37.x

---
 .github/workflows/test.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f31cc79c56a..edfd7a109a6 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -108,7 +108,7 @@ jobs:
       - name: Setup Deno
         uses: denoland/setup-deno@v1
         with:
-          deno-version: v1.34.x
+          deno-version: v1.37.x
       - run: deno --version
       - run: npm install
       - name: Run Deno tests

From d0121c503dc23626f7068997f82d5fd2c721d160 Mon Sep 17 00:00:00 2001
From: hasezoey <hasezoey@gmail.com>
Date: Tue, 22 Aug 2023 12:40:01 +0200
Subject: [PATCH 02/15] chore(deps-dev): bump mongodb-memory-server from 8.15.1
 to 9.0.0

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index c539bf9f66c..f09d3a6b6a7 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,7 @@
     "mkdirp": "^3.0.1",
     "mocha": "10.2.0",
     "moment": "2.x",
-    "mongodb-memory-server": "8.15.1",
+    "mongodb-memory-server": "9.0.0",
     "ncp": "^2.0.0",
     "nyc": "15.1.0",
     "pug": "3.0.2",

From 925221438a926240e17a6e3af88502343ddbbf66 Mon Sep 17 00:00:00 2001
From: hasezoey <hasezoey@gmail.com>
Date: Tue, 22 Aug 2023 12:41:37 +0200
Subject: [PATCH 03/15] chore(workflows/test): update mongodb versions to their
 latest patch

---
 .github/workflows/test.yml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index edfd7a109a6..0a0a56c2182 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -41,7 +41,7 @@ jobs:
       matrix:
         node: [14, 16, 18, 20]
         os: [ubuntu-20.04, ubuntu-22.04]
-        mongodb: [4.4.18, 5.0.14, 6.0.4]
+        mongodb: [4.4.22, 5.0.19, 6.0.9]
         include:
           - os: ubuntu-20.04 # customize on which matrix the coverage will be collected on
             mongodb: 5.0.14
@@ -49,9 +49,9 @@ jobs:
             coverage: true
         exclude:
           - os: ubuntu-22.04 # exclude because there are no 4.x mongodb builds for 2204
-            mongodb: 4.4.18
+            mongodb: 4.4.22
           - os: ubuntu-22.04 # exclude because there are no 5.x mongodb builds for 2204
-            mongodb: 5.0.14
+            mongodb: 5.0.19
     name: Node ${{ matrix.node }} MongoDB ${{ matrix.mongodb }} OS ${{ matrix.os }}
     env:
       MONGOMS_VERSION: ${{ matrix.mongodb }}
@@ -90,7 +90,7 @@ jobs:
     runs-on: ubuntu-20.04
     name: Deno tests
     env:
-      MONGOMS_VERSION: 6.0.4
+      MONGOMS_VERSION: 6.0.9
       MONGOMS_PREFER_GLOBAL_PATH: 1
       FORCE_COLOR: true
     steps:

From 459b8b517c84957c0d755ff1fcbfe0c19565fe79 Mon Sep 17 00:00:00 2001
From: hasezoey <hasezoey@gmail.com>
Date: Tue, 22 Aug 2023 12:49:28 +0200
Subject: [PATCH 04/15] chore(workflows/test): add mongodb 7.0.0 as test

---
 .github/workflows/test.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 0a0a56c2182..2fd1321f28a 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -41,7 +41,7 @@ jobs:
       matrix:
         node: [14, 16, 18, 20]
         os: [ubuntu-20.04, ubuntu-22.04]
-        mongodb: [4.4.22, 5.0.19, 6.0.9]
+        mongodb: [4.4.22, 5.0.19, 6.0.9, 7.0.0]
         include:
           - os: ubuntu-20.04 # customize on which matrix the coverage will be collected on
             mongodb: 5.0.14

From d8e1f4f2064c9c838c4f43adda70bdf4f29c462b Mon Sep 17 00:00:00 2001
From: hasezoey <hasezoey@gmail.com>
Date: Thu, 21 Sep 2023 12:09:12 +0200
Subject: [PATCH 05/15] test(schema.select.test): clear data before test

---
 test/schema.select.test.js | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/test/schema.select.test.js b/test/schema.select.test.js
index a6a2ae29a32..db133a9ed39 100644
--- a/test/schema.select.test.js
+++ b/test/schema.select.test.js
@@ -26,6 +26,9 @@ describe('schema select option', function() {
   afterEach(() => require('./util').stopRemainingOps(db));
 
   it('excluding paths through schematype', async function() {
+    // data clearing is required for this test, because in deno some other test leaks a "_id: immutable" index
+    await require('./util').clearTestData(db);
+
     const schema = new Schema({
       thin: Boolean,
       name: { type: String, select: false },

From 28ca4f29643c7688d6c273cfa53392e212cda959 Mon Sep 17 00:00:00 2001
From: hasezoey <hasezoey@gmail.com>
Date: Mon, 9 Oct 2023 11:58:18 +0200
Subject: [PATCH 06/15] test(schema.select.test): change the way things are
 dropped

---
 test/schema.select.test.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/schema.select.test.js b/test/schema.select.test.js
index db133a9ed39..dfdd4596926 100644
--- a/test/schema.select.test.js
+++ b/test/schema.select.test.js
@@ -27,7 +27,7 @@ describe('schema select option', function() {
 
   it('excluding paths through schematype', async function() {
     // data clearing is required for this test, because in deno some other test leaks a "_id: immutable" index
-    await require('./util').clearTestData(db);
+    await db.dropDatabase();
 
     const schema = new Schema({
       thin: Boolean,

From 86a8447c8636a57ed9982b71bfefaa8b2929cd79 Mon Sep 17 00:00:00 2001
From: hasezoey <hasezoey@gmail.com>
Date: Fri, 19 Apr 2024 16:12:50 +0200
Subject: [PATCH 07/15] chore(deps-dev): bump mongodb-memory-server from 9.0.0
 to 9.1.8

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index c70ae76814e..708bbd28f49 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
     "mkdirp": "^3.0.1",
     "mocha": "10.2.0",
     "moment": "2.x",
-    "mongodb-memory-server": "9.0.0",
+    "mongodb-memory-server": "9.1.8",
     "ncp": "^2.0.0",
     "nyc": "15.1.0",
     "pug": "3.0.2",

From d6d8e954872b5d904c9c60b212357b8ffd897acf Mon Sep 17 00:00:00 2001
From: hasezoey <hasezoey@gmail.com>
Date: Fri, 19 Apr 2024 16:15:01 +0200
Subject: [PATCH 08/15]  chore(workflows/test): update mongodb versions to
 their latest patch

---
 .github/workflows/test.yml | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 2fd1321f28a..4c7258bf49a 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -41,17 +41,17 @@ jobs:
       matrix:
         node: [14, 16, 18, 20]
         os: [ubuntu-20.04, ubuntu-22.04]
-        mongodb: [4.4.22, 5.0.19, 6.0.9, 7.0.0]
+        mongodb: [4.4.28, 5.0.25, 6.0.14, 7.0.7]
         include:
           - os: ubuntu-20.04 # customize on which matrix the coverage will be collected on
-            mongodb: 5.0.14
+            mongodb: 5.0.25
             node: 16
             coverage: true
         exclude:
           - os: ubuntu-22.04 # exclude because there are no 4.x mongodb builds for 2204
-            mongodb: 4.4.22
+            mongodb: 4.4.28
           - os: ubuntu-22.04 # exclude because there are no 5.x mongodb builds for 2204
-            mongodb: 5.0.19
+            mongodb: 5.0.25
     name: Node ${{ matrix.node }} MongoDB ${{ matrix.mongodb }} OS ${{ matrix.os }}
     env:
       MONGOMS_VERSION: ${{ matrix.mongodb }}
@@ -90,7 +90,7 @@ jobs:
     runs-on: ubuntu-20.04
     name: Deno tests
     env:
-      MONGOMS_VERSION: 6.0.9
+      MONGOMS_VERSION: 6.0.14
       MONGOMS_PREFER_GLOBAL_PATH: 1
       FORCE_COLOR: true
     steps:

From dfc44865095232d556a950375b2b0f4eba25674b Mon Sep 17 00:00:00 2001
From: Valeri Karpov <val@karpov.io>
Date: Mon, 22 Apr 2024 11:22:13 -0400
Subject: [PATCH 09/15] fix(array): avoid converting to `$set` when calling
 `pull()` on an element in the middle of the array

Re: #14502
---
 lib/types/array/methods/index.js | 11 +++++++----
 test/types.array.test.js         | 21 +++++++++++++++++++++
 2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/lib/types/array/methods/index.js b/lib/types/array/methods/index.js
index f192e8c21ea..355b005c96a 100644
--- a/lib/types/array/methods/index.js
+++ b/lib/types/array/methods/index.js
@@ -603,7 +603,10 @@ const methods = {
 
   pull() {
     const values = [].map.call(arguments, (v, i) => this._cast(v, i, { defaults: false }), this);
-    const cur = this[arrayParentSymbol].get(this[arrayPathSymbol]);
+    let cur = this[arrayParentSymbol].get(this[arrayPathSymbol]);
+    if (utils.isMongooseArray(cur)) {
+      cur = cur.__array;
+    }
     let i = cur.length;
     let mem;
     this._markModified();
@@ -615,10 +618,10 @@ const methods = {
           return mem.equals(v);
         });
         if (some) {
-          [].splice.call(cur, i, 1);
+          cur.splice(i, 1);
         }
-      } else if (~cur.indexOf.call(values, mem)) {
-        [].splice.call(cur, i, 1);
+      } else if (~this.indexOf.call(values, mem)) {
+        cur.splice(i, 1);
       }
     }
 
diff --git a/test/types.array.test.js b/test/types.array.test.js
index ccc83e02558..3aea341915c 100644
--- a/test/types.array.test.js
+++ b/test/types.array.test.js
@@ -597,6 +597,27 @@ describe('types array', function() {
       doc.a.pull(cat.id);
       assert.equal(doc.a.length, 0);
 
+      assert.ok(doc.getChanges().$pullAll.a);
+    });
+
+    it('registers $pull atomic if pulling from middle (gh-14502)', async function() {
+      const schema = new Schema({
+        a: [{ type: Schema.ObjectId, ref: 'Cat' }]
+      });
+      const A = db.model('Test', schema);
+
+      const oid1 = new mongoose.Types.ObjectId();
+      const oid2 = new mongoose.Types.ObjectId();
+      const oid3 = new mongoose.Types.ObjectId();
+      const a = new A({ a: [oid1, oid2, oid3] });
+      await a.save();
+
+      const doc = await A.findById(a);
+      assert.equal(doc.a.length, 3);
+      doc.a.pull(oid2);
+      assert.equal(doc.a.length, 2);
+
+      assert.ok(doc.getChanges().$pullAll.a);
     });
 
     it('handles pulling with no _id (gh-3341)', async function() {

From 299828d3d7a447d69fc114c502bd84595ecbf943 Mon Sep 17 00:00:00 2001
From: Valeri Karpov <val@karpov.io>
Date: Mon, 22 Apr 2024 12:31:32 -0400
Subject: [PATCH 10/15] fix(document): make isDirectModified return true if
 path is direct modified in subdoc

Re: #14502
---
 lib/document.js       | 20 ++++++++++++---
 test/document.test.js | 58 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/lib/document.js b/lib/document.js
index d820f2974f5..b8b8ed4360b 100644
--- a/lib/document.js
+++ b/lib/document.js
@@ -2381,15 +2381,29 @@ Document.prototype.isDirectModified = function(path) {
   }
 
   if (typeof path === 'string' && path.indexOf(' ') === -1) {
-    return this.$__.activePaths.getStatePaths('modify').hasOwnProperty(path);
+    const res = this.$__.activePaths.getStatePaths('modify').hasOwnProperty(path);
+    if (res || path.indexOf('.') === -1) {
+      return res;
+    }
+
+    const pieces = path.split('.');
+    for (let i = 0; i < pieces.length - 1; ++i) {
+      const subpath = pieces.slice(0, i + 1).join('.');
+      const subdoc = this.$get(subpath);
+      if (subdoc != null && subdoc.$__ != null && subdoc.isDirectModified(pieces.slice(i + 1).join('.'))) {
+        return true;
+      }
+    }
+
+    return false;
   }
 
   let paths = path;
-  if (!Array.isArray(paths)) {
+  if (typeof paths === 'string') {
     paths = paths.split(' ');
   }
 
-  return paths.some(path => this.$__.activePaths.getStatePaths('modify').hasOwnProperty(path));
+  return paths.some(path => this.isDirectModified(path));
 };
 
 /**
diff --git a/test/document.test.js b/test/document.test.js
index e0d0218b46e..1ea50588c31 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -13055,6 +13055,64 @@ describe('document', function() {
     const obj = parent.toJSON({ getters: true });
     assert.equal(obj.children[0].name, 'Stefan');
   });
+
+  it('isDirectModified on paths underneath direct modified subdoc (gh-14502)', async function() {
+    const JsonFieldSchema = new Schema({
+      fieldA: String,
+      fieldB: String
+    });
+
+    const CommentSchema = new Schema({
+      title: String,
+      body: String,
+      jsonField: JsonFieldSchema
+    });
+
+    const blogPostSchema = new Schema({
+      comment: CommentSchema
+    });
+
+    const Comments = db.model('Comments', CommentSchema);
+    const BlogPost = db.model('BlogPost', blogPostSchema);
+
+    const comment1 = new Comments({});
+    comment1.init({
+      title: 'Test',
+      body: 'Test',
+      jsonField: {
+        fieldA: 'field A',
+        fieldB: 'field B'
+      }
+    });
+
+    const update = {
+      title: 'New test',
+      jsonField: {
+        fieldA: 'new Field A'
+      }
+    };
+    Object.assign(comment1, { ...update });
+
+    assert.ok(comment1.isDirectModified('jsonField.fieldA'));
+    assert.ok(comment1.jsonField.isDirectModified('fieldA'));
+
+    const blogPost = new BlogPost({});
+    blogPost.init({
+      comment: {
+        title: 'Test',
+        body: 'Test',
+        jsonField: {
+          fieldA: 'field A',
+          fieldB: 'field B'
+        }
+      }
+    });
+
+    Object.assign(blogPost.comment, { ...update });
+
+    assert.ok(blogPost.isDirectModified('comment.jsonField.fieldA'));
+    assert.ok(blogPost.comment.jsonField.isDirectModified('fieldA'));
+  });
 });
 
 describe('Check if instance function that is supplied in schema option is availabe', function() {

From cadcf383fc67edd376e9fdd60e6fcaf90feb6fc7 Mon Sep 17 00:00:00 2001
From: Valeri Karpov <val@karpov.io>
Date: Thu, 25 Apr 2024 12:24:31 -0400
Subject: [PATCH 11/15] Update test/document.test.js

Co-authored-by: hasezoey <hasezoey@gmail.com>
---
 test/document.test.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/document.test.js b/test/document.test.js
index 1ea50588c31..017845b8de2 100644
--- a/test/document.test.js
+++ b/test/document.test.js
@@ -13068,12 +13068,12 @@ describe('document', function() {
       jsonField: JsonFieldSchema
     });
 
-    const blogPostSchema = new Schema({
+    const BlogPostSchema = new Schema({
       comment: CommentSchema
     });
 
     const Comments = db.model('Comments', CommentSchema);
-    const BlogPost = db.model('BlogPost', blogPostSchema);
+    const BlogPost = db.model('BlogPost', BlogPostSchema);
 
     const comment1 = new Comments({});
     comment1.init({

From c4c7414fcddbbb60b2fa525c6d72fd13e8ed060d Mon Sep 17 00:00:00 2001
From: Lorand Horvath <72015221+lorand-horvath@users.noreply.github.com>
Date: Fri, 3 May 2024 19:28:36 +0300
Subject: [PATCH 12/15] Bump mongodb driver to 5.9.2

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index dcd3039fa3c..115d1cb94c8 100644
--- a/package.json
+++ b/package.json
@@ -21,7 +21,7 @@
   "dependencies": {
     "bson": "^5.5.0",
     "kareem": "2.5.1",
-    "mongodb": "5.9.1",
+    "mongodb": "5.9.2",
     "mpath": "0.9.0",
     "mquery": "5.0.0",
     "ms": "2.1.3",

From de052048dc5c7e126bba5e16a070383018b447cd Mon Sep 17 00:00:00 2001
From: hasezoey <hasezoey@gmail.com>
Date: Sat, 11 May 2024 17:37:35 +0200
Subject: [PATCH 13/15] chore(deps-dev): bump mongodb-memory-server from 9.1.8
 to 9.2.0

---
 package.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 708bbd28f49..72a4952d0d2 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
     "mkdirp": "^3.0.1",
     "mocha": "10.2.0",
     "moment": "2.x",
-    "mongodb-memory-server": "9.1.8",
+    "mongodb-memory-server": "9.2.0",
     "ncp": "^2.0.0",
     "nyc": "15.1.0",
     "pug": "3.0.2",

From 4f5641f3ac8744f47c77e85042ceec665ccdd551 Mon Sep 17 00:00:00 2001
From: Valeri Karpov <val@karpov.io>
Date: Sat, 18 May 2024 07:02:59 -0400
Subject: [PATCH 14/15] fix(update): cast array of strings underneath doc array
 with array filters

Fix #14595
---
 lib/schema.js                                |  4 +++
 test/helpers/update.castArrayFilters.test.js | 38 ++++++++++++++++++++
 2 files changed, 42 insertions(+)

diff --git a/lib/schema.js b/lib/schema.js
index cc704d2f12d..7e7004823fa 100644
--- a/lib/schema.js
+++ b/lib/schema.js
@@ -2584,6 +2584,10 @@ Schema.prototype._getSchema = function(path) {
           // If there is no foundschema.schema we are dealing with
           // a path like array.$
           if (p !== parts.length) {
+            if (p + 1 === parts.length && foundschema.$embeddedSchemaType && (parts[p] === '$' || isArrayFilter(parts[p]))) {
+              return foundschema.$embeddedSchemaType;
+            }
+
             if (foundschema.schema) {
               let ret;
               if (parts[p] === '$' || isArrayFilter(parts[p])) {
diff --git a/test/helpers/update.castArrayFilters.test.js b/test/helpers/update.castArrayFilters.test.js
index d132663b590..0db3c031c9d 100644
--- a/test/helpers/update.castArrayFilters.test.js
+++ b/test/helpers/update.castArrayFilters.test.js
@@ -311,4 +311,42 @@ describe('castArrayFilters', function() {
 
     assert.strictEqual(q.options.arrayFilters[0]['element.number'], 1);
   });
+
+  it('correctly casts array of strings underneath doc array (gh-12565)', function() {
+    const userSchema = new Schema({
+      groups: [{
+        document: 'ObjectId',
+        tags: [String]
+      }]
+    });
+
+    const q = new Query();
+    q.schema = userSchema;
+
+    const groupId = new Types.ObjectId();
+    const filter = {
+      groups: {
+        $elemMatch: {
+          document: groupId,
+          tags: 'tag-to-update'
+        }
+      }
+    };
+    const update = {
+      $set: {
+        'groups.$[group].tags.$[tag]': 42
+      }
+    };
+    const opts = {
+      arrayFilters: [
+        { 'group.document': groupId },
+        { tag: { $eq: 'tag-to-update' } }
+      ]
+    };
+    q.updateOne(filter, update, opts);
+    castArrayFilters(q);
+    q._update = q._castUpdate(q._update, false);
+
+    assert.strictEqual(q.getUpdate().$set['groups.$[group].tags.$[tag]'], '42');
+  });
 });

From 32f1ee1962cda1ef7f9f9dbfe0f05b1d7bb25767 Mon Sep 17 00:00:00 2001
From: Valeri Karpov <val@karpov.io>
Date: Tue, 21 May 2024 15:39:56 -0400
Subject: [PATCH 15/15] chore: release 7.6.12

---
 CHANGELOG.md | 6 ++++++
 package.json | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e3805188d97..76916f787df 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,9 @@
+7.6.12 / 2024-05-21
+===================
+ * fix(array): avoid converting to $set when calling pull() on an element in the middle of the array #14531 #14502
+ * fix: bump mongodb driver to 5.9.2 #14561 [lorand-horvath](https://github.com/lorand-horvath)
+ * fix(update): cast array of strings underneath doc array with array filters #14605 #14595
+
 7.6.11 / 2024-04-11
 ===================
  * fix(populate): avoid match function filtering out null values in populate result #14518
diff --git a/package.json b/package.json
index 8407f41ab09..14eac926273 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
   "name": "mongoose",
   "description": "Mongoose MongoDB ODM",
-  "version": "7.6.11",
+  "version": "7.6.12",
   "author": "Guillermo Rauch <guillermo@learnboost.com>",
   "keywords": [
     "mongodb",