Skip to content

Commit 782cbfe

Browse files
leeyehwangxiao
authored andcommitted
fix AV.Object.extend SO error and support ES6 extends syntax (#352)
* fix(Object): return OldClassObject when extend Class with className only fix stack overflow when calling AV.Object.extend('className') multiple times. * feat(Object): support ES6 extends syntax * test(Promise): run promise tests last fix broken tests in browsers
1 parent 228bc9b commit 782cbfe

File tree

4 files changed

+71
-52
lines changed

4 files changed

+71
-52
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"eslint-plugin-import": "^1.6.0",
2929
"eslint-plugin-jsx-a11y": "^1.0.3",
3030
"eslint-plugin-react": "^5.0.1",
31-
"expect.js": "0.2.0",
31+
"expect.js": "^0.3.0",
3232
"gulp": "^3.8.10",
3333
"gulp-babel": "^6.1.1",
3434
"gulp-clean": "^0.3.1",
@@ -44,7 +44,7 @@
4444
"gulp-sourcemaps": "^1.6.0",
4545
"gulp-tar": "^1.3.2",
4646
"gulp-uglify": "^1.0.2",
47-
"mocha": "2.4.5",
47+
"mocha": "^3.0.0",
4848
"vinyl-source-stream": "^1.1.0"
4949
},
5050
"license": "MIT",

src/object.js

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,10 +1422,14 @@ module.exports = function(AV) {
14221422
// This new subclass has been told to extend both from "this" and from
14231423
// OldClassObject. This is multiple inheritance, which isn't supported.
14241424
// For now, let's just pick one.
1425-
NewClassObject = OldClassObject._extend(protoProps, classProps);
1425+
if (protoProps || classProps) {
1426+
NewClassObject = OldClassObject._extend(protoProps, classProps);
1427+
} else {
1428+
return OldClassObject;
1429+
}
14261430
} else {
14271431
protoProps = protoProps || {};
1428-
protoProps.className = className;
1432+
protoProps._className = className;
14291433
NewClassObject = this._extend(protoProps, classProps);
14301434
}
14311435
// Extending a subclass should reuse the classname automatically.
@@ -1443,6 +1447,29 @@ module.exports = function(AV) {
14431447
return NewClassObject;
14441448
};
14451449

