Skip to content

Commit 6ed3385

Browse files
authored
Merge pull request #14395 from Automattic/vkarpov15/gh-14353
fix(document): make `$clone` avoid converting subdocs into POJOs
2 parents c5e9de6 + 30e9f5b commit 6ed3385

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

lib/document.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -4735,7 +4735,7 @@ Document.prototype.$clone = function() {
47354735
const clonedDoc = new Model();
47364736
clonedDoc.$isNew = this.$isNew;
47374737
if (this._doc) {
4738-
clonedDoc._doc = clone(this._doc);
4738+
clonedDoc._doc = clone(this._doc, { retainDocuments: true });
47394739
}
47404740
if (this.$__) {
47414741
const Cache = this.$__.constructor;

lib/helpers/clone.js

+17-4
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,23 @@ function clone(obj, options, isArrayChild) {
3636
}
3737

3838
if (isMongooseObject(obj)) {
39-
// Single nested subdocs should apply getters later in `applyGetters()`
40-
// when calling `toObject()`. See gh-7442, gh-8295
41-
if (options && options._skipSingleNestedGetters && obj.$isSingleNested) {
42-
options = Object.assign({}, options, { getters: false });
39+
if (options) {
40+
// Single nested subdocs should apply getters later in `applyGetters()`
41+
// when calling `toObject()`. See gh-7442, gh-8295
42+
if (options._skipSingleNestedGetters && obj.$isSingleNested) {
43+
options = Object.assign({}, options, { getters: false });
44+
}
45+
if (options.retainDocuments && obj.$__ != null) {
46+
const clonedDoc = obj.$clone();
47+
if (obj.__index != null) {
48+
clonedDoc.__index = obj.__index;
49+
}
50+
if (obj.__parentArray != null) {
51+
clonedDoc.__parentArray = obj.__parentArray;
52+
}
53+
clonedDoc.$__parent = obj.$__parent;
54+
return clonedDoc;
55+
}
4356
}
4457
const isSingleNested = obj.$isSingleNested;
4558

test/document.test.js

+21
Original file line numberDiff line numberDiff line change
@@ -12070,6 +12070,27 @@ describe('document', function() {
1207012070
assert.strictEqual(clonedDoc.$session(), session);
1207112071
});
1207212072

12073+
it('$clone() with single nested and doc array (gh-14353) (gh-11849)', async function() {
12074+
const schema = new mongoose.Schema({
12075+
subdocArray: [{
12076+
name: String
12077+
}],
12078+
subdoc: new mongoose.Schema({ name: String })
12079+
});
12080+
const Test = db.model('Test', schema);
12081+
12082+
const item = await Test.create({ subdocArray: [{ name: 'test 1' }], subdoc: { name: 'test 2' } });
12083+
12084+
const doc = await Test.findById(item._id);
12085+
const clonedDoc = doc.$clone();
12086+
12087+
assert.ok(clonedDoc.subdocArray[0].$__);
12088+
assert.ok(clonedDoc.subdoc.$__);
12089+
12090+
assert.deepEqual(doc.subdocArray[0], clonedDoc.subdocArray[0]);
12091+
assert.deepEqual(doc.subdoc, clonedDoc.subdoc);
12092+
});
12093+
1207312094
it('can create document with document array and top-level key named `schema` (gh-12480)', async function() {
1207412095
const AuthorSchema = new Schema({
1207512096
fullName: { type: 'String', required: true }

0 commit comments

Comments
 (0)