refactor: rename things
This commit is contained in:
parent
0cd8183fbf
commit
80d1eb7480
@ -1,4 +1,4 @@
|
|||||||
import { observable, autorun, unwrap, isObservable } from '../../src'
|
import { observable, effect, unwrap, isObservable } from '../../src'
|
||||||
|
|
||||||
describe('observer/collections', () => {
|
describe('observer/collections', () => {
|
||||||
describe('Map', () => {
|
describe('Map', () => {
|
||||||
@ -13,7 +13,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe mutations', () => {
|
it('should observe mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const map = observable(new Map())
|
const map = observable(new Map())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = map.get('key')
|
dummy = map.get('key')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe size mutations', () => {
|
it('should observe size mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const map = observable(new Map())
|
const map = observable(new Map())
|
||||||
autorun(() => (dummy = map.size))
|
effect(() => (dummy = map.size))
|
||||||
|
|
||||||
expect(dummy).toBe(0)
|
expect(dummy).toBe(0)
|
||||||
map.set('key1', 'value')
|
map.set('key1', 'value')
|
||||||
@ -44,7 +44,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe for of iteration', () => {
|
it('should observe for of iteration', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const map = observable(new Map())
|
const map = observable(new Map())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
for (let [key, num] of map) {
|
for (let [key, num] of map) {
|
||||||
@ -67,7 +67,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe forEach iteration', () => {
|
it('should observe forEach iteration', () => {
|
||||||
let dummy: any
|
let dummy: any
|
||||||
const map = observable(new Map())
|
const map = observable(new Map())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
map.forEach((num: any) => (dummy += num))
|
map.forEach((num: any) => (dummy += num))
|
||||||
})
|
})
|
||||||
@ -86,7 +86,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe keys iteration', () => {
|
it('should observe keys iteration', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const map = observable(new Map())
|
const map = observable(new Map())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (let key of map.keys()) {
|
for (let key of map.keys()) {
|
||||||
dummy += key
|
dummy += key
|
||||||
@ -107,7 +107,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe values iteration', () => {
|
it('should observe values iteration', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const map = observable(new Map())
|
const map = observable(new Map())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (let num of map.values()) {
|
for (let num of map.values()) {
|
||||||
dummy += num
|
dummy += num
|
||||||
@ -128,7 +128,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe entries iteration', () => {
|
it('should observe entries iteration', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const map = observable(new Map())
|
const map = observable(new Map())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
for (let [key, num] of map.entries()) {
|
for (let [key, num] of map.entries()) {
|
||||||
@ -151,7 +151,7 @@ describe('observer/collections', () => {
|
|||||||
it('should be triggered by clearing', () => {
|
it('should be triggered by clearing', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const map = observable(new Map())
|
const map = observable(new Map())
|
||||||
autorun(() => (dummy = map.get('key')))
|
effect(() => (dummy = map.get('key')))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
map.set('key', 3)
|
map.set('key', 3)
|
||||||
@ -163,7 +163,7 @@ describe('observer/collections', () => {
|
|||||||
it('should not observe custom property mutations', () => {
|
it('should not observe custom property mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const map: any = observable(new Map())
|
const map: any = observable(new Map())
|
||||||
autorun(() => (dummy = map.customProp))
|
effect(() => (dummy = map.customProp))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
map.customProp = 'Hello World'
|
map.customProp = 'Hello World'
|
||||||
@ -174,7 +174,7 @@ describe('observer/collections', () => {
|
|||||||
let dummy
|
let dummy
|
||||||
const map = observable(new Map())
|
const map = observable(new Map())
|
||||||
const mapSpy = jest.fn(() => (dummy = map.get('key')))
|
const mapSpy = jest.fn(() => (dummy = map.get('key')))
|
||||||
autorun(mapSpy)
|
effect(mapSpy)
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
expect(mapSpy).toHaveBeenCalledTimes(1)
|
expect(mapSpy).toHaveBeenCalledTimes(1)
|
||||||
@ -198,7 +198,7 @@ describe('observer/collections', () => {
|
|||||||
it('should not observe raw data', () => {
|
it('should not observe raw data', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const map = observable(new Map())
|
const map = observable(new Map())
|
||||||
autorun(() => (dummy = unwrap(map).get('key')))
|
effect(() => (dummy = unwrap(map).get('key')))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
map.set('key', 'Hello')
|
map.set('key', 'Hello')
|
||||||
@ -229,7 +229,7 @@ describe('observer/collections', () => {
|
|||||||
const observed = observable(new Map())
|
const observed = observable(new Map())
|
||||||
observed.set('key', { a: 1 })
|
observed.set('key', { a: 1 })
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = observed.get('key').a
|
dummy = observed.get('key').a
|
||||||
})
|
})
|
||||||
observed.get('key').a = 2
|
observed.get('key').a = 2
|
||||||
@ -239,7 +239,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe nested values in iterations (forEach)', () => {
|
it('should observe nested values in iterations (forEach)', () => {
|
||||||
const map = observable(new Map([[1, { foo: 1 }]]))
|
const map = observable(new Map([[1, { foo: 1 }]]))
|
||||||
let dummy: any
|
let dummy: any
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
map.forEach(value => {
|
map.forEach(value => {
|
||||||
expect(isObservable(value)).toBe(true)
|
expect(isObservable(value)).toBe(true)
|
||||||
@ -254,7 +254,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe nested values in iterations (values)', () => {
|
it('should observe nested values in iterations (values)', () => {
|
||||||
const map = observable(new Map([[1, { foo: 1 }]]))
|
const map = observable(new Map([[1, { foo: 1 }]]))
|
||||||
let dummy: any
|
let dummy: any
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (const value of map.values()) {
|
for (const value of map.values()) {
|
||||||
expect(isObservable(value)).toBe(true)
|
expect(isObservable(value)).toBe(true)
|
||||||
@ -270,7 +270,7 @@ describe('observer/collections', () => {
|
|||||||
const key = {}
|
const key = {}
|
||||||
const map = observable(new Map([[key, { foo: 1 }]]))
|
const map = observable(new Map([[key, { foo: 1 }]]))
|
||||||
let dummy: any
|
let dummy: any
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (const [key, value] of map.entries()) {
|
for (const [key, value] of map.entries()) {
|
||||||
key
|
key
|
||||||
@ -288,7 +288,7 @@ describe('observer/collections', () => {
|
|||||||
const key = {}
|
const key = {}
|
||||||
const map = observable(new Map([[key, { foo: 1 }]]))
|
const map = observable(new Map([[key, { foo: 1 }]]))
|
||||||
let dummy: any
|
let dummy: any
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (const [key, value] of map) {
|
for (const [key, value] of map) {
|
||||||
key
|
key
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { observable, autorun, isObservable, unwrap } from '../../src'
|
import { observable, effect, isObservable, unwrap } from '../../src'
|
||||||
|
|
||||||
describe('observer/collections', () => {
|
describe('observer/collections', () => {
|
||||||
describe('Set', () => {
|
describe('Set', () => {
|
||||||
@ -13,7 +13,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe mutations', () => {
|
it('should observe mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => (dummy = set.has('value')))
|
effect(() => (dummy = set.has('value')))
|
||||||
|
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
set.add('value')
|
set.add('value')
|
||||||
@ -25,7 +25,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe for of iteration', () => {
|
it('should observe for of iteration', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (let num of set) {
|
for (let num of set) {
|
||||||
dummy += num
|
dummy += num
|
||||||
@ -45,7 +45,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe forEach iteration', () => {
|
it('should observe forEach iteration', () => {
|
||||||
let dummy: any
|
let dummy: any
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
set.forEach(num => (dummy += num))
|
set.forEach(num => (dummy += num))
|
||||||
})
|
})
|
||||||
@ -63,7 +63,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe values iteration', () => {
|
it('should observe values iteration', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (let num of set.values()) {
|
for (let num of set.values()) {
|
||||||
dummy += num
|
dummy += num
|
||||||
@ -83,7 +83,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe keys iteration', () => {
|
it('should observe keys iteration', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (let num of set.keys()) {
|
for (let num of set.keys()) {
|
||||||
dummy += num
|
dummy += num
|
||||||
@ -103,7 +103,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe entries iteration', () => {
|
it('should observe entries iteration', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
for (let [key, num] of set.entries()) {
|
for (let [key, num] of set.entries()) {
|
||||||
@ -125,7 +125,7 @@ describe('observer/collections', () => {
|
|||||||
it('should be triggered by clearing', () => {
|
it('should be triggered by clearing', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => (dummy = set.has('key')))
|
effect(() => (dummy = set.has('key')))
|
||||||
|
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
set.add('key')
|
set.add('key')
|
||||||
@ -137,7 +137,7 @@ describe('observer/collections', () => {
|
|||||||
it('should not observe custom property mutations', () => {
|
it('should not observe custom property mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set: any = observable(new Set())
|
const set: any = observable(new Set())
|
||||||
autorun(() => (dummy = set.customProp))
|
effect(() => (dummy = set.customProp))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
set.customProp = 'Hello World'
|
set.customProp = 'Hello World'
|
||||||
@ -147,7 +147,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe size mutations', () => {
|
it('should observe size mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => (dummy = set.size))
|
effect(() => (dummy = set.size))
|
||||||
|
|
||||||
expect(dummy).toBe(0)
|
expect(dummy).toBe(0)
|
||||||
set.add('value')
|
set.add('value')
|
||||||
@ -163,7 +163,7 @@ describe('observer/collections', () => {
|
|||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
const setSpy = jest.fn(() => (dummy = set.has('value')))
|
const setSpy = jest.fn(() => (dummy = set.has('value')))
|
||||||
autorun(setSpy)
|
effect(setSpy)
|
||||||
|
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
expect(setSpy).toHaveBeenCalledTimes(1)
|
expect(setSpy).toHaveBeenCalledTimes(1)
|
||||||
@ -187,7 +187,7 @@ describe('observer/collections', () => {
|
|||||||
it('should not observe raw data', () => {
|
it('should not observe raw data', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => (dummy = unwrap(set).has('value')))
|
effect(() => (dummy = unwrap(set).has('value')))
|
||||||
|
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
set.add('value')
|
set.add('value')
|
||||||
@ -197,7 +197,7 @@ describe('observer/collections', () => {
|
|||||||
it('should not observe raw iterations', () => {
|
it('should not observe raw iterations', () => {
|
||||||
let dummy = 0
|
let dummy = 0
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (let [num] of unwrap(set).entries()) {
|
for (let [num] of unwrap(set).entries()) {
|
||||||
dummy += num
|
dummy += num
|
||||||
@ -227,7 +227,7 @@ describe('observer/collections', () => {
|
|||||||
it('should not be triggered by raw mutations', () => {
|
it('should not be triggered by raw mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => (dummy = set.has('value')))
|
effect(() => (dummy = set.has('value')))
|
||||||
|
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
unwrap(set).add('value')
|
unwrap(set).add('value')
|
||||||
@ -242,7 +242,7 @@ describe('observer/collections', () => {
|
|||||||
it('should not observe raw size mutations', () => {
|
it('should not observe raw size mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => (dummy = unwrap(set).size))
|
effect(() => (dummy = unwrap(set).size))
|
||||||
|
|
||||||
expect(dummy).toBe(0)
|
expect(dummy).toBe(0)
|
||||||
set.add('value')
|
set.add('value')
|
||||||
@ -252,7 +252,7 @@ describe('observer/collections', () => {
|
|||||||
it('should not be triggered by raw size mutations', () => {
|
it('should not be triggered by raw size mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
autorun(() => (dummy = set.size))
|
effect(() => (dummy = set.size))
|
||||||
|
|
||||||
expect(dummy).toBe(0)
|
expect(dummy).toBe(0)
|
||||||
unwrap(set).add('value')
|
unwrap(set).add('value')
|
||||||
@ -264,7 +264,7 @@ describe('observer/collections', () => {
|
|||||||
const key = {}
|
const key = {}
|
||||||
const set = observable(new Set())
|
const set = observable(new Set())
|
||||||
const setSpy = jest.fn(() => (dummy = set.has(key)))
|
const setSpy = jest.fn(() => (dummy = set.has(key)))
|
||||||
autorun(setSpy)
|
effect(setSpy)
|
||||||
|
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
expect(setSpy).toHaveBeenCalledTimes(1)
|
expect(setSpy).toHaveBeenCalledTimes(1)
|
||||||
@ -290,7 +290,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe nested values in iterations (forEach)', () => {
|
it('should observe nested values in iterations (forEach)', () => {
|
||||||
const set = observable(new Set([{ foo: 1 }]))
|
const set = observable(new Set([{ foo: 1 }]))
|
||||||
let dummy: any
|
let dummy: any
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
set.forEach(value => {
|
set.forEach(value => {
|
||||||
expect(isObservable(value)).toBe(true)
|
expect(isObservable(value)).toBe(true)
|
||||||
@ -307,7 +307,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe nested values in iterations (values)', () => {
|
it('should observe nested values in iterations (values)', () => {
|
||||||
const set = observable(new Set([{ foo: 1 }]))
|
const set = observable(new Set([{ foo: 1 }]))
|
||||||
let dummy: any
|
let dummy: any
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (const value of set.values()) {
|
for (const value of set.values()) {
|
||||||
expect(isObservable(value)).toBe(true)
|
expect(isObservable(value)).toBe(true)
|
||||||
@ -324,7 +324,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe nested values in iterations (entries)', () => {
|
it('should observe nested values in iterations (entries)', () => {
|
||||||
const set = observable(new Set([{ foo: 1 }]))
|
const set = observable(new Set([{ foo: 1 }]))
|
||||||
let dummy: any
|
let dummy: any
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (const [key, value] of set.entries()) {
|
for (const [key, value] of set.entries()) {
|
||||||
expect(isObservable(key)).toBe(true)
|
expect(isObservable(key)).toBe(true)
|
||||||
@ -342,7 +342,7 @@ describe('observer/collections', () => {
|
|||||||
it('should observe nested values in iterations (for...of)', () => {
|
it('should observe nested values in iterations (for...of)', () => {
|
||||||
const set = observable(new Set([{ foo: 1 }]))
|
const set = observable(new Set([{ foo: 1 }]))
|
||||||
let dummy: any
|
let dummy: any
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (const value of set) {
|
for (const value of set) {
|
||||||
expect(isObservable(value)).toBe(true)
|
expect(isObservable(value)).toBe(true)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { observable, autorun, unwrap, isObservable } from '../../src'
|
import { observable, effect, unwrap, isObservable } from '../../src'
|
||||||
|
|
||||||
describe('observer/collections', () => {
|
describe('observer/collections', () => {
|
||||||
describe('WeakMap', () => {
|
describe('WeakMap', () => {
|
||||||
@ -14,7 +14,7 @@ describe('observer/collections', () => {
|
|||||||
let dummy
|
let dummy
|
||||||
const key = {}
|
const key = {}
|
||||||
const map = observable(new WeakMap())
|
const map = observable(new WeakMap())
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = map.get(key)
|
dummy = map.get(key)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ describe('observer/collections', () => {
|
|||||||
it('should not observe custom property mutations', () => {
|
it('should not observe custom property mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const map: any = observable(new WeakMap())
|
const map: any = observable(new WeakMap())
|
||||||
autorun(() => (dummy = map.customProp))
|
effect(() => (dummy = map.customProp))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
map.customProp = 'Hello World'
|
map.customProp = 'Hello World'
|
||||||
@ -42,7 +42,7 @@ describe('observer/collections', () => {
|
|||||||
const key = {}
|
const key = {}
|
||||||
const map = observable(new WeakMap())
|
const map = observable(new WeakMap())
|
||||||
const mapSpy = jest.fn(() => (dummy = map.get(key)))
|
const mapSpy = jest.fn(() => (dummy = map.get(key)))
|
||||||
autorun(mapSpy)
|
effect(mapSpy)
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
expect(mapSpy).toHaveBeenCalledTimes(1)
|
expect(mapSpy).toHaveBeenCalledTimes(1)
|
||||||
@ -64,7 +64,7 @@ describe('observer/collections', () => {
|
|||||||
let dummy
|
let dummy
|
||||||
const key = {}
|
const key = {}
|
||||||
const map = observable(new WeakMap())
|
const map = observable(new WeakMap())
|
||||||
autorun(() => (dummy = unwrap(map).get(key)))
|
effect(() => (dummy = unwrap(map).get(key)))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
map.set(key, 'Hello')
|
map.set(key, 'Hello')
|
||||||
@ -98,7 +98,7 @@ describe('observer/collections', () => {
|
|||||||
const key = {}
|
const key = {}
|
||||||
observed.set(key, { a: 1 })
|
observed.set(key, { a: 1 })
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = observed.get(key).a
|
dummy = observed.get(key).a
|
||||||
})
|
})
|
||||||
observed.get(key).a = 2
|
observed.get(key).a = 2
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { observable, isObservable, autorun, unwrap } from '../../src'
|
import { observable, isObservable, effect, unwrap } from '../../src'
|
||||||
|
|
||||||
describe('observer/collections', () => {
|
describe('observer/collections', () => {
|
||||||
describe('WeakSet', () => {
|
describe('WeakSet', () => {
|
||||||
@ -14,7 +14,7 @@ describe('observer/collections', () => {
|
|||||||
let dummy
|
let dummy
|
||||||
const value = {}
|
const value = {}
|
||||||
const set = observable(new WeakSet())
|
const set = observable(new WeakSet())
|
||||||
autorun(() => (dummy = set.has(value)))
|
effect(() => (dummy = set.has(value)))
|
||||||
|
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
set.add(value)
|
set.add(value)
|
||||||
@ -26,7 +26,7 @@ describe('observer/collections', () => {
|
|||||||
it('should not observe custom property mutations', () => {
|
it('should not observe custom property mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const set: any = observable(new WeakSet())
|
const set: any = observable(new WeakSet())
|
||||||
autorun(() => (dummy = set.customProp))
|
effect(() => (dummy = set.customProp))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
set.customProp = 'Hello World'
|
set.customProp = 'Hello World'
|
||||||
@ -38,7 +38,7 @@ describe('observer/collections', () => {
|
|||||||
const value = {}
|
const value = {}
|
||||||
const set = observable(new WeakSet())
|
const set = observable(new WeakSet())
|
||||||
const setSpy = jest.fn(() => (dummy = set.has(value)))
|
const setSpy = jest.fn(() => (dummy = set.has(value)))
|
||||||
autorun(setSpy)
|
effect(setSpy)
|
||||||
|
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
expect(setSpy).toHaveBeenCalledTimes(1)
|
expect(setSpy).toHaveBeenCalledTimes(1)
|
||||||
@ -60,7 +60,7 @@ describe('observer/collections', () => {
|
|||||||
const value = {}
|
const value = {}
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new WeakSet())
|
const set = observable(new WeakSet())
|
||||||
autorun(() => (dummy = unwrap(set).has(value)))
|
effect(() => (dummy = unwrap(set).has(value)))
|
||||||
|
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
set.add(value)
|
set.add(value)
|
||||||
@ -71,7 +71,7 @@ describe('observer/collections', () => {
|
|||||||
const value = {}
|
const value = {}
|
||||||
let dummy
|
let dummy
|
||||||
const set = observable(new WeakSet())
|
const set = observable(new WeakSet())
|
||||||
autorun(() => (dummy = set.has(value)))
|
effect(() => (dummy = set.has(value)))
|
||||||
|
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
unwrap(set).add(value)
|
unwrap(set).add(value)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { computed, observable, autorun, stop } from '../src'
|
import { computed, observable, effect, stop } from '../src'
|
||||||
|
|
||||||
describe('observer/computed', () => {
|
describe('observer/computed', () => {
|
||||||
it('should return updated value', () => {
|
it('should return updated value', () => {
|
||||||
@ -52,11 +52,11 @@ describe('observer/computed', () => {
|
|||||||
expect(callArg).toBe(ctx)
|
expect(callArg).toBe(ctx)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should trigger autorun', () => {
|
it('should trigger effect', () => {
|
||||||
const value: any = observable({})
|
const value: any = observable({})
|
||||||
const cValue = computed(() => value.foo)
|
const cValue = computed(() => value.foo)
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = cValue()
|
dummy = cValue()
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
@ -75,7 +75,7 @@ describe('observer/computed', () => {
|
|||||||
expect(c1()).toBe(1)
|
expect(c1()).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should trigger autorun when chained', () => {
|
it('should trigger effect when chained', () => {
|
||||||
const value: any = observable({ foo: 0 })
|
const value: any = observable({ foo: 0 })
|
||||||
const getter1 = jest.fn(() => value.foo)
|
const getter1 = jest.fn(() => value.foo)
|
||||||
const getter2 = jest.fn(() => {
|
const getter2 = jest.fn(() => {
|
||||||
@ -85,7 +85,7 @@ describe('observer/computed', () => {
|
|||||||
const c2 = computed(getter2)
|
const c2 = computed(getter2)
|
||||||
|
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = c2()
|
dummy = c2()
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(1)
|
expect(dummy).toBe(1)
|
||||||
@ -98,7 +98,7 @@ describe('observer/computed', () => {
|
|||||||
expect(getter2).toHaveBeenCalledTimes(2)
|
expect(getter2).toHaveBeenCalledTimes(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should trigger autorun when chained (mixed invocations)', () => {
|
it('should trigger effect when chained (mixed invocations)', () => {
|
||||||
const value: any = observable({ foo: 0 })
|
const value: any = observable({ foo: 0 })
|
||||||
const getter1 = jest.fn(() => value.foo)
|
const getter1 = jest.fn(() => value.foo)
|
||||||
const getter2 = jest.fn(() => {
|
const getter2 = jest.fn(() => {
|
||||||
@ -108,7 +108,7 @@ describe('observer/computed', () => {
|
|||||||
const c2 = computed(getter2)
|
const c2 = computed(getter2)
|
||||||
|
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = c1() + c2()
|
dummy = c1() + c2()
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(1)
|
expect(dummy).toBe(1)
|
||||||
@ -126,13 +126,13 @@ describe('observer/computed', () => {
|
|||||||
const value: any = observable({})
|
const value: any = observable({})
|
||||||
const cValue = computed(() => value.foo)
|
const cValue = computed(() => value.foo)
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = cValue()
|
dummy = cValue()
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
value.foo = 1
|
value.foo = 1
|
||||||
expect(dummy).toBe(1)
|
expect(dummy).toBe(1)
|
||||||
stop(cValue.runner)
|
stop(cValue.effect)
|
||||||
value.foo = 2
|
value.foo = 2
|
||||||
expect(dummy).toBe(1)
|
expect(dummy).toBe(1)
|
||||||
})
|
})
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
import {
|
import {
|
||||||
observable,
|
observable,
|
||||||
autorun,
|
effect,
|
||||||
stop,
|
stop,
|
||||||
unwrap,
|
unwrap,
|
||||||
OperationTypes,
|
OperationTypes,
|
||||||
DebuggerEvent,
|
DebuggerEvent,
|
||||||
markNonReactive
|
markNonReactive
|
||||||
} from '../src/index'
|
} from '../src/index'
|
||||||
import { ITERATE_KEY } from '../src/autorun'
|
import { ITERATE_KEY } from '../src/effect'
|
||||||
|
|
||||||
describe('observer/autorun', () => {
|
describe('observer/effect', () => {
|
||||||
it('should run the passed function once (wrapped by a autorun)', () => {
|
it('should run the passed function once (wrapped by a effect)', () => {
|
||||||
const fnSpy = jest.fn(() => {})
|
const fnSpy = jest.fn(() => {})
|
||||||
autorun(fnSpy)
|
effect(fnSpy)
|
||||||
expect(fnSpy).toHaveBeenCalledTimes(1)
|
expect(fnSpy).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should observe basic properties', () => {
|
it('should observe basic properties', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const counter = observable({ num: 0 })
|
const counter = observable({ num: 0 })
|
||||||
autorun(() => (dummy = counter.num))
|
effect(() => (dummy = counter.num))
|
||||||
|
|
||||||
expect(dummy).toBe(0)
|
expect(dummy).toBe(0)
|
||||||
counter.num = 7
|
counter.num = 7
|
||||||
@ -29,18 +29,18 @@ describe('observer/autorun', () => {
|
|||||||
it('should observe multiple properties', () => {
|
it('should observe multiple properties', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const counter = observable({ num1: 0, num2: 0 })
|
const counter = observable({ num1: 0, num2: 0 })
|
||||||
autorun(() => (dummy = counter.num1 + counter.num1 + counter.num2))
|
effect(() => (dummy = counter.num1 + counter.num1 + counter.num2))
|
||||||
|
|
||||||
expect(dummy).toBe(0)
|
expect(dummy).toBe(0)
|
||||||
counter.num1 = counter.num2 = 7
|
counter.num1 = counter.num2 = 7
|
||||||
expect(dummy).toBe(21)
|
expect(dummy).toBe(21)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should handle multiple autoruns', () => {
|
it('should handle multiple effects', () => {
|
||||||
let dummy1, dummy2
|
let dummy1, dummy2
|
||||||
const counter = observable({ num: 0 })
|
const counter = observable({ num: 0 })
|
||||||
autorun(() => (dummy1 = counter.num))
|
effect(() => (dummy1 = counter.num))
|
||||||
autorun(() => (dummy2 = counter.num))
|
effect(() => (dummy2 = counter.num))
|
||||||
|
|
||||||
expect(dummy1).toBe(0)
|
expect(dummy1).toBe(0)
|
||||||
expect(dummy2).toBe(0)
|
expect(dummy2).toBe(0)
|
||||||
@ -52,7 +52,7 @@ describe('observer/autorun', () => {
|
|||||||
it('should observe nested properties', () => {
|
it('should observe nested properties', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const counter = observable({ nested: { num: 0 } })
|
const counter = observable({ nested: { num: 0 } })
|
||||||
autorun(() => (dummy = counter.nested.num))
|
effect(() => (dummy = counter.nested.num))
|
||||||
|
|
||||||
expect(dummy).toBe(0)
|
expect(dummy).toBe(0)
|
||||||
counter.nested.num = 8
|
counter.nested.num = 8
|
||||||
@ -62,7 +62,7 @@ describe('observer/autorun', () => {
|
|||||||
it('should observe delete operations', () => {
|
it('should observe delete operations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const obj = observable({ prop: 'value' })
|
const obj = observable({ prop: 'value' })
|
||||||
autorun(() => (dummy = obj.prop))
|
effect(() => (dummy = obj.prop))
|
||||||
|
|
||||||
expect(dummy).toBe('value')
|
expect(dummy).toBe('value')
|
||||||
delete obj.prop
|
delete obj.prop
|
||||||
@ -72,7 +72,7 @@ describe('observer/autorun', () => {
|
|||||||
it('should observe has operations', () => {
|
it('should observe has operations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const obj: any = observable({ prop: 'value' })
|
const obj: any = observable({ prop: 'value' })
|
||||||
autorun(() => (dummy = 'prop' in obj))
|
effect(() => (dummy = 'prop' in obj))
|
||||||
|
|
||||||
expect(dummy).toBe(true)
|
expect(dummy).toBe(true)
|
||||||
delete obj.prop
|
delete obj.prop
|
||||||
@ -86,7 +86,7 @@ describe('observer/autorun', () => {
|
|||||||
const counter = observable({ num: 0 })
|
const counter = observable({ num: 0 })
|
||||||
const parentCounter = observable({ num: 2 })
|
const parentCounter = observable({ num: 2 })
|
||||||
Object.setPrototypeOf(counter, parentCounter)
|
Object.setPrototypeOf(counter, parentCounter)
|
||||||
autorun(() => (dummy = counter.num))
|
effect(() => (dummy = counter.num))
|
||||||
|
|
||||||
expect(dummy).toBe(0)
|
expect(dummy).toBe(0)
|
||||||
delete counter.num
|
delete counter.num
|
||||||
@ -102,7 +102,7 @@ describe('observer/autorun', () => {
|
|||||||
const counter = observable({ num: 0 })
|
const counter = observable({ num: 0 })
|
||||||
const parentCounter = observable({ num: 2 })
|
const parentCounter = observable({ num: 2 })
|
||||||
Object.setPrototypeOf(counter, parentCounter)
|
Object.setPrototypeOf(counter, parentCounter)
|
||||||
autorun(() => (dummy = 'num' in counter))
|
effect(() => (dummy = 'num' in counter))
|
||||||
|
|
||||||
expect(dummy).toBe(true)
|
expect(dummy).toBe(true)
|
||||||
delete counter.num
|
delete counter.num
|
||||||
@ -125,8 +125,8 @@ describe('observer/autorun', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
Object.setPrototypeOf(obj, parent)
|
Object.setPrototypeOf(obj, parent)
|
||||||
autorun(() => (dummy = obj.prop))
|
effect(() => (dummy = obj.prop))
|
||||||
autorun(() => (parentDummy = parent.prop))
|
effect(() => (parentDummy = parent.prop))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
expect(parentDummy).toBe(undefined)
|
expect(parentDummy).toBe(undefined)
|
||||||
@ -142,7 +142,7 @@ describe('observer/autorun', () => {
|
|||||||
it('should observe function call chains', () => {
|
it('should observe function call chains', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const counter = observable({ num: 0 })
|
const counter = observable({ num: 0 })
|
||||||
autorun(() => (dummy = getNum()))
|
effect(() => (dummy = getNum()))
|
||||||
|
|
||||||
function getNum() {
|
function getNum() {
|
||||||
return counter.num
|
return counter.num
|
||||||
@ -156,7 +156,7 @@ describe('observer/autorun', () => {
|
|||||||
it('should observe iteration', () => {
|
it('should observe iteration', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const list = observable(['Hello'])
|
const list = observable(['Hello'])
|
||||||
autorun(() => (dummy = list.join(' ')))
|
effect(() => (dummy = list.join(' ')))
|
||||||
|
|
||||||
expect(dummy).toBe('Hello')
|
expect(dummy).toBe('Hello')
|
||||||
list.push('World!')
|
list.push('World!')
|
||||||
@ -168,7 +168,7 @@ describe('observer/autorun', () => {
|
|||||||
it('should observe implicit array length changes', () => {
|
it('should observe implicit array length changes', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const list = observable(['Hello'])
|
const list = observable(['Hello'])
|
||||||
autorun(() => (dummy = list.join(' ')))
|
effect(() => (dummy = list.join(' ')))
|
||||||
|
|
||||||
expect(dummy).toBe('Hello')
|
expect(dummy).toBe('Hello')
|
||||||
list[1] = 'World!'
|
list[1] = 'World!'
|
||||||
@ -181,7 +181,7 @@ describe('observer/autorun', () => {
|
|||||||
let dummy
|
let dummy
|
||||||
const list: any[] = observable([])
|
const list: any[] = observable([])
|
||||||
list[1] = 'World!'
|
list[1] = 'World!'
|
||||||
autorun(() => (dummy = list.join(' ')))
|
effect(() => (dummy = list.join(' ')))
|
||||||
|
|
||||||
expect(dummy).toBe(' World!')
|
expect(dummy).toBe(' World!')
|
||||||
list[0] = 'Hello'
|
list[0] = 'Hello'
|
||||||
@ -193,7 +193,7 @@ describe('observer/autorun', () => {
|
|||||||
it('should observe enumeration', () => {
|
it('should observe enumeration', () => {
|
||||||
let dummy = 0
|
let dummy = 0
|
||||||
const numbers: any = observable({ num1: 3 })
|
const numbers: any = observable({ num1: 3 })
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = 0
|
dummy = 0
|
||||||
for (let key in numbers) {
|
for (let key in numbers) {
|
||||||
dummy += numbers[key]
|
dummy += numbers[key]
|
||||||
@ -211,8 +211,8 @@ describe('observer/autorun', () => {
|
|||||||
const key = Symbol('symbol keyed prop')
|
const key = Symbol('symbol keyed prop')
|
||||||
let dummy, hasDummy
|
let dummy, hasDummy
|
||||||
const obj = observable({ [key]: 'value' })
|
const obj = observable({ [key]: 'value' })
|
||||||
autorun(() => (dummy = obj[key]))
|
effect(() => (dummy = obj[key]))
|
||||||
autorun(() => (hasDummy = key in obj))
|
effect(() => (hasDummy = key in obj))
|
||||||
|
|
||||||
expect(dummy).toBe('value')
|
expect(dummy).toBe('value')
|
||||||
expect(hasDummy).toBe(true)
|
expect(hasDummy).toBe(true)
|
||||||
@ -227,7 +227,7 @@ describe('observer/autorun', () => {
|
|||||||
const key = Symbol.isConcatSpreadable
|
const key = Symbol.isConcatSpreadable
|
||||||
let dummy
|
let dummy
|
||||||
const array: any = observable([])
|
const array: any = observable([])
|
||||||
autorun(() => (dummy = array[key]))
|
effect(() => (dummy = array[key]))
|
||||||
|
|
||||||
expect(array[key]).toBe(undefined)
|
expect(array[key]).toBe(undefined)
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
@ -242,7 +242,7 @@ describe('observer/autorun', () => {
|
|||||||
|
|
||||||
let dummy
|
let dummy
|
||||||
const obj = observable({ func: oldFunc })
|
const obj = observable({ func: oldFunc })
|
||||||
autorun(() => (dummy = obj.func))
|
effect(() => (dummy = obj.func))
|
||||||
|
|
||||||
expect(dummy).toBe(oldFunc)
|
expect(dummy).toBe(oldFunc)
|
||||||
obj.func = newFunc
|
obj.func = newFunc
|
||||||
@ -255,8 +255,8 @@ describe('observer/autorun', () => {
|
|||||||
|
|
||||||
const getSpy = jest.fn(() => (getDummy = obj.prop))
|
const getSpy = jest.fn(() => (getDummy = obj.prop))
|
||||||
const hasSpy = jest.fn(() => (hasDummy = 'prop' in obj))
|
const hasSpy = jest.fn(() => (hasDummy = 'prop' in obj))
|
||||||
autorun(getSpy)
|
effect(getSpy)
|
||||||
autorun(hasSpy)
|
effect(hasSpy)
|
||||||
|
|
||||||
expect(getDummy).toBe('value')
|
expect(getDummy).toBe('value')
|
||||||
expect(hasDummy).toBe(true)
|
expect(hasDummy).toBe(true)
|
||||||
@ -270,7 +270,7 @@ describe('observer/autorun', () => {
|
|||||||
it('should not observe raw mutations', () => {
|
it('should not observe raw mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const obj: any = observable()
|
const obj: any = observable()
|
||||||
autorun(() => (dummy = unwrap(obj).prop))
|
effect(() => (dummy = unwrap(obj).prop))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
obj.prop = 'value'
|
obj.prop = 'value'
|
||||||
@ -280,7 +280,7 @@ describe('observer/autorun', () => {
|
|||||||
it('should not be triggered by raw mutations', () => {
|
it('should not be triggered by raw mutations', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const obj: any = observable()
|
const obj: any = observable()
|
||||||
autorun(() => (dummy = obj.prop))
|
effect(() => (dummy = obj.prop))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
unwrap(obj).prop = 'value'
|
unwrap(obj).prop = 'value'
|
||||||
@ -299,8 +299,8 @@ describe('observer/autorun', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
Object.setPrototypeOf(obj, parent)
|
Object.setPrototypeOf(obj, parent)
|
||||||
autorun(() => (dummy = obj.prop))
|
effect(() => (dummy = obj.prop))
|
||||||
autorun(() => (parentDummy = parent.prop))
|
effect(() => (parentDummy = parent.prop))
|
||||||
|
|
||||||
expect(dummy).toBe(undefined)
|
expect(dummy).toBe(undefined)
|
||||||
expect(parentDummy).toBe(undefined)
|
expect(parentDummy).toBe(undefined)
|
||||||
@ -313,7 +313,7 @@ describe('observer/autorun', () => {
|
|||||||
const counter = observable({ num: 0 })
|
const counter = observable({ num: 0 })
|
||||||
|
|
||||||
const counterSpy = jest.fn(() => counter.num++)
|
const counterSpy = jest.fn(() => counter.num++)
|
||||||
autorun(counterSpy)
|
effect(counterSpy)
|
||||||
expect(counter.num).toBe(1)
|
expect(counter.num).toBe(1)
|
||||||
expect(counterSpy).toHaveBeenCalledTimes(1)
|
expect(counterSpy).toHaveBeenCalledTimes(1)
|
||||||
counter.num = 4
|
counter.num = 4
|
||||||
@ -329,18 +329,18 @@ describe('observer/autorun', () => {
|
|||||||
numSpy()
|
numSpy()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
autorun(numSpy)
|
effect(numSpy)
|
||||||
expect(counter.num).toEqual(10)
|
expect(counter.num).toEqual(10)
|
||||||
expect(numSpy).toHaveBeenCalledTimes(10)
|
expect(numSpy).toHaveBeenCalledTimes(10)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should avoid infinite loops with other autoruns', () => {
|
it('should avoid infinite loops with other effects', () => {
|
||||||
const nums = observable({ num1: 0, num2: 1 })
|
const nums = observable({ num1: 0, num2: 1 })
|
||||||
|
|
||||||
const spy1 = jest.fn(() => (nums.num1 = nums.num2))
|
const spy1 = jest.fn(() => (nums.num1 = nums.num2))
|
||||||
const spy2 = jest.fn(() => (nums.num2 = nums.num1))
|
const spy2 = jest.fn(() => (nums.num2 = nums.num1))
|
||||||
autorun(spy1)
|
effect(spy1)
|
||||||
autorun(spy2)
|
effect(spy2)
|
||||||
expect(nums.num1).toBe(1)
|
expect(nums.num1).toBe(1)
|
||||||
expect(nums.num2).toBe(1)
|
expect(nums.num2).toBe(1)
|
||||||
expect(spy1).toHaveBeenCalledTimes(1)
|
expect(spy1).toHaveBeenCalledTimes(1)
|
||||||
@ -361,12 +361,12 @@ describe('observer/autorun', () => {
|
|||||||
function greet() {
|
function greet() {
|
||||||
return 'Hello World'
|
return 'Hello World'
|
||||||
}
|
}
|
||||||
const autorun1 = autorun(greet)
|
const effect1 = effect(greet)
|
||||||
const autorun2 = autorun(greet)
|
const effect2 = effect(greet)
|
||||||
expect(typeof autorun1).toBe('function')
|
expect(typeof effect1).toBe('function')
|
||||||
expect(typeof autorun2).toBe('function')
|
expect(typeof effect2).toBe('function')
|
||||||
expect(autorun1).not.toBe(greet)
|
expect(effect1).not.toBe(greet)
|
||||||
expect(autorun1).not.toBe(autorun2)
|
expect(effect1).not.toBe(effect2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should discover new branches while running automatically', () => {
|
it('should discover new branches while running automatically', () => {
|
||||||
@ -376,7 +376,7 @@ describe('observer/autorun', () => {
|
|||||||
const conditionalSpy = jest.fn(() => {
|
const conditionalSpy = jest.fn(() => {
|
||||||
dummy = obj.run ? obj.prop : 'other'
|
dummy = obj.run ? obj.prop : 'other'
|
||||||
})
|
})
|
||||||
autorun(conditionalSpy)
|
effect(conditionalSpy)
|
||||||
|
|
||||||
expect(dummy).toBe('other')
|
expect(dummy).toBe('other')
|
||||||
expect(conditionalSpy).toHaveBeenCalledTimes(1)
|
expect(conditionalSpy).toHaveBeenCalledTimes(1)
|
||||||
@ -395,7 +395,7 @@ describe('observer/autorun', () => {
|
|||||||
let dummy
|
let dummy
|
||||||
let run = false
|
let run = false
|
||||||
const obj = observable({ prop: 'value' })
|
const obj = observable({ prop: 'value' })
|
||||||
const runner = autorun(() => {
|
const runner = effect(() => {
|
||||||
dummy = run ? obj.prop : 'other'
|
dummy = run ? obj.prop : 'other'
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -416,7 +416,7 @@ describe('observer/autorun', () => {
|
|||||||
const conditionalSpy = jest.fn(() => {
|
const conditionalSpy = jest.fn(() => {
|
||||||
dummy = obj.run ? obj.prop : 'other'
|
dummy = obj.run ? obj.prop : 'other'
|
||||||
})
|
})
|
||||||
autorun(conditionalSpy)
|
effect(conditionalSpy)
|
||||||
|
|
||||||
expect(dummy).toBe('value')
|
expect(dummy).toBe('value')
|
||||||
expect(conditionalSpy).toHaveBeenCalledTimes(1)
|
expect(conditionalSpy).toHaveBeenCalledTimes(1)
|
||||||
@ -428,9 +428,9 @@ describe('observer/autorun', () => {
|
|||||||
expect(conditionalSpy).toHaveBeenCalledTimes(2)
|
expect(conditionalSpy).toHaveBeenCalledTimes(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not double wrap if the passed function is a autorun', () => {
|
it('should not double wrap if the passed function is a effect', () => {
|
||||||
const runner = autorun(() => {})
|
const runner = effect(() => {})
|
||||||
const otherRunner = autorun(runner)
|
const otherRunner = effect(runner)
|
||||||
expect(runner).not.toBe(otherRunner)
|
expect(runner).not.toBe(otherRunner)
|
||||||
expect(runner.raw).toBe(otherRunner.raw)
|
expect(runner.raw).toBe(otherRunner.raw)
|
||||||
})
|
})
|
||||||
@ -444,7 +444,7 @@ describe('observer/autorun', () => {
|
|||||||
}
|
}
|
||||||
dummy = obj.prop
|
dummy = obj.prop
|
||||||
})
|
})
|
||||||
autorun(fnSpy)
|
effect(fnSpy)
|
||||||
|
|
||||||
expect(fnSpy).toHaveBeenCalledTimes(1)
|
expect(fnSpy).toHaveBeenCalledTimes(1)
|
||||||
obj.prop = 16
|
obj.prop = 16
|
||||||
@ -452,33 +452,33 @@ describe('observer/autorun', () => {
|
|||||||
expect(fnSpy).toHaveBeenCalledTimes(2)
|
expect(fnSpy).toHaveBeenCalledTimes(2)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should allow nested autoruns', () => {
|
it('should allow nested effects', () => {
|
||||||
const nums = observable({ num1: 0, num2: 1, num3: 2 })
|
const nums = observable({ num1: 0, num2: 1, num3: 2 })
|
||||||
const dummy: any = {}
|
const dummy: any = {}
|
||||||
|
|
||||||
const childSpy = jest.fn(() => (dummy.num1 = nums.num1))
|
const childSpy = jest.fn(() => (dummy.num1 = nums.num1))
|
||||||
const childautorun = autorun(childSpy)
|
const childeffect = effect(childSpy)
|
||||||
const parentSpy = jest.fn(() => {
|
const parentSpy = jest.fn(() => {
|
||||||
dummy.num2 = nums.num2
|
dummy.num2 = nums.num2
|
||||||
childautorun()
|
childeffect()
|
||||||
dummy.num3 = nums.num3
|
dummy.num3 = nums.num3
|
||||||
})
|
})
|
||||||
autorun(parentSpy)
|
effect(parentSpy)
|
||||||
|
|
||||||
expect(dummy).toEqual({ num1: 0, num2: 1, num3: 2 })
|
expect(dummy).toEqual({ num1: 0, num2: 1, num3: 2 })
|
||||||
expect(parentSpy).toHaveBeenCalledTimes(1)
|
expect(parentSpy).toHaveBeenCalledTimes(1)
|
||||||
expect(childSpy).toHaveBeenCalledTimes(2)
|
expect(childSpy).toHaveBeenCalledTimes(2)
|
||||||
// this should only call the childautorun
|
// this should only call the childeffect
|
||||||
nums.num1 = 4
|
nums.num1 = 4
|
||||||
expect(dummy).toEqual({ num1: 4, num2: 1, num3: 2 })
|
expect(dummy).toEqual({ num1: 4, num2: 1, num3: 2 })
|
||||||
expect(parentSpy).toHaveBeenCalledTimes(1)
|
expect(parentSpy).toHaveBeenCalledTimes(1)
|
||||||
expect(childSpy).toHaveBeenCalledTimes(3)
|
expect(childSpy).toHaveBeenCalledTimes(3)
|
||||||
// this calls the parentautorun, which calls the childautorun once
|
// this calls the parenteffect, which calls the childeffect once
|
||||||
nums.num2 = 10
|
nums.num2 = 10
|
||||||
expect(dummy).toEqual({ num1: 4, num2: 10, num3: 2 })
|
expect(dummy).toEqual({ num1: 4, num2: 10, num3: 2 })
|
||||||
expect(parentSpy).toHaveBeenCalledTimes(2)
|
expect(parentSpy).toHaveBeenCalledTimes(2)
|
||||||
expect(childSpy).toHaveBeenCalledTimes(4)
|
expect(childSpy).toHaveBeenCalledTimes(4)
|
||||||
// this calls the parentautorun, which calls the childautorun once
|
// this calls the parenteffect, which calls the childeffect once
|
||||||
nums.num3 = 7
|
nums.num3 = 7
|
||||||
expect(dummy).toEqual({ num1: 4, num2: 10, num3: 7 })
|
expect(dummy).toEqual({ num1: 4, num2: 10, num3: 7 })
|
||||||
expect(parentSpy).toHaveBeenCalledTimes(3)
|
expect(parentSpy).toHaveBeenCalledTimes(3)
|
||||||
@ -497,7 +497,7 @@ describe('observer/autorun', () => {
|
|||||||
}
|
}
|
||||||
const model = observable(new Model())
|
const model = observable(new Model())
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = model.count
|
dummy = model.count
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(0)
|
expect(dummy).toBe(0)
|
||||||
@ -511,7 +511,7 @@ describe('observer/autorun', () => {
|
|||||||
runner = _runner
|
runner = _runner
|
||||||
})
|
})
|
||||||
const obj = observable({ foo: 1 })
|
const obj = observable({ foo: 1 })
|
||||||
autorun(
|
effect(
|
||||||
() => {
|
() => {
|
||||||
dummy = obj.foo
|
dummy = obj.foo
|
||||||
},
|
},
|
||||||
@ -537,7 +537,7 @@ describe('observer/autorun', () => {
|
|||||||
events.push(e)
|
events.push(e)
|
||||||
})
|
})
|
||||||
const obj = observable({ foo: 1, bar: 2 })
|
const obj = observable({ foo: 1, bar: 2 })
|
||||||
const runner = autorun(
|
const runner = effect(
|
||||||
() => {
|
() => {
|
||||||
dummy = obj.foo
|
dummy = obj.foo
|
||||||
dummy = 'bar' in obj
|
dummy = 'bar' in obj
|
||||||
@ -549,19 +549,19 @@ describe('observer/autorun', () => {
|
|||||||
expect(onTrack).toHaveBeenCalledTimes(3)
|
expect(onTrack).toHaveBeenCalledTimes(3)
|
||||||
expect(events).toEqual([
|
expect(events).toEqual([
|
||||||
{
|
{
|
||||||
runner,
|
effect: runner,
|
||||||
target: unwrap(obj),
|
target: unwrap(obj),
|
||||||
type: OperationTypes.GET,
|
type: OperationTypes.GET,
|
||||||
key: 'foo'
|
key: 'foo'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
runner,
|
effect: runner,
|
||||||
target: unwrap(obj),
|
target: unwrap(obj),
|
||||||
type: OperationTypes.HAS,
|
type: OperationTypes.HAS,
|
||||||
key: 'bar'
|
key: 'bar'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
runner,
|
effect: runner,
|
||||||
target: unwrap(obj),
|
target: unwrap(obj),
|
||||||
type: OperationTypes.ITERATE,
|
type: OperationTypes.ITERATE,
|
||||||
key: ITERATE_KEY
|
key: ITERATE_KEY
|
||||||
@ -576,7 +576,7 @@ describe('observer/autorun', () => {
|
|||||||
events.push(e)
|
events.push(e)
|
||||||
})
|
})
|
||||||
const obj = observable({ foo: 1 })
|
const obj = observable({ foo: 1 })
|
||||||
const runner = autorun(
|
const runner = effect(
|
||||||
() => {
|
() => {
|
||||||
dummy = obj.foo
|
dummy = obj.foo
|
||||||
},
|
},
|
||||||
@ -587,7 +587,7 @@ describe('observer/autorun', () => {
|
|||||||
expect(dummy).toBe(2)
|
expect(dummy).toBe(2)
|
||||||
expect(onTrigger).toHaveBeenCalledTimes(1)
|
expect(onTrigger).toHaveBeenCalledTimes(1)
|
||||||
expect(events[0]).toEqual({
|
expect(events[0]).toEqual({
|
||||||
runner,
|
effect: runner,
|
||||||
target: unwrap(obj),
|
target: unwrap(obj),
|
||||||
type: OperationTypes.SET,
|
type: OperationTypes.SET,
|
||||||
key: 'foo',
|
key: 'foo',
|
||||||
@ -599,7 +599,7 @@ describe('observer/autorun', () => {
|
|||||||
expect(dummy).toBeUndefined()
|
expect(dummy).toBeUndefined()
|
||||||
expect(onTrigger).toHaveBeenCalledTimes(2)
|
expect(onTrigger).toHaveBeenCalledTimes(2)
|
||||||
expect(events[1]).toEqual({
|
expect(events[1]).toEqual({
|
||||||
runner,
|
effect: runner,
|
||||||
target: unwrap(obj),
|
target: unwrap(obj),
|
||||||
type: OperationTypes.DELETE,
|
type: OperationTypes.DELETE,
|
||||||
key: 'foo',
|
key: 'foo',
|
||||||
@ -610,7 +610,7 @@ describe('observer/autorun', () => {
|
|||||||
it('stop', () => {
|
it('stop', () => {
|
||||||
let dummy
|
let dummy
|
||||||
const obj = observable({ prop: 1 })
|
const obj = observable({ prop: 1 })
|
||||||
const runner = autorun(() => {
|
const runner = effect(() => {
|
||||||
dummy = obj.prop
|
dummy = obj.prop
|
||||||
})
|
})
|
||||||
obj.prop = 2
|
obj.prop = 2
|
||||||
@ -619,7 +619,7 @@ describe('observer/autorun', () => {
|
|||||||
obj.prop = 3
|
obj.prop = 3
|
||||||
expect(dummy).toBe(2)
|
expect(dummy).toBe(2)
|
||||||
|
|
||||||
// stopped runner should still be manually callable
|
// stopped effect should still be manually callable
|
||||||
runner()
|
runner()
|
||||||
expect(dummy).toBe(3)
|
expect(dummy).toBe(3)
|
||||||
})
|
})
|
||||||
@ -631,7 +631,7 @@ describe('observer/autorun', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = obj.foo.prop
|
dummy = obj.foo.prop
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(0)
|
expect(dummy).toBe(0)
|
@ -8,7 +8,7 @@ import {
|
|||||||
markImmutable,
|
markImmutable,
|
||||||
lock,
|
lock,
|
||||||
unlock,
|
unlock,
|
||||||
autorun
|
effect
|
||||||
} from '../src'
|
} from '../src'
|
||||||
|
|
||||||
describe('observer/immutable', () => {
|
describe('observer/immutable', () => {
|
||||||
@ -75,10 +75,10 @@ describe('observer/immutable', () => {
|
|||||||
expect(warn).not.toHaveBeenCalled()
|
expect(warn).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not trigger autoruns when locked', () => {
|
it('should not trigger effects when locked', () => {
|
||||||
const observed = immutable({ a: 1 })
|
const observed = immutable({ a: 1 })
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = observed.a
|
dummy = observed.a
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(1)
|
expect(dummy).toBe(1)
|
||||||
@ -87,10 +87,10 @@ describe('observer/immutable', () => {
|
|||||||
expect(dummy).toBe(1)
|
expect(dummy).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should trigger autoruns when unlocked', () => {
|
it('should trigger effects when unlocked', () => {
|
||||||
const observed = immutable({ a: 1 })
|
const observed = immutable({ a: 1 })
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = observed.a
|
dummy = observed.a
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(1)
|
expect(dummy).toBe(1)
|
||||||
@ -161,10 +161,10 @@ describe('observer/immutable', () => {
|
|||||||
expect(warn).not.toHaveBeenCalled()
|
expect(warn).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not trigger autoruns when locked', () => {
|
it('should not trigger effects when locked', () => {
|
||||||
const observed = immutable([{ a: 1 }])
|
const observed = immutable([{ a: 1 }])
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = observed[0].a
|
dummy = observed[0].a
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(1)
|
expect(dummy).toBe(1)
|
||||||
@ -176,10 +176,10 @@ describe('observer/immutable', () => {
|
|||||||
expect(dummy).toBe(1)
|
expect(dummy).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should trigger autoruns when unlocked', () => {
|
it('should trigger effects when unlocked', () => {
|
||||||
const observed = immutable([{ a: 1 }])
|
const observed = immutable([{ a: 1 }])
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = observed[0].a
|
dummy = observed[0].a
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(1)
|
expect(dummy).toBe(1)
|
||||||
@ -220,11 +220,11 @@ describe('observer/immutable', () => {
|
|||||||
expect(isImmutable(original.get(key1))).toBe(false)
|
expect(isImmutable(original.get(key1))).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not allow mutation & not trigger autorun', () => {
|
test('should not allow mutation & not trigger effect', () => {
|
||||||
const map = immutable(new Collection())
|
const map = immutable(new Collection())
|
||||||
const key = {}
|
const key = {}
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = map.get(key)
|
dummy = map.get(key)
|
||||||
})
|
})
|
||||||
expect(dummy).toBeUndefined()
|
expect(dummy).toBeUndefined()
|
||||||
@ -234,12 +234,12 @@ describe('observer/immutable', () => {
|
|||||||
expect(warn).toHaveBeenCalledTimes(1)
|
expect(warn).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should allow mutation & trigger autorun when unlocked', () => {
|
test('should allow mutation & trigger effect when unlocked', () => {
|
||||||
const map = immutable(new Collection())
|
const map = immutable(new Collection())
|
||||||
const isWeak = Collection === WeakMap
|
const isWeak = Collection === WeakMap
|
||||||
const key = {}
|
const key = {}
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = map.get(key) + (isWeak ? 0 : map.size)
|
dummy = map.get(key) + (isWeak ? 0 : map.size)
|
||||||
})
|
})
|
||||||
expect(dummy).toBeNaN()
|
expect(dummy).toBeNaN()
|
||||||
@ -289,11 +289,11 @@ describe('observer/immutable', () => {
|
|||||||
expect(original.has(observable(key1))).toBe(false)
|
expect(original.has(observable(key1))).toBe(false)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not allow mutation & not trigger autorun', () => {
|
test('should not allow mutation & not trigger effect', () => {
|
||||||
const set = immutable(new Collection())
|
const set = immutable(new Collection())
|
||||||
const key = {}
|
const key = {}
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = set.has(key)
|
dummy = set.has(key)
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
@ -303,11 +303,11 @@ describe('observer/immutable', () => {
|
|||||||
expect(warn).toHaveBeenCalledTimes(1)
|
expect(warn).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should allow mutation & trigger autorun when unlocked', () => {
|
test('should allow mutation & trigger effect when unlocked', () => {
|
||||||
const set = immutable(new Collection())
|
const set = immutable(new Collection())
|
||||||
const key = {}
|
const key = {}
|
||||||
let dummy
|
let dummy
|
||||||
autorun(() => {
|
effect(() => {
|
||||||
dummy = set.has(key)
|
dummy = set.has(key)
|
||||||
})
|
})
|
||||||
expect(dummy).toBe(false)
|
expect(dummy).toBe(false)
|
||||||
|
@ -1,180 +0,0 @@
|
|||||||
import { OperationTypes } from './operations'
|
|
||||||
import { Dep, KeyToDepMap, targetMap } from './state'
|
|
||||||
|
|
||||||
export interface Autorun {
|
|
||||||
(): any
|
|
||||||
isAutorun: true
|
|
||||||
active: boolean
|
|
||||||
raw: Function
|
|
||||||
deps: Array<Dep>
|
|
||||||
computed?: boolean
|
|
||||||
scheduler?: Scheduler
|
|
||||||
onTrack?: Debugger
|
|
||||||
onTrigger?: Debugger
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AutorunOptions {
|
|
||||||
lazy?: boolean
|
|
||||||
scheduler?: Scheduler
|
|
||||||
onTrack?: Debugger
|
|
||||||
onTrigger?: Debugger
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Scheduler = (run: () => any) => void
|
|
||||||
|
|
||||||
export type DebuggerEvent = {
|
|
||||||
runner: Autorun
|
|
||||||
target: any
|
|
||||||
type: OperationTypes
|
|
||||||
key: string | symbol | undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
export type Debugger = (event: DebuggerEvent) => void
|
|
||||||
|
|
||||||
export const activeAutorunStack: Autorun[] = []
|
|
||||||
|
|
||||||
export const ITERATE_KEY = Symbol('iterate')
|
|
||||||
|
|
||||||
export function createAutorun(fn: Function, options: AutorunOptions): Autorun {
|
|
||||||
const runner = function runner(...args): any {
|
|
||||||
return run(runner as Autorun, fn, args)
|
|
||||||
} as Autorun
|
|
||||||
runner.isAutorun = true
|
|
||||||
runner.active = true
|
|
||||||
runner.raw = fn
|
|
||||||
runner.scheduler = options.scheduler
|
|
||||||
runner.onTrack = options.onTrack
|
|
||||||
runner.onTrigger = options.onTrigger
|
|
||||||
runner.deps = []
|
|
||||||
return runner
|
|
||||||
}
|
|
||||||
|
|
||||||
function run(runner: Autorun, fn: Function, args: any[]): any {
|
|
||||||
if (!runner.active) {
|
|
||||||
return fn(...args)
|
|
||||||
}
|
|
||||||
if (activeAutorunStack.indexOf(runner) === -1) {
|
|
||||||
cleanup(runner)
|
|
||||||
try {
|
|
||||||
activeAutorunStack.push(runner)
|
|
||||||
return fn(...args)
|
|
||||||
} finally {
|
|
||||||
activeAutorunStack.pop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function cleanup(runner: Autorun) {
|
|
||||||
for (let i = 0; i < runner.deps.length; i++) {
|
|
||||||
runner.deps[i].delete(runner)
|
|
||||||
}
|
|
||||||
runner.deps = []
|
|
||||||
}
|
|
||||||
|
|
||||||
export function track(
|
|
||||||
target: any,
|
|
||||||
type: OperationTypes,
|
|
||||||
key?: string | symbol
|
|
||||||
) {
|
|
||||||
const runner = activeAutorunStack[activeAutorunStack.length - 1]
|
|
||||||
if (runner) {
|
|
||||||
if (type === OperationTypes.ITERATE) {
|
|
||||||
key = ITERATE_KEY
|
|
||||||
}
|
|
||||||
// keyMap must exist because only an observed target can call this function
|
|
||||||
const depsMap = targetMap.get(target) as KeyToDepMap
|
|
||||||
let dep = depsMap.get(key as string | symbol)
|
|
||||||
if (!dep) {
|
|
||||||
depsMap.set(key as string | symbol, (dep = new Set()))
|
|
||||||
}
|
|
||||||
if (!dep.has(runner)) {
|
|
||||||
dep.add(runner)
|
|
||||||
runner.deps.push(dep)
|
|
||||||
if (__DEV__ && runner.onTrack) {
|
|
||||||
runner.onTrack({
|
|
||||||
runner,
|
|
||||||
target,
|
|
||||||
type,
|
|
||||||
key
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trigger(
|
|
||||||
target: any,
|
|
||||||
type: OperationTypes,
|
|
||||||
key?: string | symbol,
|
|
||||||
extraInfo?: any
|
|
||||||
) {
|
|
||||||
const depsMap = targetMap.get(target) as KeyToDepMap
|
|
||||||
const runners = new Set()
|
|
||||||
const computedRunners = new Set()
|
|
||||||
if (type === OperationTypes.CLEAR) {
|
|
||||||
// collection being cleared, trigger all runners for target
|
|
||||||
depsMap.forEach(dep => {
|
|
||||||
addRunners(runners, computedRunners, dep)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// schedule runs for SET | ADD | DELETE
|
|
||||||
if (key !== void 0) {
|
|
||||||
addRunners(runners, computedRunners, depsMap.get(key as string | symbol))
|
|
||||||
}
|
|
||||||
// also run for iteration key on ADD | DELETE
|
|
||||||
if (type === OperationTypes.ADD || type === OperationTypes.DELETE) {
|
|
||||||
const iterationKey = Array.isArray(target) ? 'length' : ITERATE_KEY
|
|
||||||
addRunners(runners, computedRunners, depsMap.get(iterationKey))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const run = (runner: Autorun) => {
|
|
||||||
scheduleRun(runner, target, type, key, extraInfo)
|
|
||||||
}
|
|
||||||
// Important: computed runners must be run first so that computed getters
|
|
||||||
// can be invalidated before any normal runners that depend on them are run.
|
|
||||||
computedRunners.forEach(run)
|
|
||||||
runners.forEach(run)
|
|
||||||
}
|
|
||||||
|
|
||||||
function addRunners(
|
|
||||||
runners: Set<Autorun>,
|
|
||||||
computedRunners: Set<Autorun>,
|
|
||||||
runnersToAdd: Set<Autorun> | undefined
|
|
||||||
) {
|
|
||||||
if (runnersToAdd !== void 0) {
|
|
||||||
runnersToAdd.forEach(runner => {
|
|
||||||
if (runner.computed) {
|
|
||||||
computedRunners.add(runner)
|
|
||||||
} else {
|
|
||||||
runners.add(runner)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function scheduleRun(
|
|
||||||
runner: Autorun,
|
|
||||||
target: any,
|
|
||||||
type: OperationTypes,
|
|
||||||
key: string | symbol | undefined,
|
|
||||||
extraInfo: any
|
|
||||||
) {
|
|
||||||
if (__DEV__ && runner.onTrigger) {
|
|
||||||
runner.onTrigger(
|
|
||||||
Object.assign(
|
|
||||||
{
|
|
||||||
runner,
|
|
||||||
target,
|
|
||||||
key,
|
|
||||||
type
|
|
||||||
},
|
|
||||||
extraInfo
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (runner.scheduler !== void 0) {
|
|
||||||
runner.scheduler(runner)
|
|
||||||
} else {
|
|
||||||
runner()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
import { observable, immutable, unwrap } from './index'
|
import { observable, immutable, unwrap } from './index'
|
||||||
import { OperationTypes } from './operations'
|
import { OperationTypes } from './operations'
|
||||||
import { track, trigger } from './autorun'
|
import { track, trigger } from './effect'
|
||||||
import { LOCKED } from './lock'
|
import { LOCKED } from './lock'
|
||||||
import { isObject } from '@vue/shared'
|
import { isObject } from '@vue/shared'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { unwrap, observable, immutable } from './index'
|
import { unwrap, observable, immutable } from './index'
|
||||||
import { track, trigger } from './autorun'
|
import { track, trigger } from './effect'
|
||||||
import { OperationTypes } from './operations'
|
import { OperationTypes } from './operations'
|
||||||
import { LOCKED } from './lock'
|
import { LOCKED } from './lock'
|
||||||
import { isObject } from '@vue/shared'
|
import { isObject } from '@vue/shared'
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { autorun } from './index'
|
import { effect } from './index'
|
||||||
import { Autorun, activeAutorunStack } from './autorun'
|
import { ReactiveEffect, activeReactiveEffectStack } from './effect'
|
||||||
|
|
||||||
export interface ComputedGetter<T = any> {
|
export interface ComputedGetter<T = any> {
|
||||||
(): T
|
(): T
|
||||||
runner: Autorun
|
effect: ReactiveEffect
|
||||||
}
|
}
|
||||||
|
|
||||||
export function computed<T, C = null>(
|
export function computed<T, C = null>(
|
||||||
@ -12,7 +12,7 @@ export function computed<T, C = null>(
|
|||||||
): ComputedGetter<T> {
|
): ComputedGetter<T> {
|
||||||
let dirty: boolean = true
|
let dirty: boolean = true
|
||||||
let value: any = undefined
|
let value: any = undefined
|
||||||
const runner = autorun(() => getter.call(context, context), {
|
const runner = effect(() => getter.call(context, context), {
|
||||||
lazy: true,
|
lazy: true,
|
||||||
scheduler: () => {
|
scheduler: () => {
|
||||||
dirty = true
|
dirty = true
|
||||||
@ -23,21 +23,22 @@ export function computed<T, C = null>(
|
|||||||
value = runner()
|
value = runner()
|
||||||
dirty = false
|
dirty = false
|
||||||
}
|
}
|
||||||
// When computed autoruns are accessed in a parent autorun, the parent
|
// When computed effects are accessed in a parent effect, the parent
|
||||||
// should track all the dependencies the computed property has tracked.
|
// should track all the dependencies the computed property has tracked.
|
||||||
// This should also apply for chained computed properties.
|
// This should also apply for chained computed properties.
|
||||||
trackChildRun(runner)
|
trackChildRun(runner)
|
||||||
return value
|
return value
|
||||||
}) as ComputedGetter
|
}) as ComputedGetter
|
||||||
// expose runner so computed can be stopped
|
// expose effect so computed can be stopped
|
||||||
computedGetter.runner = runner
|
computedGetter.effect = runner
|
||||||
// mark runner as computed so that it gets priority during trigger
|
// mark effect as computed so that it gets priority during trigger
|
||||||
runner.computed = true
|
runner.computed = true
|
||||||
return computedGetter
|
return computedGetter
|
||||||
}
|
}
|
||||||
|
|
||||||
function trackChildRun(childRunner: Autorun) {
|
function trackChildRun(childRunner: ReactiveEffect) {
|
||||||
const parentRunner = activeAutorunStack[activeAutorunStack.length - 1]
|
const parentRunner =
|
||||||
|
activeReactiveEffectStack[activeReactiveEffectStack.length - 1]
|
||||||
if (parentRunner) {
|
if (parentRunner) {
|
||||||
for (let i = 0; i < childRunner.deps.length; i++) {
|
for (let i = 0; i < childRunner.deps.length; i++) {
|
||||||
const dep = childRunner.deps[i]
|
const dep = childRunner.deps[i]
|
||||||
|
183
packages/observer/src/effect.ts
Normal file
183
packages/observer/src/effect.ts
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
import { OperationTypes } from './operations'
|
||||||
|
import { Dep, KeyToDepMap, targetMap } from './state'
|
||||||
|
|
||||||
|
export interface ReactiveEffect {
|
||||||
|
(): any
|
||||||
|
isEffect: true
|
||||||
|
active: boolean
|
||||||
|
raw: Function
|
||||||
|
deps: Array<Dep>
|
||||||
|
computed?: boolean
|
||||||
|
scheduler?: Scheduler
|
||||||
|
onTrack?: Debugger
|
||||||
|
onTrigger?: Debugger
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReactiveEffectOptions {
|
||||||
|
lazy?: boolean
|
||||||
|
scheduler?: Scheduler
|
||||||
|
onTrack?: Debugger
|
||||||
|
onTrigger?: Debugger
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Scheduler = (run: () => any) => void
|
||||||
|
|
||||||
|
export type DebuggerEvent = {
|
||||||
|
effect: ReactiveEffect
|
||||||
|
target: any
|
||||||
|
type: OperationTypes
|
||||||
|
key: string | symbol | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Debugger = (event: DebuggerEvent) => void
|
||||||
|
|
||||||
|
export const activeReactiveEffectStack: ReactiveEffect[] = []
|
||||||
|
|
||||||
|
export const ITERATE_KEY = Symbol('iterate')
|
||||||
|
|
||||||
|
export function createReactiveEffect(
|
||||||
|
fn: Function,
|
||||||
|
options: ReactiveEffectOptions
|
||||||
|
): ReactiveEffect {
|
||||||
|
const effect = function effect(...args): any {
|
||||||
|
return run(effect as ReactiveEffect, fn, args)
|
||||||
|
} as ReactiveEffect
|
||||||
|
effect.isEffect = true
|
||||||
|
effect.active = true
|
||||||
|
effect.raw = fn
|
||||||
|
effect.scheduler = options.scheduler
|
||||||
|
effect.onTrack = options.onTrack
|
||||||
|
effect.onTrigger = options.onTrigger
|
||||||
|
effect.deps = []
|
||||||
|
return effect
|
||||||
|
}
|
||||||
|
|
||||||
|
function run(effect: ReactiveEffect, fn: Function, args: any[]): any {
|
||||||
|
if (!effect.active) {
|
||||||
|
return fn(...args)
|
||||||
|
}
|
||||||
|
if (activeReactiveEffectStack.indexOf(effect) === -1) {
|
||||||
|
cleanup(effect)
|
||||||
|
try {
|
||||||
|
activeReactiveEffectStack.push(effect)
|
||||||
|
return fn(...args)
|
||||||
|
} finally {
|
||||||
|
activeReactiveEffectStack.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cleanup(effect: ReactiveEffect) {
|
||||||
|
for (let i = 0; i < effect.deps.length; i++) {
|
||||||
|
effect.deps[i].delete(effect)
|
||||||
|
}
|
||||||
|
effect.deps = []
|
||||||
|
}
|
||||||
|
|
||||||
|
export function track(
|
||||||
|
target: any,
|
||||||
|
type: OperationTypes,
|
||||||
|
key?: string | symbol
|
||||||
|
) {
|
||||||
|
const effect = activeReactiveEffectStack[activeReactiveEffectStack.length - 1]
|
||||||
|
if (effect) {
|
||||||
|
if (type === OperationTypes.ITERATE) {
|
||||||
|
key = ITERATE_KEY
|
||||||
|
}
|
||||||
|
// keyMap must exist because only an observed target can call this function
|
||||||
|
const depsMap = targetMap.get(target) as KeyToDepMap
|
||||||
|
let dep = depsMap.get(key as string | symbol)
|
||||||
|
if (!dep) {
|
||||||
|
depsMap.set(key as string | symbol, (dep = new Set()))
|
||||||
|
}
|
||||||
|
if (!dep.has(effect)) {
|
||||||
|
dep.add(effect)
|
||||||
|
effect.deps.push(dep)
|
||||||
|
if (__DEV__ && effect.onTrack) {
|
||||||
|
effect.onTrack({
|
||||||
|
effect,
|
||||||
|
target,
|
||||||
|
type,
|
||||||
|
key
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function trigger(
|
||||||
|
target: any,
|
||||||
|
type: OperationTypes,
|
||||||
|
key?: string | symbol,
|
||||||
|
extraInfo?: any
|
||||||
|
) {
|
||||||
|
const depsMap = targetMap.get(target) as KeyToDepMap
|
||||||
|
const effects = new Set()
|
||||||
|
const computedRunners = new Set()
|
||||||
|
if (type === OperationTypes.CLEAR) {
|
||||||
|
// collection being cleared, trigger all effects for target
|
||||||
|
depsMap.forEach(dep => {
|
||||||
|
addRunners(effects, computedRunners, dep)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// schedule runs for SET | ADD | DELETE
|
||||||
|
if (key !== void 0) {
|
||||||
|
addRunners(effects, computedRunners, depsMap.get(key as string | symbol))
|
||||||
|
}
|
||||||
|
// also run for iteration key on ADD | DELETE
|
||||||
|
if (type === OperationTypes.ADD || type === OperationTypes.DELETE) {
|
||||||
|
const iterationKey = Array.isArray(target) ? 'length' : ITERATE_KEY
|
||||||
|
addRunners(effects, computedRunners, depsMap.get(iterationKey))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const run = (effect: ReactiveEffect) => {
|
||||||
|
scheduleRun(effect, target, type, key, extraInfo)
|
||||||
|
}
|
||||||
|
// Important: computed effects must be run first so that computed getters
|
||||||
|
// can be invalidated before any normal effects that depend on them are run.
|
||||||
|
computedRunners.forEach(run)
|
||||||
|
effects.forEach(run)
|
||||||
|
}
|
||||||
|
|
||||||
|
function addRunners(
|
||||||
|
effects: Set<ReactiveEffect>,
|
||||||
|
computedRunners: Set<ReactiveEffect>,
|
||||||
|
effectsToAdd: Set<ReactiveEffect> | undefined
|
||||||
|
) {
|
||||||
|
if (effectsToAdd !== void 0) {
|
||||||
|
effectsToAdd.forEach(effect => {
|
||||||
|
if (effect.computed) {
|
||||||
|
computedRunners.add(effect)
|
||||||
|
} else {
|
||||||
|
effects.add(effect)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleRun(
|
||||||
|
effect: ReactiveEffect,
|
||||||
|
target: any,
|
||||||
|
type: OperationTypes,
|
||||||
|
key: string | symbol | undefined,
|
||||||
|
extraInfo: any
|
||||||
|
) {
|
||||||
|
if (__DEV__ && effect.onTrigger) {
|
||||||
|
effect.onTrigger(
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
effect,
|
||||||
|
target,
|
||||||
|
key,
|
||||||
|
type
|
||||||
|
},
|
||||||
|
extraInfo
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (effect.scheduler !== void 0) {
|
||||||
|
effect.scheduler(effect)
|
||||||
|
} else {
|
||||||
|
effect()
|
||||||
|
}
|
||||||
|
}
|
@ -17,14 +17,14 @@ import {
|
|||||||
} from './state'
|
} from './state'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createAutorun,
|
createReactiveEffect,
|
||||||
cleanup,
|
cleanup,
|
||||||
Autorun,
|
ReactiveEffect,
|
||||||
AutorunOptions,
|
ReactiveEffectOptions,
|
||||||
DebuggerEvent
|
DebuggerEvent
|
||||||
} from './autorun'
|
} from './effect'
|
||||||
|
|
||||||
export { Autorun, AutorunOptions, DebuggerEvent }
|
export { ReactiveEffect, ReactiveEffectOptions, DebuggerEvent }
|
||||||
export { OperationTypes } from './operations'
|
export { OperationTypes } from './operations'
|
||||||
export { computed, ComputedGetter } from './computed'
|
export { computed, ComputedGetter } from './computed'
|
||||||
export { lock, unlock } from './lock'
|
export { lock, unlock } from './lock'
|
||||||
@ -114,24 +114,24 @@ function createObservable(
|
|||||||
return observed
|
return observed
|
||||||
}
|
}
|
||||||
|
|
||||||
export function autorun(
|
export function effect(
|
||||||
fn: Function,
|
fn: Function,
|
||||||
options: AutorunOptions = EMPTY_OBJ
|
options: ReactiveEffectOptions = EMPTY_OBJ
|
||||||
): Autorun {
|
): ReactiveEffect {
|
||||||
if ((fn as Autorun).isAutorun) {
|
if ((fn as ReactiveEffect).isEffect) {
|
||||||
fn = (fn as Autorun).raw
|
fn = (fn as ReactiveEffect).raw
|
||||||
}
|
}
|
||||||
const runner = createAutorun(fn, options)
|
const effect = createReactiveEffect(fn, options)
|
||||||
if (!options.lazy) {
|
if (!options.lazy) {
|
||||||
runner()
|
effect()
|
||||||
}
|
}
|
||||||
return runner
|
return effect
|
||||||
}
|
}
|
||||||
|
|
||||||
export function stop(runner: Autorun) {
|
export function stop(effect: ReactiveEffect) {
|
||||||
if (runner.active) {
|
if (effect.active) {
|
||||||
cleanup(runner)
|
cleanup(effect)
|
||||||
runner.active = false
|
effect.active = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { Autorun } from './autorun'
|
import { ReactiveEffect } from './effect'
|
||||||
|
|
||||||
// The main WeakMap that stores {target -> key -> dep} connections.
|
// The main WeakMap that stores {target -> key -> dep} connections.
|
||||||
// Conceptually, it's easier to think of a dependency as a Dep class
|
// Conceptually, it's easier to think of a dependency as a Dep class
|
||||||
// which maintains a Set of subscribers, but we simply store them as
|
// which maintains a Set of subscribers, but we simply store them as
|
||||||
// raw Sets to reduce memory overhead.
|
// raw Sets to reduce memory overhead.
|
||||||
export type Dep = Set<Autorun>
|
export type Dep = Set<ReactiveEffect>
|
||||||
export type KeyToDepMap = Map<string | symbol, Dep>
|
export type KeyToDepMap = Map<string | symbol, Dep>
|
||||||
export const targetMap: WeakMap<any, KeyToDepMap> = new WeakMap()
|
export const targetMap: WeakMap<any, KeyToDepMap> = new WeakMap()
|
||||||
|
|
||||||
|
@ -12,7 +12,9 @@ import {
|
|||||||
nextTick,
|
nextTick,
|
||||||
resetOps,
|
resetOps,
|
||||||
dumpOps,
|
dumpOps,
|
||||||
NodeOpTypes
|
NodeOpTypes,
|
||||||
|
createFragment,
|
||||||
|
createTextVNode
|
||||||
} from '@vue/runtime-test'
|
} from '@vue/runtime-test'
|
||||||
|
|
||||||
describe('Fragments', () => {
|
describe('Fragments', () => {
|
||||||
@ -57,9 +59,12 @@ describe('Fragments', () => {
|
|||||||
class App extends Component {
|
class App extends Component {
|
||||||
render() {
|
render() {
|
||||||
return state.ok
|
return state.ok
|
||||||
? h.f([h('div', 'one'), h.t('two')], ChildrenFlags.NONE_KEYED_VNODES)
|
? createFragment(
|
||||||
: h.f(
|
[h('div', 'one'), createTextVNode('two')],
|
||||||
[h('div', 'foo'), h.t('bar'), h.t('baz')],
|
ChildrenFlags.NONE_KEYED_VNODES
|
||||||
|
)
|
||||||
|
: createFragment(
|
||||||
|
[h('div', 'foo'), createTextVNode('bar'), createTextVNode('baz')],
|
||||||
ChildrenFlags.NONE_KEYED_VNODES
|
ChildrenFlags.NONE_KEYED_VNODES
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
WatchOptions
|
WatchOptions
|
||||||
} from './componentOptions'
|
} from './componentOptions'
|
||||||
import { setupWatcher } from './componentWatch'
|
import { setupWatcher } from './componentWatch'
|
||||||
import { Autorun, DebuggerEvent, ComputedGetter } from '@vue/observer'
|
import { ReactiveEffect, DebuggerEvent, ComputedGetter } from '@vue/observer'
|
||||||
import { nextTick } from '@vue/scheduler'
|
import { nextTick } from '@vue/scheduler'
|
||||||
import { ErrorTypes } from './errorHandling'
|
import { ErrorTypes } from './errorHandling'
|
||||||
import { initializeComponentInstance } from './componentUtils'
|
import { initializeComponentInstance } from './componentUtils'
|
||||||
@ -101,7 +101,7 @@ export interface ComponentInstance<P = {}, D = {}>
|
|||||||
$children: ComponentInstance[]
|
$children: ComponentInstance[]
|
||||||
$options: ComponentOptions<P, D>
|
$options: ComponentOptions<P, D>
|
||||||
|
|
||||||
_updateHandle: Autorun
|
_update: ReactiveEffect
|
||||||
_queueJob: ((fn: () => void) => void)
|
_queueJob: ((fn: () => void) => void)
|
||||||
_self: ComponentInstance<P, D> // on proxies only
|
_self: ComponentInstance<P, D> // on proxies only
|
||||||
}
|
}
|
||||||
@ -128,11 +128,11 @@ class InternalComponent implements PublicInstanceMethods {
|
|||||||
|
|
||||||
_rawData: Data | null = null
|
_rawData: Data | null = null
|
||||||
_computedGetters: Record<string, ComputedGetter> | null = null
|
_computedGetters: Record<string, ComputedGetter> | null = null
|
||||||
_watchHandles: Set<Autorun> | null = null
|
_watchHandles: Set<ReactiveEffect> | null = null
|
||||||
_mounted: boolean = false
|
_mounted: boolean = false
|
||||||
_unmounted: boolean = false
|
_unmounted: boolean = false
|
||||||
_events: { [event: string]: Function[] | null } | null = null
|
_events: { [event: string]: Function[] | null } | null = null
|
||||||
_updateHandle: Autorun | null = null
|
_update: ReactiveEffect | null = null
|
||||||
_queueJob: ((fn: () => void) => void) | null = null
|
_queueJob: ((fn: () => void) => void) | null = null
|
||||||
_isVue: boolean = true
|
_isVue: boolean = true
|
||||||
_inactiveRoot: boolean = false
|
_inactiveRoot: boolean = false
|
||||||
|
@ -25,7 +25,7 @@ export function teardownComputed(instance: ComponentInstance) {
|
|||||||
const handles = instance._computedGetters
|
const handles = instance._computedGetters
|
||||||
if (handles !== null) {
|
if (handles !== null) {
|
||||||
for (const key in handles) {
|
for (const key in handles) {
|
||||||
stop(handles[key].runner)
|
stop(handles[key].effect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ export function teardownComponentInstance(instance: ComponentInstance) {
|
|||||||
1
|
1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
stop(instance._updateHandle)
|
stop(instance._update)
|
||||||
teardownComputed(instance)
|
teardownComputed(instance)
|
||||||
teardownWatch(instance)
|
teardownWatch(instance)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { ComponentInstance } from './component'
|
import { ComponentInstance } from './component'
|
||||||
import { ComponentWatchOptions, WatchOptions } from './componentOptions'
|
import { ComponentWatchOptions, WatchOptions } from './componentOptions'
|
||||||
import { autorun, stop } from '@vue/observer'
|
import { effect, stop } from '@vue/observer'
|
||||||
import { queueJob } from '@vue/scheduler'
|
import { queueJob } from '@vue/scheduler'
|
||||||
import { handleError, ErrorTypes } from './errorHandling'
|
import { handleError, ErrorTypes } from './errorHandling'
|
||||||
import { warn } from './warning'
|
import { warn } from './warning'
|
||||||
@ -70,7 +70,7 @@ export function setupWatcher(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const runner = autorun(getter, {
|
const runner = effect(getter, {
|
||||||
lazy: true,
|
lazy: true,
|
||||||
scheduler: options.sync
|
scheduler: options.sync
|
||||||
? applyCb
|
? applyCb
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import {
|
import {
|
||||||
autorun,
|
effect as createReactiveEffect,
|
||||||
stop,
|
stop as stopReactiveEffect,
|
||||||
Autorun,
|
ReactiveEffect,
|
||||||
immutable,
|
immutable,
|
||||||
AutorunOptions
|
ReactiveEffectOptions
|
||||||
} from '@vue/observer'
|
} from '@vue/observer'
|
||||||
import {
|
import {
|
||||||
queueJob,
|
queueJob,
|
||||||
handleSchedulerError,
|
handleSchedulerError,
|
||||||
nextTick,
|
nextTick,
|
||||||
queueEffect,
|
queuePostEffect,
|
||||||
flushEffects,
|
flushEffects,
|
||||||
queueNodeOp
|
queueNodeOp
|
||||||
} from '@vue/scheduler'
|
} from '@vue/scheduler'
|
||||||
@ -78,7 +78,7 @@ export interface RendererOptions {
|
|||||||
export interface FunctionalHandle {
|
export interface FunctionalHandle {
|
||||||
prev: VNode
|
prev: VNode
|
||||||
next: VNode
|
next: VNode
|
||||||
update: Autorun
|
update: ReactiveEffect
|
||||||
container: RenderNode | null
|
container: RenderNode | null
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,12 +206,12 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
queueInsertOrAppend(container, el, endNode)
|
queueInsertOrAppend(container, el, endNode)
|
||||||
}
|
}
|
||||||
if (ref) {
|
if (ref) {
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
ref(el)
|
ref(el)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (data != null && data.vnodeMounted) {
|
if (data != null && data.vnodeMounted) {
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
data.vnodeMounted(vnode)
|
data.vnodeMounted(vnode)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -272,7 +272,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const doMount = () => {
|
const doMount = () => {
|
||||||
handle.update = autorun(
|
handle.update = createReactiveEffect(
|
||||||
() => {
|
() => {
|
||||||
if (!handle.next) {
|
if (!handle.next) {
|
||||||
// initial mount
|
// initial mount
|
||||||
@ -280,7 +280,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
pushWarningContext(vnode)
|
pushWarningContext(vnode)
|
||||||
}
|
}
|
||||||
const subTree = (vnode.children = renderFunctionalRoot(vnode))
|
const subTree = (vnode.children = renderFunctionalRoot(vnode))
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
vnode.el = subTree.el as RenderNode
|
vnode.el = subTree.el as RenderNode
|
||||||
})
|
})
|
||||||
mount(subTree, container, vnode as MountedVNode, isSVG, endNode)
|
mount(subTree, container, vnode as MountedVNode, isSVG, endNode)
|
||||||
@ -306,7 +306,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
doMount()
|
doMount()
|
||||||
// cleanup if mount is invalidated before committed
|
// cleanup if mount is invalidated before committed
|
||||||
return () => {
|
return () => {
|
||||||
stop(handle.update)
|
stopReactiveEffect(handle.update)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -319,7 +319,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
const prevTree = prev.children as MountedVNode
|
const prevTree = prev.children as MountedVNode
|
||||||
const nextTree = (next.children = renderFunctionalRoot(next))
|
const nextTree = (next.children = renderFunctionalRoot(next))
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
next.el = nextTree.el
|
next.el = nextTree.el
|
||||||
})
|
})
|
||||||
patch(
|
patch(
|
||||||
@ -355,7 +355,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
const { children, childFlags } = vnode
|
const { children, childFlags } = vnode
|
||||||
switch (childFlags) {
|
switch (childFlags) {
|
||||||
case ChildrenFlags.SINGLE_VNODE:
|
case ChildrenFlags.SINGLE_VNODE:
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
vnode.el = (children as MountedVNode).el
|
vnode.el = (children as MountedVNode).el
|
||||||
})
|
})
|
||||||
mount(children as VNode, container, contextVNode, isSVG, endNode)
|
mount(children as VNode, container, contextVNode, isSVG, endNode)
|
||||||
@ -366,7 +366,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
vnode.el = placeholder.el
|
vnode.el = placeholder.el
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
vnode.el = (children as MountedVNode[])[0].el
|
vnode.el = (children as MountedVNode[])[0].el
|
||||||
})
|
})
|
||||||
mountArrayChildren(
|
mountArrayChildren(
|
||||||
@ -403,7 +403,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (ref) {
|
if (ref) {
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
ref(target)
|
ref(target)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -638,7 +638,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
// then retrieve its next sibling to use as the end node for patchChildren.
|
// then retrieve its next sibling to use as the end node for patchChildren.
|
||||||
const endNode = platformNextSibling(getVNodeLastEl(prevVNode))
|
const endNode = platformNextSibling(getVNodeLastEl(prevVNode))
|
||||||
const { childFlags, children } = nextVNode
|
const { childFlags, children } = nextVNode
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
switch (childFlags) {
|
switch (childFlags) {
|
||||||
case ChildrenFlags.SINGLE_VNODE:
|
case ChildrenFlags.SINGLE_VNODE:
|
||||||
nextVNode.el = (children as MountedVNode).el
|
nextVNode.el = (children as MountedVNode).el
|
||||||
@ -1181,7 +1181,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// functional
|
// functional
|
||||||
stop((handle as FunctionalHandle).update)
|
stopReactiveEffect((handle as FunctionalHandle).update)
|
||||||
unmount(children as MountedVNode)
|
unmount(children as MountedVNode)
|
||||||
}
|
}
|
||||||
} else if (flags & VNodeFlags.PORTAL) {
|
} else if (flags & VNodeFlags.PORTAL) {
|
||||||
@ -1293,16 +1293,16 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
} = instance
|
} = instance
|
||||||
|
|
||||||
instance.$forceUpdate = () => {
|
instance.$forceUpdate = () => {
|
||||||
queueJob(instance._updateHandle)
|
queueJob(instance._update)
|
||||||
}
|
}
|
||||||
|
|
||||||
const autorunOptions: AutorunOptions = {
|
const effectOptions: ReactiveEffectOptions = {
|
||||||
scheduler: queueJob
|
scheduler: queueJob
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
if (renderTracked) {
|
if (renderTracked) {
|
||||||
autorunOptions.onTrack = event => {
|
effectOptions.onTrack = event => {
|
||||||
callLifecycleHookWithHandler(
|
callLifecycleHookWithHandler(
|
||||||
renderTracked,
|
renderTracked,
|
||||||
$proxy,
|
$proxy,
|
||||||
@ -1312,7 +1312,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (renderTriggered) {
|
if (renderTriggered) {
|
||||||
autorunOptions.onTrigger = event => {
|
effectOptions.onTrigger = event => {
|
||||||
callLifecycleHookWithHandler(
|
callLifecycleHookWithHandler(
|
||||||
renderTriggered,
|
renderTriggered,
|
||||||
$proxy,
|
$proxy,
|
||||||
@ -1323,7 +1323,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instance._updateHandle = autorun(() => {
|
instance._update = createReactiveEffect(() => {
|
||||||
if (instance._unmounted) {
|
if (instance._unmounted) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1340,7 +1340,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
|
|
||||||
instance.$vnode = renderInstanceRoot(instance) as MountedVNode
|
instance.$vnode = renderInstanceRoot(instance) as MountedVNode
|
||||||
|
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
vnode.el = instance.$vnode.el
|
vnode.el = instance.$vnode.el
|
||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
// expose __vue__ for devtools
|
// expose __vue__ for devtools
|
||||||
@ -1360,7 +1360,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
|
|
||||||
mount(instance.$vnode, container, vnode as MountedVNode, isSVG, endNode)
|
mount(instance.$vnode, container, vnode as MountedVNode, isSVG, endNode)
|
||||||
}
|
}
|
||||||
}, autorunOptions)
|
}, effectOptions)
|
||||||
|
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
popWarningContext()
|
popWarningContext()
|
||||||
@ -1397,7 +1397,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
|
|
||||||
const nextVNode = renderInstanceRoot(instance) as MountedVNode
|
const nextVNode = renderInstanceRoot(instance) as MountedVNode
|
||||||
|
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
instance.$vnode = nextVNode
|
instance.$vnode = nextVNode
|
||||||
const el = nextVNode.el as RenderNode
|
const el = nextVNode.el as RenderNode
|
||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
@ -1486,7 +1486,7 @@ export function createRenderer(options: RendererOptions) {
|
|||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
popWarningContext()
|
popWarningContext()
|
||||||
}
|
}
|
||||||
queueEffect(() => {
|
queuePostEffect(() => {
|
||||||
callActivatedHook(instance, true)
|
callActivatedHook(instance, true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { queueJob, queueEffect, nextTick } from '../src/index'
|
import { queueJob, queuePostEffect, nextTick } from '../src/index'
|
||||||
|
|
||||||
describe('scheduler', () => {
|
describe('scheduler', () => {
|
||||||
it('queueJob', async () => {
|
it('queueJob', async () => {
|
||||||
@ -36,11 +36,11 @@ describe('scheduler', () => {
|
|||||||
const calls: any = []
|
const calls: any = []
|
||||||
const job1 = () => {
|
const job1 = () => {
|
||||||
calls.push('job1')
|
calls.push('job1')
|
||||||
queueEffect(cb1)
|
queuePostEffect(cb1)
|
||||||
}
|
}
|
||||||
const job2 = () => {
|
const job2 = () => {
|
||||||
calls.push('job2')
|
calls.push('job2')
|
||||||
queueEffect(cb2)
|
queuePostEffect(cb2)
|
||||||
}
|
}
|
||||||
const cb1 = () => {
|
const cb1 = () => {
|
||||||
calls.push('cb1')
|
calls.push('cb1')
|
||||||
@ -59,13 +59,13 @@ describe('scheduler', () => {
|
|||||||
const calls: any = []
|
const calls: any = []
|
||||||
const job1 = () => {
|
const job1 = () => {
|
||||||
calls.push('job1')
|
calls.push('job1')
|
||||||
queueEffect(cb1)
|
queuePostEffect(cb1)
|
||||||
// job1 queues job2
|
// job1 queues job2
|
||||||
queueJob(job2)
|
queueJob(job2)
|
||||||
}
|
}
|
||||||
const job2 = () => {
|
const job2 = () => {
|
||||||
calls.push('job2')
|
calls.push('job2')
|
||||||
queueEffect(cb2)
|
queuePostEffect(cb2)
|
||||||
}
|
}
|
||||||
const cb1 = () => {
|
const cb1 = () => {
|
||||||
calls.push('cb1')
|
calls.push('cb1')
|
||||||
@ -96,11 +96,11 @@ describe('scheduler', () => {
|
|||||||
expect(calls).toEqual(['job1', 'job2'])
|
expect(calls).toEqual(['job1', 'job2'])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('queueJob inside postCommitCb', async () => {
|
it('queueJob inside postEffect', async () => {
|
||||||
const calls: any = []
|
const calls: any = []
|
||||||
const job1 = () => {
|
const job1 = () => {
|
||||||
calls.push('job1')
|
calls.push('job1')
|
||||||
queueEffect(cb1)
|
queuePostEffect(cb1)
|
||||||
}
|
}
|
||||||
const cb1 = () => {
|
const cb1 = () => {
|
||||||
// queue another job in postFlushCb
|
// queue another job in postFlushCb
|
||||||
@ -109,7 +109,7 @@ describe('scheduler', () => {
|
|||||||
}
|
}
|
||||||
const job2 = () => {
|
const job2 = () => {
|
||||||
calls.push('job2')
|
calls.push('job2')
|
||||||
queueEffect(cb2)
|
queuePostEffect(cb2)
|
||||||
}
|
}
|
||||||
const cb2 = () => {
|
const cb2 = () => {
|
||||||
calls.push('cb2')
|
calls.push('cb2')
|
||||||
|
@ -31,15 +31,15 @@ interface Job<T extends Function = () => void> {
|
|||||||
ops: Op[]
|
ops: Op[]
|
||||||
// Any post DOM mutation side-effects (updated / mounted hooks, refs) are
|
// Any post DOM mutation side-effects (updated / mounted hooks, refs) are
|
||||||
// buffered inside the job's effects queue.
|
// buffered inside the job's effects queue.
|
||||||
// Effects are queued by calling `queueEffect` inside the job function.
|
// Effects are queued by calling `queuePostEffect` inside the job function.
|
||||||
effects: Function[]
|
postEffects: Function[]
|
||||||
// A job may queue other jobs (e.g. a parent component update triggers the
|
// A job may queue other jobs (e.g. a parent component update triggers the
|
||||||
// update of a child component). Jobs queued by another job is kept in the
|
// update of a child component). Jobs queued by another job is kept in the
|
||||||
// parent's children array, so that in case the parent job is invalidated,
|
// parent's children array, so that in case the parent job is invalidated,
|
||||||
// all its children can be invalidated as well (recursively).
|
// all its children can be invalidated as well (recursively).
|
||||||
children: Job[]
|
children: Job[]
|
||||||
// Sometimes it's inevitable for a stage fn to produce some side effects
|
// Sometimes it's inevitable for a stage fn to produce some side effects
|
||||||
// (e.g. a component instance sets up an Autorun). In those cases the stage fn
|
// (e.g. a component instance sets up an ReactiveEffect). In those cases the stage fn
|
||||||
// can return a cleanup function which will be called when the job is
|
// can return a cleanup function which will be called when the job is
|
||||||
// invalidated.
|
// invalidated.
|
||||||
cleanup: T | null
|
cleanup: T | null
|
||||||
@ -172,8 +172,8 @@ function flushAfterMacroTask() {
|
|||||||
// This is the main API of the scheduler. The raw job can actually be any
|
// This is the main API of the scheduler. The raw job can actually be any
|
||||||
// function, but since they are invalidated by identity, it is important that
|
// function, but since they are invalidated by identity, it is important that
|
||||||
// a component's update job is a consistent function across its lifecycle -
|
// a component's update job is a consistent function across its lifecycle -
|
||||||
// in the renderer, it's actually instance._updateHandle which is in turn
|
// in the renderer, it's actually instance._update which is in turn
|
||||||
// an Autorun function.
|
// an ReactiveEffect function.
|
||||||
export function queueJob(rawJob: Function) {
|
export function queueJob(rawJob: Function) {
|
||||||
const job = rawJob as Job
|
const job = rawJob as Job
|
||||||
if (currentJob) {
|
if (currentJob) {
|
||||||
@ -196,9 +196,9 @@ export function queueJob(rawJob: Function) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function queueEffect(fn: Function) {
|
export function queuePostEffect(fn: Function) {
|
||||||
if (currentJob) {
|
if (currentJob) {
|
||||||
currentJob.effects.push(fn)
|
currentJob.postEffects.push(fn)
|
||||||
} else {
|
} else {
|
||||||
postEffectsQueue.push(fn)
|
postEffectsQueue.push(fn)
|
||||||
}
|
}
|
||||||
@ -296,13 +296,13 @@ function flush(): void {
|
|||||||
|
|
||||||
function resetJob(job: Job) {
|
function resetJob(job: Job) {
|
||||||
job.ops.length = 0
|
job.ops.length = 0
|
||||||
job.effects.length = 0
|
job.postEffects.length = 0
|
||||||
job.children.length = 0
|
job.children.length = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
function queueJobForStaging(job: Job) {
|
function queueJobForStaging(job: Job) {
|
||||||
job.ops = job.ops || []
|
job.ops = job.ops || []
|
||||||
job.effects = job.effects || []
|
job.postEffects = job.postEffects || []
|
||||||
job.children = job.children || []
|
job.children = job.children || []
|
||||||
resetJob(job)
|
resetJob(job)
|
||||||
// inherit parent job's expiration deadline
|
// inherit parent job's expiration deadline
|
||||||
@ -361,13 +361,13 @@ function stageJob(job: Job) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function commitJob(job: Job) {
|
function commitJob(job: Job) {
|
||||||
const { ops, effects } = job
|
const { ops, postEffects } = job
|
||||||
for (let i = 0; i < ops.length; i++) {
|
for (let i = 0; i < ops.length; i++) {
|
||||||
applyOp(ops[i])
|
applyOp(ops[i])
|
||||||
}
|
}
|
||||||
// queue post commit cbs
|
// queue post commit cbs
|
||||||
if (effects) {
|
if (postEffects) {
|
||||||
postEffectsQueue.push(...effects)
|
postEffectsQueue.push(...postEffects)
|
||||||
}
|
}
|
||||||
resetJob(job)
|
resetJob(job)
|
||||||
job.status = JobStatus.IDLE
|
job.status = JobStatus.IDLE
|
||||||
|
Loading…
Reference in New Issue
Block a user