From 4e1a0daa8690e1f1cf35ac0525b1935ebe95797f Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 3 Oct 2022 13:28:11 +1100 Subject: [PATCH 1/9] fix: properly encode nested objects --- spec/MongoStorageAdapter.spec.js | 38 ++++++++++++++++++++ src/Adapters/Storage/Mongo/MongoTransform.js | 10 ++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/spec/MongoStorageAdapter.spec.js b/spec/MongoStorageAdapter.spec.js index 68c56da15d..caf67c6918 100644 --- a/spec/MongoStorageAdapter.spec.js +++ b/spec/MongoStorageAdapter.spec.js @@ -213,6 +213,44 @@ describe_only_db('mongo')('MongoStorageAdapter', () => { }); }); + it('handles nested dates', async () => { + await new Parse.Object('MyClass', { + foo: { + test: { + date: new Date(), + }, + }, + bar: { + date: new Date(), + }, + date: new Date(), + }).save(); + const adapter = Config.get(Parse.applicationId).database.adapter; + const [object] = await adapter._rawFind('MyClass', {}); + expect(object.date instanceof Date).toBeTrue(); + expect(object.bar.date instanceof Date).toBeTrue(); + expect(object.foo.test.date instanceof Date).toBeTrue(); + }); + + it('handles nested dates in array ', async () => { + await new Parse.Object('MyClass', { + foo: { + test: { + date: [new Date()], + }, + }, + bar: { + date: [new Date()], + }, + date: [new Date()], + }).save(); + const adapter = Config.get(Parse.applicationId).database.adapter; + const [object] = await adapter._rawFind('MyClass', {}); + expect(object.date[0] instanceof Date).toBeTrue(); + expect(object.bar.date[0] instanceof Date).toBeTrue(); + expect(object.foo.test.date[0] instanceof Date).toBeTrue(); + }); + it('handles updating a single object with array, object date', done => { const adapter = new MongoStorageAdapter({ uri: databaseURI }); diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 91ad23fa4a..d0e9f2e507 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -1012,9 +1012,15 @@ function transformUpdateOperator({ __op, amount, objects }, flatten) { } function mapValues(object, iterator) { const result = {}; - Object.keys(object).forEach(key => { + for (const key in object) { result[key] = iterator(object[key]); - }); + if (result[key] instanceof Date) { + continue; + } + if (Array.isArray(result[key]) || Object.prototype.toString.call(result[key]) === '[object Object]') { + result[key] = mapValues(object[key], iterator); + } + } return result; } From ada0cd897f0e39de04da3a63436f7e6ac4d513bb Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 3 Oct 2022 14:27:29 +1100 Subject: [PATCH 2/9] Update MongoTransform.js --- src/Adapters/Storage/Mongo/MongoTransform.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index d0e9f2e507..ea93e2057e 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -1017,7 +1017,8 @@ function mapValues(object, iterator) { if (result[key] instanceof Date) { continue; } - if (Array.isArray(result[key]) || Object.prototype.toString.call(result[key]) === '[object Object]') { + const encodeArray = Array.isArray(result[key]) ? result[key].some(row => Object.prototype.toString.call(row) === '[object Object]') : false; + if (encodeArray || Object.prototype.toString.call(result[key]) === '[object Object]') { result[key] = mapValues(object[key], iterator); } } From a02c95d906197336c4bdd1682c8808bafd98855b Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 3 Oct 2022 14:40:53 +1100 Subject: [PATCH 3/9] Update MongoTransform.js --- src/Adapters/Storage/Mongo/MongoTransform.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index ea93e2057e..5811794336 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -1014,11 +1014,7 @@ function mapValues(object, iterator) { const result = {}; for (const key in object) { result[key] = iterator(object[key]); - if (result[key] instanceof Date) { - continue; - } - const encodeArray = Array.isArray(result[key]) ? result[key].some(row => Object.prototype.toString.call(row) === '[object Object]') : false; - if (encodeArray || Object.prototype.toString.call(result[key]) === '[object Object]') { + if (JSON.stringify(result[key]).includes('__type') && (Array.isArray(result[key]) || Object.prototype.toString.call(result[key]) === '[object Object]')) { result[key] = mapValues(object[key], iterator); } } From fef839c077133ae33b9f219c4c6414f1491968e2 Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 3 Oct 2022 14:53:50 +1100 Subject: [PATCH 4/9] Update MongoTransform.js --- src/Adapters/Storage/Mongo/MongoTransform.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 5811794336..2a8475a053 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -1014,7 +1014,11 @@ function mapValues(object, iterator) { const result = {}; for (const key in object) { result[key] = iterator(object[key]); - if (JSON.stringify(result[key]).includes('__type') && (Array.isArray(result[key]) || Object.prototype.toString.call(result[key]) === '[object Object]')) { + if ( + result[key] && + JSON.stringify(result[key]).includes('__type') && + (Array.isArray(result[key]) || Object.prototype.toString.call(result[key]) === '[object Object]') + ) { result[key] = mapValues(object[key], iterator); } } From ffe2eff208040596f58500b1e619f9c0f66a3308 Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 3 Oct 2022 15:06:48 +1100 Subject: [PATCH 5/9] Update ParseQuery.hint.spec.js --- spec/ParseQuery.hint.spec.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/ParseQuery.hint.spec.js b/spec/ParseQuery.hint.spec.js index db45106359..aba9a4ceb1 100644 --- a/spec/ParseQuery.hint.spec.js +++ b/spec/ParseQuery.hint.spec.js @@ -409,6 +409,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { }); it_only_mongodb_version('>=5.2')('query aggregate with hint (rest)', async () => { + try { const object = new TestObject({ foo: 'bar' }); await object.save(); let options = Object.assign({}, masterKeyOptions, { @@ -439,5 +440,9 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); + } catch (e) { + console.log(e); + throw e; + } }); }); From 8109d302d400b17054388b11789586f0decd93ee Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 3 Oct 2022 15:18:28 +1100 Subject: [PATCH 6/9] tests --- spec/ParseQuery.hint.spec.js | 4 ++-- src/Adapters/Storage/Mongo/MongoTransform.js | 6 +----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/spec/ParseQuery.hint.spec.js b/spec/ParseQuery.hint.spec.js index aba9a4ceb1..15644dae2b 100644 --- a/spec/ParseQuery.hint.spec.js +++ b/spec/ParseQuery.hint.spec.js @@ -408,7 +408,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); }); - it_only_mongodb_version('>=5.2')('query aggregate with hint (rest)', async () => { + fit_only_mongodb_version('>=5.2')('query aggregate with hint (rest)', async () => { try { const object = new TestObject({ foo: 'bar' }); await object.save(); @@ -441,7 +441,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); } catch (e) { - console.log(e); + console.log(e.text); throw e; } }); diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 2a8475a053..29a4a8c9d4 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -1014,11 +1014,7 @@ function mapValues(object, iterator) { const result = {}; for (const key in object) { result[key] = iterator(object[key]); - if ( - result[key] && - JSON.stringify(result[key]).includes('__type') && - (Array.isArray(result[key]) || Object.prototype.toString.call(result[key]) === '[object Object]') - ) { + if (result[key] && JSON.stringify(result[key]).includes(`"__type"`)) { result[key] = mapValues(object[key], iterator); } } From 976bbead0b6aec284900fc27d69e2607b654107d Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 3 Oct 2022 15:24:21 +1100 Subject: [PATCH 7/9] Update ParseQuery.hint.spec.js --- spec/ParseQuery.hint.spec.js | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/ParseQuery.hint.spec.js b/spec/ParseQuery.hint.spec.js index 15644dae2b..5324bd5782 100644 --- a/spec/ParseQuery.hint.spec.js +++ b/spec/ParseQuery.hint.spec.js @@ -410,6 +410,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { fit_only_mongodb_version('>=5.2')('query aggregate with hint (rest)', async () => { try { + await reconfigureServer({silent: false}); const object = new TestObject({ foo: 'bar' }); await object.save(); let options = Object.assign({}, masterKeyOptions, { From ed9899b629c252e974e886c26a348a0cabbddf76 Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 3 Oct 2022 15:33:09 +1100 Subject: [PATCH 8/9] Update MongoTransform.js --- src/Adapters/Storage/Mongo/MongoTransform.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Adapters/Storage/Mongo/MongoTransform.js b/src/Adapters/Storage/Mongo/MongoTransform.js index 29a4a8c9d4..aabf744978 100644 --- a/src/Adapters/Storage/Mongo/MongoTransform.js +++ b/src/Adapters/Storage/Mongo/MongoTransform.js @@ -1012,12 +1012,12 @@ function transformUpdateOperator({ __op, amount, objects }, flatten) { } function mapValues(object, iterator) { const result = {}; - for (const key in object) { + Object.keys(object).forEach(key => { result[key] = iterator(object[key]); if (result[key] && JSON.stringify(result[key]).includes(`"__type"`)) { result[key] = mapValues(object[key], iterator); } - } + }); return result; } From 4343d933ade258031432b42c9390baed8cd67fa0 Mon Sep 17 00:00:00 2001 From: dblythy Date: Mon, 3 Oct 2022 15:36:39 +1100 Subject: [PATCH 9/9] Update ParseQuery.hint.spec.js --- spec/ParseQuery.hint.spec.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/spec/ParseQuery.hint.spec.js b/spec/ParseQuery.hint.spec.js index 5324bd5782..db45106359 100644 --- a/spec/ParseQuery.hint.spec.js +++ b/spec/ParseQuery.hint.spec.js @@ -408,9 +408,7 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); }); - fit_only_mongodb_version('>=5.2')('query aggregate with hint (rest)', async () => { - try { - await reconfigureServer({silent: false}); + it_only_mongodb_version('>=5.2')('query aggregate with hint (rest)', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); let options = Object.assign({}, masterKeyOptions, { @@ -441,9 +439,5 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.stage).toBe('IXSCAN'); expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.indexName).toBe('_id_'); expect(queryPlanner.winningPlan.queryPlan.inputStage.inputStage.keyPattern).toEqual({ _id: 1 }); - } catch (e) { - console.log(e.text); - throw e; - } }); });