Skip to content

Commit d1b9302

Browse files
committed
added exception when an endless loop of recursion is detected and testcases for encoding of temporary objects
1 parent 4d6e2e4 commit d1b9302

File tree

4 files changed

+52
-2
lines changed

4 files changed

+52
-2
lines changed

integration/cloud/main.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,22 @@ Parse.Cloud.job('CloudJob2', function() {
4949
Parse.Cloud.job('CloudJobFailing', function() {
5050
throw 'cloud job failed';
5151
});
52+
53+
//ugly patch. Should not stay here, but I don't know how to test changes in Cloud Code otherwise
54+
//parse-server uses the published parse SDK version, but we want to test the patched version via cloud code
55+
const PatchedParse = require('../../node').Parse;
56+
//FunctionsRouter.js 104 calls Parse._encode directly, so it must be patched.
57+
Parse._encode = PatchedParse._encode;
58+
//Parse.Object calls encode, so it must be patched.
59+
Parse.Object = PatchedParse.Object;
60+
61+
Parse.Cloud.define('getUnsavedObject', function(){
62+
const parent = new Parse.Object("Unsaved");
63+
const child = new Parse.Object("secondUnsaved");
64+
const childOfChild = new Parse.Object("thirdUnsaved");
65+
child.set("foz", "baz");
66+
child.set("child", childOfChild);
67+
parent.set("foo", "bar");
68+
parent.set("child", child);
69+
return parent;
70+
});

integration/test/ParseCloudTest.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,4 +133,15 @@ describe('Parse Cloud', () => {
133133
done();
134134
});
135135
});
136+
137+
it('should transfer unsaved object as full JSON', (done) => {
138+
Parse.Cloud.run('getUnsavedObject').then((result) => {
139+
expect(result).toBeInstanceOf(Parse.Object);
140+
expect(result.get('foo')).toEqual('bar');
141+
expect(result.get('child')).toBeInstanceOf(Parse.Object);
142+
expect(result.get('child').get('child')).toBeInstanceOf(Parse.Object);
143+
expect(result.get('child').get('foz')).toEqual('baz');
144+
done();
145+
}).catch(done.fail);
146+
});
136147
});

src/__tests__/encode-test.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,4 +263,15 @@ describe('encode', () => {
263263
str: 'abc'
264264
});
265265
});
266+
267+
it('should throw an error when recursion is detected in unsaved objects', (done) => {
268+
const parent = new ParseObject('Parent');
269+
const child = new ParseObject('Child');
270+
parent._serverData = {};
271+
child._serverData = {};
272+
parent.attributes = { child : child};
273+
child.attributes = {parent : parent};
274+
expect(function() {encode(parent)}).toThrow("Circular recursion is not allowed on temporary Objects.");
275+
done();
276+
});
266277
});

src/encode.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,18 @@ function encode(value: mixed, disallowObjects: boolean, forcePointers: boolean,
3232
if (offline && value._getId().startsWith('local')) {
3333
return value.toOfflinePointer();
3434
}
35-
if (value.id === undefined){
36-
return value._toFullJSON();
35+
36+
if (value.id === undefined) {
37+
if (value._temp) {
38+
throw new Error("Circular recursion is not allowed on temporary Objects.");
39+
}
40+
if (seen.includes(value)) {
41+
value._temp = true;
42+
}
43+
seen = seen.concat(seenEntry);
44+
return value._toFullJSON(seen, offline);
3745
}
46+
3847
return value.toPointer();
3948
}
4049
seen = seen.concat(seenEntry);

0 commit comments

Comments
 (0)