1450+
// ES6 class syntax support
1451+
Object.defineProperty(AV.Object.prototype, 'className', {
1452+
get: function(){
1453+
const className = this._className || this.constructor.name;
1454+
// If someone tries to subclass "User", coerce it to the right type.
1455+
if (className === "User") {
1456+
return "_User";
1457+
}
1458+
return className;
1459+
},
1460+
});
1461+
1462+
AV.Object.register = klass => {
1463+
if (!(klass.prototype instanceof AV.Object)) {
1464+
throw new Error('registered class is not a subclass of AV.Object');
1465+
}
1466+
const className = klass.name;
1467+
if (!className.length) {
1468+
throw new Error('registered class must be named');
1469+
}
1470+
AV.Object._classMap[className] = klass;
1471+
};
1472+
14461473
AV.Object._findUnsavedChildren = function(object, children, files) {
14471474
AV._traverse(object, function(object) {
14481475
if (object instanceof AV.Object) {

test/object.js

Lines changed: 38 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ var GameScore = AV.Object.extend("GameScore");
44

55
var Post=AV.Object.extend("Post");
66

7+
// for #extend test
8+
class Person extends AV.Object {}
9+
var BackbonePerson = AV.Object.extend('Person');
10+
711
describe('Objects', function(){
812
var objId;
913
var gameScore = GameScore.new();
@@ -23,6 +27,34 @@ describe('Objects', function(){
2327
});
2428
new Post().name;
2529
});
30+
31+
describe('#extend', () => {
32+
it('extend for multiple times should not throw', () => {
33+
let Test;
34+
for (var i=100000; i > 0; i--) {
35+
Test = AV.Object.extend('Test');
36+
}
37+
new Test();
38+
});
39+
40+
it('ES6 extend syntex', () => {
41+
var backbonePerson = new BackbonePerson();
42+
backbonePerson.set('name', 'leeyeh');
43+
var es6Person = new Person();
44+
es6Person.set('name', 'leeyeh');
45+
expect(backbonePerson.toJSON()).to.eql(es6Person.toJSON());
46+
expect(backbonePerson._toFullJSON()).to.eql(es6Person._toFullJSON());
47+
});
48+
49+
it('#resiger an ES6 class', () => {
50+
expect(new AV.Object('Person')).to.be.a(BackbonePerson);
51+
AV.Object.register(Person);
52+
expect(new AV.Object('Person')).to.be.a(Person);
53+
expect(() => AV.Object.register(1)).to.throwError();
54+
expect(() => AV.Object.register(function(){})).to.throwError();
55+
})
56+
});
57+
2658
describe('#Saving Objects', function(){
2759
it('should crate a Object', function(done){
2860
//gameScore.set("newcol","sss")
@@ -174,7 +206,7 @@ describe('Objects', function(){
174206
expect(score2.id).to.be.eql(gameScore.id);
175207
})
176208
);
177-
it('fetchAll with non-existed Class should fail', (done) =>
209+
it('fetchAll with non-existed Class should fail', (done) => {
178210
AV.Object.fetchAll([
179211
AV.Object.createWithoutData('GameScore', gameScore.id),
180212
AV.Object.createWithoutData('FakeClass', gameScore.id),
@@ -184,8 +216,8 @@ describe('Objects', function(){
184216
expect(err).to.be.an(Error);
185217
done();
186218
})
187-
);
188-
it('fetchAll with dirty objet should fail', (done) =>
219+
});
220+
it('fetchAll with dirty objet should fail', (done) => {
189221
AV.Object.fetchAll([
190222
AV.Object.createWithoutData('GameScore', gameScore.id),
191223
new GameScore(),
@@ -195,7 +227,7 @@ describe('Objects', function(){
195227
expect(err).to.be.an(Error);
196228
done();
197229
})
198-
);
230+
});
199231
});
200232

201233
describe("Deleting Objects",function(){
@@ -469,50 +501,10 @@ describe('Objects', function(){
469501
});
470502
});
471503
});
504+
472505

473-
/*
474-
475-
it("it should fetch relation post",function(done){
476-
var post=myComment.get("parent");
477-
post.fetch({
478-
success:function(post){
479-
done();
480-
}
481-
})
482-
})
483-
484-
it("many to many relations create",function(done){
485-
var user = AV.User.current();
486-
relation = user.relation("likes");
487-
relation.add(post);
488-
user.save({
489-
success:function(){
490-
done();
491-
},
492-
error:function(err){
493-
throw err;
494-
}
495-
});
496-
})
497-
498-
it("many to many relations query",function(done){
499-
500-
relation.query().find({
501-
success: function(list) {
502-
done();
503-
// list contains the posts that the current user likes.
504-
},
505-
error:function(err){
506-
throw err;
507-
}
508-
});
509-
})
510-
511-
*/
512-
513-
514-
});
515506

507+
});
516508

517509

518510
});//END RETRIEVING

test/test.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<link rel="stylesheet" href="../node_modules/mocha/mocha.css" />
77
<script src="../node_modules/mocha/mocha.js"></script>
8-
<script src="../node_modules/expect.js/expect.js"></script>
8+
<script src="../node_modules/expect.js/index.js"></script>
99
<script src="../node_modules/superagent/superagent.js"></script>
1010
<!--AV Test init-->
1111

@@ -22,7 +22,6 @@
2222
console.log(arguments);
2323
}
2424
</script>
25-
<script src="promise.js"></script>
2625
<script src="storage.js"></script>
2726
<script src="cache.js"></script>
2827
<script src="file.js"></script>
@@ -37,6 +36,7 @@
3736
<script src="sms.js"></script>
3837
<script src="search.js"></script>
3938
<script src="cloud.js"></script>
39+
<script src="promise.js"></script>
4040
<script>
4141
onload = function(){
4242
mocha.checkLeaks();

0 commit comments

Comments
 (0)