Skip to content

Commit

Permalink
Fix an issue with getRoot and optimise cache
Browse files Browse the repository at this point in the history
  • Loading branch information
ForsakenHarmony committed Mar 10, 2018
1 parent 82004d7 commit 9ca3f24
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 35 deletions.
77 changes: 42 additions & 35 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,29 @@ const objKeys = Object.keys.bind(Object);

function diff(oldObj, newObj, whitelist) {
if (oldObj === newObj) return oldObj;
const keys = objKeys(oldObj).reduce(
(acc, val) => (~acc.indexOf(val) ? acc : acc.concat(val)),
objKeys(newObj)
);
keys.forEach(key => {
if (~whitelist.indexOf(key)) return;
const oldVal = oldObj[key];
const newVal = newObj[key];
if (oldVal === newVal) return oldObj;
if (
oldVal != null &&
newVal != null &&
typeof oldVal === 'object' &&
typeof newVal === 'object'
) {
oldVal[modelSymbol]
? oldVal.applySnapshot(newVal, true)
: diff(oldVal, newVal, whitelist);
} else {
oldObj[apc][key] = newVal;
}
});
objKeys(oldObj)
.reduce(
(acc, val) => (~acc.indexOf(val) ? acc : acc.concat(val)),
objKeys(newObj)
)
.forEach(key => {
if (~whitelist.indexOf(key)) return;
const oldVal = oldObj[key];
const newVal = newObj[key];
if (oldVal === newVal) return oldObj;
if (
oldVal != null &&
newVal != null &&
typeof oldVal === 'object' &&
typeof newVal === 'object'
) {
oldVal[modelSymbol]
? oldVal.applySnapshot(newVal, true)
: diff(oldVal, newVal, whitelist);
} else {
oldObj[apc][key] = newVal;
}
});
}

function setUpObject(obj, emit, symbol, path, parent = obj) {
Expand Down Expand Up @@ -158,7 +159,7 @@ const model = (name, { initial, actions, views }) => {
return parent;
},
getRoot() {
return parent ? parent.getRoot() === null && parent : null;
return parent ? (parent.getRoot() ? parent.getRoot() : parent) : null;
},
};

Expand All @@ -176,11 +177,8 @@ const model = (name, { initial, actions, views }) => {

state = setUpObject(state, emit, symbol, '');

const viewProxy = state[vpc];
const actionProxy = state[apc];

if (actions) {
const boundActions = actions(actionProxy);
const boundActions = actions(state[apc]);
const keys = objKeys(boundActions);

const emitSnapshot = (name, args) => {
Expand All @@ -207,28 +205,37 @@ const model = (name, { initial, actions, views }) => {
}

if (views) {
const boundViews = views(viewProxy);
const boundViews = views(state[vpc]);
const keys = objKeys(boundViews);
const cache = {};
// r = refresh on get, v = value
// I don't trust uglify here
const caches = {};

for (let key of keys) {
const viewFn = boundViews[key];

Object.defineProperty(state, key, {
get: () => cache[key],
get: () => {
const cache = caches[key];
if (cache.r) {
cache.r = false;
cache.v = boundViews[key]();
}
return cache.v;
},
configurable: false,
});
cache[key] = viewFn();
caches[key] = { v: boundViews[key](), r: false };
}

// update the cache on change
emitter.on('patch', () => {
state.onPatch(() => {
for (let key of keys) {
cache[key] = boundViews[key]();
caches[key].r = true;
}
});
}

// typeof state.init === 'function' && state.init();

return state;
};

Expand Down
48 changes: 48 additions & 0 deletions test/model.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,4 +183,52 @@ describe('model()', function() {

expect(instance.fullname).toBe('Tom Clancy');
});

it('should get the root in nested models', () => {
const Model2 = model('M1', {
initial: () => ({}),
actions: self => ({
root() {
return self.getRoot().thing;
},
}),
});

const Model1 = model('M1', {
initial: () => ({
nest: Model2(),
}),
actions: self => ({
root() {
return self.getRoot().thing;
},
}),
});

const Model = model('M', {
initial: () => ({
nest: Model1(),
thing: 'root',
}),
});

const instance = Model();

debugger;
expect(instance.nest.root()).toBe('root');
expect(instance.nest.nest.root()).toBe('root');
});

// it('should call init when instantiated', () => {
// const init = jest.fn();
//
// const Model = model('Model', {
// initial: () => ({}),
// actions: state => ({
// init,
// }),
// });
// Model();
// expect(init).toBeCalled();
// });
});

0 comments on commit 9ca3f24

Please sign in to comment.