Skip to content

Commit

Permalink
added exception when an endless loop of recursion is detected and tes…
Browse files Browse the repository at this point in the history
…tcases for encoding of temporary objects
  • Loading branch information
fastrde committed Nov 25, 2020
1 parent 4d6e2e4 commit d1b9302
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 2 deletions.
19 changes: 19 additions & 0 deletions integration/cloud/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,22 @@ Parse.Cloud.job('CloudJob2', function() {
Parse.Cloud.job('CloudJobFailing', function() {
throw 'cloud job failed';
});

//ugly patch. Should not stay here, but I don't know how to test changes in Cloud Code otherwise
//parse-server uses the published parse SDK version, but we want to test the patched version via cloud code
const PatchedParse = require('../../node').Parse;
//FunctionsRouter.js 104 calls Parse._encode directly, so it must be patched.
Parse._encode = PatchedParse._encode;
//Parse.Object calls encode, so it must be patched.
Parse.Object = PatchedParse.Object;

Parse.Cloud.define('getUnsavedObject', function(){
const parent = new Parse.Object("Unsaved");
const child = new Parse.Object("secondUnsaved");
const childOfChild = new Parse.Object("thirdUnsaved");
child.set("foz", "baz");
child.set("child", childOfChild);
parent.set("foo", "bar");
parent.set("child", child);
return parent;
});
11 changes: 11 additions & 0 deletions integration/test/ParseCloudTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,15 @@ describe('Parse Cloud', () => {
done();
});
});

it('should transfer unsaved object as full JSON', (done) => {
Parse.Cloud.run('getUnsavedObject').then((result) => {
expect(result).toBeInstanceOf(Parse.Object);
expect(result.get('foo')).toEqual('bar');
expect(result.get('child')).toBeInstanceOf(Parse.Object);
expect(result.get('child').get('child')).toBeInstanceOf(Parse.Object);
expect(result.get('child').get('foz')).toEqual('baz');
done();
}).catch(done.fail);
});
});
11 changes: 11 additions & 0 deletions src/__tests__/encode-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,4 +263,15 @@ describe('encode', () => {
str: 'abc'
});
});

it('should throw an error when recursion is detected in unsaved objects', (done) => {
const parent = new ParseObject('Parent');
const child = new ParseObject('Child');
parent._serverData = {};
child._serverData = {};
parent.attributes = { child : child};
child.attributes = {parent : parent};
expect(function() {encode(parent)}).toThrow("Circular recursion is not allowed on temporary Objects.");
done();
});
});
13 changes: 11 additions & 2 deletions src/encode.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,18 @@ function encode(value: mixed, disallowObjects: boolean, forcePointers: boolean,
if (offline && value._getId().startsWith('local')) {
return value.toOfflinePointer();
}
if (value.id === undefined){
return value._toFullJSON();

if (value.id === undefined) {
if (value._temp) {
throw new Error("Circular recursion is not allowed on temporary Objects.");
}
if (seen.includes(value)) {
value._temp = true;
}
seen = seen.concat(seenEntry);
return value._toFullJSON(seen, offline);
}

return value.toPointer();
}
seen = seen.concat(seenEntry);
Expand Down

0 comments on commit d1b9302

Please sign in to comment.