Skip to content

Commit

Permalink
fix: urlSync inheritance bug: side effect on parent
Browse files Browse the repository at this point in the history
  • Loading branch information
imcuttle committed Mar 12, 2018
1 parent b8fad04 commit 96b5d9c
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 36 deletions.
54 changes: 23 additions & 31 deletions src/decorator/utils/getStateLifeDecorator.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,7 @@ export const assignState = action(
)

// const g = {}
function extendsHideProps(target, propKey, value) {
const old = target[propKey] && target[propKey]
if (typeof old === 'object' && old !== null) {
// only saved on top parent
if (!Array.isArray(old)) {
Object.assign(old, value)
}
else {
old.push(value)
}
return
}
function setHideProps(target, propKey, value) {
Object.defineProperty(target, propKey, {
value,
configurable: true,
Expand Down Expand Up @@ -109,27 +98,31 @@ export default (config = {}, name = 'state-life') => {
logger.warn('`' + property + '`' + 'is unobservable,', name, 'would make it to be observable.')
descriptor = observable(target, property, descriptor)
}
const hideArrPropKey = `__[[${name}_array]]__`

// Firstly!
// Supports inheritance
const hideArrPropKey = `__[[${name}_hooks]]__`

// const hidePropKey = `__[[${name}_origin_hooks]]__`
// if (!target[hidePropKey] || !target[hidePropKey][property]) {
// extendsHideProps(target, hidePropKey, {
// [property]: hooks
// })
// NOTE:
// class P {
// @urlSync s = 'a'
// }

// class S extends P {
// @urlSync s = 'a'
// }
// new S() --> should run the S.s hooks, ignore P hooks
// Firstly!
if (!target[hideArrPropKey]) {
extendsHideProps(target, hideArrPropKey, [])
setHideProps(target, hideArrPropKey, [])
}
// inheritance
else if (!target.hasOwnProperty(hideArrPropKey)) {
// set to Prototype
setHideProps(target, hideArrPropKey, target[hideArrPropKey].slice())
}
let i = target[hideArrPropKey].findIndex(([p]) => p === property)
if (i >= 0) {
target[hideArrPropKey].splice(i, 1)
}
const func = (
function () {
function (options, urlKey, property) {
let dispose
let syncUrlTimer
let syncUrlFn
Expand Down Expand Up @@ -211,10 +204,9 @@ export default (config = {}, name = 'state-life') => {
}
}
}
)()
extendsHideProps(target, hideArrPropKey, [property, func])

const arrays = target[hideArrPropKey]
)(options, urlKey, property)
// const arrays =
target[hideArrPropKey].push([property, urlKey, func])

const hooks = {
init: target[initKey],
Expand All @@ -227,22 +219,22 @@ export default (config = {}, name = 'state-life') => {
}

target[initKey] = function (...args) {
arrays.forEach(([, { init }]) => {
this[hideArrPropKey].forEach(([, , { init }]) => {
init.call(this)
})
return callHook(this, initKey, args)
}
if (updateKey) {
target[updateKey] = function (...args) {
arrays.forEach(([, { update }]) => {
this[hideArrPropKey].forEach(([, , { update }]) => {
update.call(this)
})
return callHook(this, updateKey, args)
}
}
target[exitKey] = function (...args) {
// @todo setTimeout move to all for better performance.
arrays.forEach(([, { init }]) => {
this[hideArrPropKey].forEach(([, , { init }]) => {
init.call(this)
})
return callHook(this, exitKey, args)
Expand Down
73 changes: 68 additions & 5 deletions test/decorator-urlSync.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,6 @@ describe('decorator-urlSync', function () {

expect(new S().v).toBe('sv')

// expect(
// Object.keys(s['__[[urlsync_origin_hooks]]__'])
// ).toEqual(
// ['str', 'num', 'int', 'obj', 'arr', 'root', 'a', 'b']
// )
vm = S.create({ a: 'abc', b: 'bbb' })
ReactDOM.render(
<RouterV3 history={hashHistory} routes={{ path: '/', component: vm }}/>,
Expand Down Expand Up @@ -228,4 +223,72 @@ describe('decorator-urlSync', function () {
expect(updated).toBe(true)
done()
})

test('multi Son extends alone Parent', async (done) => {
class Parent extends App {
@urlSync
@observable v = ''
}

class S extends Parent {
@urlSync('s')
@observable v = ''

@urlSync
@observable sonVal = 'son'
}
class T extends Parent {
@urlSync('t')
@observable v = ''
}

const s = S.create()
const s2 = S.create()
const t = T.create()
expect(
T.prototype['__mobxLazyInitializers']
).not.toBe(
S.prototype['__mobxLazyInitializers']
)
const key = '__[[urlsync_hooks]]__'
expect(
T.prototype[key]
).not.toBe(
S.prototype[key]
)

const View = () => (
h.div({},
h(s),
h(s2, { key: 'x' }),
h(t)
)
)
ReactDOM.render(
<RouterV3 routes={{ component: View, path: '/' }} history={hashHistory} />,
dom
)
expect(
parse(hashHistory.getCurrentLocation().search)
).toEqual({})

expect(s.v).toBe('')
t.v = 'ttt'
await mockDelay()
expect(
parse(hashHistory.getCurrentLocation().search)
).toEqual({ t: 'ttt' })
expect(t.v).toBe('ttt')
expect(s.v).toBe('')
expect(s2.v).toBe('')

s.v = 'sss'
s2.v = 'sssWorks'
expect(t.v).toBe('ttt')
await mockDelay()
expect(
parse(hashHistory.getCurrentLocation().search)
).toEqual({ s: 'sssWorks', t: 'ttt' })
done()
})
})

0 comments on commit 96b5d9c

Please sign in to comment.