From cc70256d4149a9835143ad7566c01db71978e9f1 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Fri, 13 Nov 2020 17:17:12 -0500 Subject: [PATCH] fix(array): make sure `Array#toObject()` returns a vanilla JavaScript array in Node.js 6+ Fix #9540 --- lib/types/core_array.js | 6 ++++-- test/types.array.test.js | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/lib/types/core_array.js b/lib/types/core_array.js index 954df521cc7..15d90978f66 100644 --- a/lib/types/core_array.js +++ b/lib/types/core_array.js @@ -869,14 +869,16 @@ class CoreMongooseArray extends Array { if (options && options.depopulate) { options = utils.clone(options); options._isNested = true; - return this.map(function(doc) { + // Ensure return value is a vanilla array, because in Node.js 6+ `map()` + // is smart enough to use the inherited array's constructor. + return [].concat(this).map(function(doc) { return doc instanceof Document ? doc.toObject(options) : doc; }); } - return this.slice(); + return [].concat(this); } /** diff --git a/test/types.array.test.js b/test/types.array.test.js index f2f8aeacee4..dfb8f145ad9 100644 --- a/test/types.array.test.js +++ b/test/types.array.test.js @@ -379,12 +379,12 @@ describe('types array', function() { const removed = doc.numbers.splice(1, 1, '10'); assert.deepEqual(removed, [5]); assert.equal(typeof doc.numbers[1], 'number'); - assert.deepEqual(doc.numbers.toObject(), [4, 10, 6, 7]); + assert.deepStrictEqual(doc.numbers.toObject(), [4, 10, 6, 7]); doc.save(function(err) { assert.ifError(err); A.findById(a._id, function(err, doc) { assert.ifError(err); - assert.deepEqual(doc.numbers.toObject(), [4, 10, 6, 7]); + assert.deepStrictEqual(doc.numbers.toObject(), [4, 10, 6, 7]); A.collection.drop(function(err) { assert.ifError(err); @@ -1828,6 +1828,23 @@ describe('types array', function() { }); }); + it('toObject returns a vanilla JavaScript array (gh-9540)', function() { + const schema = new Schema({ arr: [Number] }); + const M = db.model('Test', schema); + + const doc = new M({ arr: [1, 2, 3] }); + + let arr = doc.arr.toObject(); + assert.ok(Array.isArray(arr)); + assert.equal(arr.constructor, Array); + assert.deepStrictEqual(arr, [1, 2, 3]); + + arr = doc.arr.toObject({ depopulate: true }); + assert.ok(Array.isArray(arr)); + assert.equal(arr.constructor, Array); + assert.deepStrictEqual(arr, [1, 2, 3]); + }); + it('pushing top level arrays and subarrays works (gh-1073)', function(done) { const schema = new Schema({ em: [new Schema({ sub: [String] })] }); const M = db.model('Test', schema);