mirror of
https://github.com/HeyPuter/puter
synced 2024-11-15 06:15:47 +00:00
feat(putility): trait method override support
Support for trait method overrides will make it possible to use putility traits with the decorator pattern while using a proxy class to avoid redundant re-implementation of proxy methods. Use of the pattern described above will occur in the implementation of client-side filesystem caching.
This commit is contained in:
parent
c12ae2a923
commit
43c5402b7c
@ -1,5 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
install_in_instance: (instance, { parameters }) => {
|
// old implementation
|
||||||
|
install_in_instance_: (instance, { parameters }) => {
|
||||||
const impls = instance._get_merged_static_object('IMPLEMENTS');
|
const impls = instance._get_merged_static_object('IMPLEMENTS');
|
||||||
|
|
||||||
instance._.impls = {};
|
instance._.impls = {};
|
||||||
@ -17,4 +18,28 @@ module.exports = {
|
|||||||
instance.as = trait_name => instance._.impls[trait_name];
|
instance.as = trait_name => instance._.impls[trait_name];
|
||||||
instance.list_traits = () => Object.keys(instance._.impls);
|
instance.list_traits = () => Object.keys(instance._.impls);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// new implementation
|
||||||
|
install_in_instance: (instance, { parameters }) => {
|
||||||
|
const chain = instance._get_inheritance_chain();
|
||||||
|
instance._.impls = {};
|
||||||
|
|
||||||
|
instance.as = trait_name => instance._.impls[trait_name];
|
||||||
|
instance.list_traits = () => Object.keys(instance._.impls);
|
||||||
|
|
||||||
|
for ( const cls of chain ) {
|
||||||
|
const cls_traits = cls.IMPLEMENTS;
|
||||||
|
if ( ! cls_traits ) continue;
|
||||||
|
for ( const trait_name in cls_traits ) {
|
||||||
|
const impl = instance._.impls[trait_name] ??
|
||||||
|
(instance._.impls[trait_name] = {});
|
||||||
|
const cls_impl = cls_traits[trait_name];
|
||||||
|
|
||||||
|
for ( const method_name in cls_impl ) {
|
||||||
|
const fn = cls_impl[method_name];
|
||||||
|
impl[method_name] = fn.bind(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
49
src/putility/test/traits.test.js
Normal file
49
src/putility/test/traits.test.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
const { expect } = require('chai');
|
||||||
|
const { AdvancedBase } = require("../src/AdvancedBase");
|
||||||
|
|
||||||
|
class TestClass extends AdvancedBase {
|
||||||
|
static IMPLEMENTS = {
|
||||||
|
test_trait: {
|
||||||
|
test_method: () => 'A'
|
||||||
|
},
|
||||||
|
override_trait: {
|
||||||
|
preserved_method: () => 'B',
|
||||||
|
override_method: () => 'C',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestSubClass extends TestClass {
|
||||||
|
static IMPLEMENTS = {
|
||||||
|
override_trait: {
|
||||||
|
override_method: () => 'D',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('traits', () => {
|
||||||
|
it('instance.as', () => {
|
||||||
|
const o = new TestClass();
|
||||||
|
expect(o.as).to.be.a('function');
|
||||||
|
const ot = o.as('test_trait');
|
||||||
|
expect(ot.test_method).to.be.a('function');
|
||||||
|
expect(ot.test_method()).to.equal('A');
|
||||||
|
});
|
||||||
|
it('traits of parent', () => {
|
||||||
|
const o = new TestSubClass();
|
||||||
|
console.log(o._get_merged_static_object('IMPLEMENTS'))
|
||||||
|
expect(o.as).to.be.a('function');
|
||||||
|
const ot = o.as('test_trait');
|
||||||
|
expect(ot.test_method).to.be.a('function');
|
||||||
|
expect(ot.test_method()).to.equal('A');
|
||||||
|
})
|
||||||
|
it('trait method overrides', () => {
|
||||||
|
const o = new TestSubClass();
|
||||||
|
expect(o.as).to.be.a('function');
|
||||||
|
const ot = o.as('override_trait');
|
||||||
|
expect(ot.preserved_method).to.be.a('function');
|
||||||
|
expect(ot.override_method).to.be.a('function');
|
||||||
|
expect (ot.preserved_method()).to.equal('B');
|
||||||
|
expect (ot.override_method()).to.equal('D');
|
||||||
|
})
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user