Skip to content

Commit 481ba24

Browse files
committed
Enable ES6 Classes as Traits. Make sure properties descriptors are kept in Host as in Trait.Closes #24.
1 parent 015922a commit 481ba24

2 files changed

Lines changed: 43 additions & 9 deletions

File tree

lib/processor/annotation/Traits.js

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,29 @@ Traits.prototype = {
4444
},
4545

4646
_applyTo: function (subject, options) {
47-
var type = this._configName,
47+
var me = this,
48+
type = me._configName,
4849
o = {},
49-
key, tp, excluded, aliases, t;
50+
tp, excluded, aliases, t;
5051

51-
if (this._isApplicable(options)) {
52+
if (me._isApplicable(options)) {
5253
o[type] = options;
53-
return this._applyTo(subject, o);
54+
return me._applyTo(subject, o);
5455
}
5556

5657
excluded = [].concat(options.excludes);
5758
aliases = options.alias || {};
5859
t = options[type];
5960
tp = t.prototype || t;
6061

61-
for (key in tp) {
62-
this._raiseErrorIfItIsState(key, tp);
63-
this._applyIfNotExcluded(key, excluded, aliases, subject, tp);
64-
}
62+
Object.getOwnPropertyNames(tp)
63+
.filter(function(key){
64+
return !key.match(/^(?:constructor|prototype|arguments|caller|name|bind|call|apply|toString|length)$/);
65+
})
66+
.forEach(function(key){
67+
me._raiseErrorIfItIsState(key, tp);
68+
me._applyIfNotExcluded(key, excluded, aliases, subject, tp);
69+
});
6570
},
6671

6772
_applyIfNotExcluded: function (key, excluded, aliases, subject, tp) {
@@ -72,7 +77,7 @@ Traits.prototype = {
7277
this._raiseErrorIfConflict(alias, subject, tp);
7378

7479
if (!subject[alias] || subject[alias] === Requires.requiredMethod) {
75-
subject[alias] = tp[key];
80+
Object.defineProperty(subject, alias, Object.getOwnPropertyDescriptor(tp, key));
7681
}
7782
}
7883
},

test/unit/processor/annotation/Traits.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,35 @@ describe('Annotation Processor @traits', function(){
7070
});
7171
});
7272

73+
describe('Passing a ES6-type class as Trait reference `@traits:[TraitA]`', function(){
74+
var sut = new Traits(),
75+
TraitA = function(){},
76+
MyClass = function(){},
77+
aMethod = function method(){},
78+
propDesc = {
79+
enumerable: false,
80+
value: aMethod
81+
};
82+
83+
Object.defineProperty(
84+
TraitA.prototype,
85+
'aMethod',
86+
propDesc
87+
);
88+
sut.setParameter([TraitA]);
89+
90+
sut.process(MyClass);
91+
92+
it('makes the TraitA methods part of the given MyClass', function(){
93+
expect(MyClass).to.respondTo('aMethod');
94+
expect(MyClass.prototype.aMethod).to.be.equal(aMethod);
95+
});
96+
97+
it('makes MyClass method to keep same property descriptor', function(){
98+
expect(Object.getOwnPropertyDescriptor(MyClass.prototype, 'aMethod') === propDesc);
99+
});
100+
});
101+
73102
describe('Passing a Trait class using options object `@traits: [{trait: TraitA}]`', function(){
74103
var sut = new Traits(),
75104
TraitA = function(){},

0 commit comments

Comments
 (0)