@mpxjs/core 2.7.52 → 2.8.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/@types/index.d.ts +342 -27
  2. package/package.json +10 -5
  3. package/src/convertor/convertor.js +2 -2
  4. package/src/convertor/mergeLifecycle.js +4 -4
  5. package/src/convertor/wxToAli.js +3 -4
  6. package/src/convertor/wxToSwan.js +2 -2
  7. package/src/convertor/wxToTt.js +1 -10
  8. package/src/convertor/wxToWeb.js +14 -7
  9. package/src/core/implement.js +2 -2
  10. package/src/core/injectMixins.js +1 -1
  11. package/src/core/innerLifecycle.js +15 -2
  12. package/src/core/mergeOptions.js +11 -5
  13. package/src/core/proxy.js +343 -229
  14. package/src/core/transferOptions.js +5 -2
  15. package/src/helper/const.js +10 -0
  16. package/src/index.js +73 -147
  17. package/src/observer/array.js +12 -17
  18. package/src/observer/computed.js +27 -56
  19. package/src/observer/dep.js +1 -1
  20. package/src/observer/effect.js +113 -0
  21. package/src/observer/effectScope.js +109 -0
  22. package/src/observer/{index.js → reactive.js} +74 -70
  23. package/src/observer/ref.js +97 -0
  24. package/src/observer/scheduler.js +171 -56
  25. package/src/observer/watch.js +163 -39
  26. package/src/platform/builtInMixins/i18nMixin.js +238 -31
  27. package/src/platform/builtInMixins/pageScrollMixin.web.js +4 -5
  28. package/src/platform/builtInMixins/pageStatusMixin.js +76 -54
  29. package/src/platform/builtInMixins/pageStatusMixin.web.js +35 -22
  30. package/src/platform/builtInMixins/proxyEventMixin.js +40 -22
  31. package/src/platform/builtInMixins/proxyEventMixin.web.js +16 -24
  32. package/src/platform/builtInMixins/refsMixin.js +82 -73
  33. package/src/platform/builtInMixins/refsMixin.web.js +0 -47
  34. package/src/platform/builtInMixins/relationsMixin.js +10 -9
  35. package/src/platform/builtInMixins/renderHelperMixin.js +1 -1
  36. package/src/platform/builtInMixins/showMixin.js +1 -1
  37. package/src/platform/createApp.js +5 -5
  38. package/src/platform/export/api.js +23 -0
  39. package/src/platform/export/api.web.js +26 -0
  40. package/src/platform/export/index.js +45 -0
  41. package/src/platform/export/index.web.js +36 -0
  42. package/src/platform/index.js +1 -5
  43. package/src/platform/patch/ali/getDefaultOptions.js +33 -31
  44. package/src/platform/patch/ali/lifecycle.js +21 -13
  45. package/src/platform/patch/builtInKeysMap.js +2 -1
  46. package/src/platform/patch/index.js +4 -9
  47. package/src/platform/patch/swan/getDefaultOptions.js +3 -3
  48. package/src/platform/patch/swan/lifecycle.js +17 -14
  49. package/src/platform/patch/web/getDefaultOptions.js +40 -16
  50. package/src/platform/patch/web/lifecycle.js +6 -3
  51. package/src/platform/patch/wx/getDefaultOptions.js +38 -31
  52. package/src/platform/patch/wx/lifecycle.js +18 -11
  53. package/src/runtime/createFactory.js +6 -2
  54. package/src/vue.web.js +3 -0
  55. package/src/vuePlugin.js +31 -0
  56. package/src/core/createStore.js +0 -241
  57. package/src/core/mapStore.js +0 -94
  58. package/src/helper/env.js +0 -20
  59. package/src/helper/getByPath.js +0 -127
  60. package/src/helper/log.js +0 -31
  61. package/src/helper/utils.js +0 -652
  62. package/src/observer/watcher.js +0 -244
@@ -1,20 +1,25 @@
1
1
  import Dep from './dep'
2
2
  import { arrayMethods } from './array'
3
+ import { ObKey } from '../helper/const'
4
+ import { isRef } from './ref'
5
+ import {
6
+ hasOwn,
7
+ isObject,
8
+ isPlainObject,
9
+ hasProto,
10
+ def,
11
+ isValidArrayIndex,
12
+ arrayProtoAugment
13
+ } from '@mpxjs/utils'
3
14
 
4
- import { def, isPlainObject, isObject, hasProto, hasOwn, isValidArrayIndex, arrayProtoAugment } from '../helper/utils'
15
+ const arrayKeys = Object.getOwnPropertyNames(arrayMethods)
5
16
 
6
- import { warn } from '../helper/log'
17
+ const rawSet = new WeakSet()
7
18
 
8
- const arrayKeys = Object.getOwnPropertyNames(arrayMethods)
19
+ let isForceTrigger = false
9
20
 
10
- /**
11
- * By default, when a reactive property is set, the new value is
12
- * also converted to become reactive. However when passing down props,
13
- * we don't want to force conversion because the value may be a nested value
14
- * under a frozen data structure. Converting it would defeat the optimization.
15
- */
16
- export const observerState = {
17
- shouldConvert: true
21
+ export function setForceTrigger (val) {
22
+ isForceTrigger = val
18
23
  }
19
24
 
20
25
  /**
@@ -24,19 +29,19 @@ export const observerState = {
24
29
  * collect dependencies and dispatches updates.
25
30
  */
26
31
  export class Observer {
27
- constructor (value) {
32
+ dep = new Dep()
33
+
34
+ constructor (value, shallow) {
28
35
  this.value = value
29
- this.dep = new Dep()
30
- this.vmCount = 0
31
- def(value, '__ob__', this)
36
+ def(value, ObKey, this)
32
37
  if (Array.isArray(value)) {
33
38
  const augment = hasProto && arrayProtoAugment
34
39
  ? protoAugment
35
40
  : copyAugment
36
41
  augment(value, arrayMethods, arrayKeys)
37
- this.observeArray(value)
42
+ !shallow && this.observeArray(value)
38
43
  } else {
39
- this.walk(value)
44
+ this.walk(value, shallow)
40
45
  }
41
46
  }
42
47
 
@@ -45,25 +50,22 @@ export class Observer {
45
50
  * getter/setters. This method should only be called when
46
51
  * value type is Object.
47
52
  */
48
- walk (obj) {
49
- const keys = Object.keys(obj)
50
- for (let i = 0; i < keys.length; i++) {
51
- defineReactive(obj, keys[i], obj[keys[i]])
52
- }
53
+ walk (obj, shallow) {
54
+ Object.keys(obj).forEach((key) => {
55
+ defineReactive(obj, key, obj[key], shallow)
56
+ })
53
57
  }
54
58
 
55
59
  /**
56
60
  * Observe a list of Array items.
57
61
  */
58
- observeArray (items) {
59
- for (let i = 0, l = items.length; i < l; i++) {
60
- observe(items[i])
62
+ observeArray (arr) {
63
+ for (let i = 0, l = arr.length; i < l; i++) {
64
+ observe(arr[i])
61
65
  }
62
66
  }
63
67
  }
64
68
 
65
- // helpers
66
-
67
69
  /**
68
70
  * Augment an target Object or Array by intercepting
69
71
  * the prototype chain using __proto__
@@ -71,7 +73,6 @@ export class Observer {
71
73
  function protoAugment (target, src, keys) {
72
74
  /* eslint-disable no-proto */
73
75
  target.__proto__ = src
74
- /* eslint-enable no-proto */
75
76
  }
76
77
 
77
78
  /**
@@ -92,22 +93,13 @@ function copyAugment (target, src, keys) {
92
93
  * returns the new observer if successfully observed,
93
94
  * or the existing observer if the value already has one.
94
95
  */
95
- export function observe (value, asRootData) {
96
- if (!isObject(value)) {
96
+ function observe (value, shallow) {
97
+ if (!isObject(value) || rawSet.has(value)) {
97
98
  return
98
99
  }
99
- let ob
100
- if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {
101
- ob = value.__ob__
102
- } else if (
103
- observerState.shouldConvert &&
104
- (Array.isArray(value) || isPlainObject(value)) &&
105
- Object.isExtensible(value)
106
- ) {
107
- ob = new Observer(value)
108
- }
109
- if (asRootData && ob) {
110
- ob.vmCount++
100
+ let ob = getObserver(value)
101
+ if (!ob && (Array.isArray(value) || isPlainObject(value)) && Object.isExtensible(value)) {
102
+ ob = new Observer(value, shallow)
111
103
  }
112
104
  return ob
113
105
  }
@@ -115,13 +107,7 @@ export function observe (value, asRootData) {
115
107
  /**
116
108
  * Define a reactive property on an Object.
117
109
  */
118
- export function defineReactive (
119
- obj,
120
- key,
121
- val,
122
- customSetter,
123
- shallow
124
- ) {
110
+ export function defineReactive (obj, key, val, shallow) {
125
111
  const dep = new Dep()
126
112
 
127
113
  const property = Object.getOwnPropertyDescriptor(obj, key)
@@ -148,17 +134,17 @@ export function defineReactive (
148
134
  }
149
135
  }
150
136
  }
151
- return value
137
+ return !shallow && isRef(value) ? value.value : value
152
138
  },
153
139
  set: function reactiveSetter (newVal) {
154
140
  const value = getter ? getter.call(obj) : val
155
141
  /* eslint-disable no-self-compare */
156
- if (newVal === value || (newVal !== newVal && value !== value)) {
142
+ if (!(shallow && isForceTrigger) && (newVal === value || (newVal !== newVal && value !== value))) {
157
143
  return
158
144
  }
159
- /* eslint-enable no-self-compare */
160
- customSetter && customSetter()
161
- if (setter) {
145
+ if (!shallow && isRef(value) && !isRef(newVal)) {
146
+ value.value = newVal
147
+ } else if (setter) {
162
148
  setter.call(obj, newVal)
163
149
  } else {
164
150
  val = newVal
@@ -184,11 +170,7 @@ export function set (target, key, val) {
184
170
  target[key] = val
185
171
  return val
186
172
  }
187
- const ob = target.__ob__
188
- if (ob && ob.vmCount) {
189
- warn('Avoid adding reactive properties to the root data at runtime, declare it upfront in the data option!')
190
- return val
191
- }
173
+ const ob = getObserver(target)
192
174
  if (!ob) {
193
175
  target[key] = val
194
176
  return val
@@ -206,11 +188,7 @@ export function del (target, key) {
206
188
  target.splice(key, 1)
207
189
  return
208
190
  }
209
- const ob = target.__ob__
210
- if (ob && ob.vmCount) {
211
- warn('Avoid deleting properties on the root data, just set it to null!')
212
- return
213
- }
191
+ const ob = getObserver(target)
214
192
  if (!hasOwn(target, key)) {
215
193
  return
216
194
  }
@@ -225,12 +203,38 @@ export function del (target, key) {
225
203
  * Collect dependencies on array elements when the array is touched, since
226
204
  * we cannot intercept array element access like property getters.
227
205
  */
228
- function dependArray (value) {
229
- for (let e, i = 0, l = value.length; i < l; i++) {
230
- e = value[i]
231
- e && e.__ob__ && e.__ob__.dep.depend()
232
- if (Array.isArray(e)) {
233
- dependArray(e)
206
+ function dependArray (arr) {
207
+ for (let i = 0, l = arr.length; i < l; i++) {
208
+ const item = arr[i]
209
+ const ob = getObserver(item)
210
+ ob && ob.dep.depend()
211
+ if (Array.isArray(item)) {
212
+ dependArray(item)
234
213
  }
235
214
  }
236
215
  }
216
+
217
+ export function reactive (value) {
218
+ observe(value)
219
+ return value
220
+ }
221
+
222
+ export function shallowReactive (value) {
223
+ observe(value, true)
224
+ return value
225
+ }
226
+
227
+ export function isReactive (value) {
228
+ return value && hasOwn(value, ObKey) && value[ObKey] instanceof Observer
229
+ }
230
+
231
+ export function getObserver (value) {
232
+ if (isReactive(value)) return value[ObKey]
233
+ }
234
+
235
+ export function markRaw (value) {
236
+ if (isObject(value)) {
237
+ rawSet.add(value)
238
+ }
239
+ return value
240
+ }
@@ -0,0 +1,97 @@
1
+ import { reactive, shallowReactive, set, isReactive, setForceTrigger } from './reactive'
2
+ import { RefKey } from '../helper/const'
3
+ import {
4
+ warn,
5
+ isPlainObject,
6
+ hasOwn
7
+ } from '@mpxjs/utils'
8
+
9
+ export class RefImpl {
10
+ constructor (options) {
11
+ Object.defineProperty(this, 'value', { enumerable: true, ...options })
12
+ }
13
+ }
14
+
15
+ export function createRef (options, effect) {
16
+ const ref = new RefImpl(options)
17
+ if (effect) {
18
+ ref.effect = effect
19
+ effect.computed = ref
20
+ }
21
+ return Object.seal(ref)
22
+ }
23
+
24
+ export function isRef (val) {
25
+ return val instanceof RefImpl
26
+ }
27
+
28
+ export function unref (ref) {
29
+ return isRef(ref) ? ref.value : ref
30
+ }
31
+
32
+ export function ref (raw) {
33
+ if (isRef(raw)) return raw
34
+ const wrapper = reactive({ [RefKey]: raw })
35
+ return createRef({
36
+ get: () => wrapper[RefKey],
37
+ set: (val) => {
38
+ wrapper[RefKey] = val
39
+ }
40
+ })
41
+ }
42
+
43
+ export function toRef (obj, key) {
44
+ if (!isReactive(obj)) warn('toRef() expects a reactive object but received a plain one.')
45
+ if (!hasOwn(obj, key)) set(obj, key)
46
+ const val = obj[key]
47
+ if (isRef(val)) return val
48
+ return createRef({
49
+ get: () => obj[key],
50
+ set: (val) => {
51
+ obj[key] = val
52
+ }
53
+ })
54
+ }
55
+
56
+ export function toRefs (obj) {
57
+ if (!isReactive(obj)) warn('toRefs() expects a reactive object but received a plain one.')
58
+ if (!isPlainObject(obj)) return obj
59
+ const result = {}
60
+ Object.keys(obj).forEach((key) => {
61
+ result[key] = toRef(obj, key)
62
+ })
63
+ return result
64
+ }
65
+
66
+ export function customRef (factory) {
67
+ const version = ref(0)
68
+ return createRef(
69
+ factory(
70
+ // track
71
+ () => version.value,
72
+ // trigger
73
+ () => {
74
+ version.value++
75
+ }
76
+ )
77
+ )
78
+ }
79
+
80
+ export function shallowRef (raw) {
81
+ if (isRef(raw)) return raw
82
+ const wrapper = shallowReactive({ [RefKey]: raw })
83
+ return createRef({
84
+ get: () => wrapper[RefKey],
85
+ set: (val) => {
86
+ wrapper[RefKey] = val
87
+ }
88
+ })
89
+ }
90
+
91
+ export function triggerRef (ref) {
92
+ if (!isRef(ref)) return
93
+ setForceTrigger(true)
94
+ /* eslint-disable no-self-assign */
95
+ ref.value = ref.value
96
+ setForceTrigger(false)
97
+ }
@@ -1,75 +1,190 @@
1
- import { asyncLock } from '../helper/utils'
2
- import { error } from '../helper/log'
3
- import EXPORT_MPX from '../index'
1
+ import { warn, isArray, callWithErrorHandling, isDev } from '@mpxjs/utils'
2
+ import Mpx from '../index'
3
+
4
+ let isFlushing = false
5
+ let isFlushPending = false
4
6
 
5
7
  const queue = []
6
- let has = {}
7
- let circular = {}
8
- let flushing = false
9
- let curIndex = 0
10
- const lockTask = asyncLock()
11
- const MAX_UPDATE_COUNT = 100
12
-
13
- export function queueWatcher (watcher) {
14
- if (!watcher.id && typeof watcher === 'function') {
15
- watcher = {
16
- id: Infinity,
17
- run: watcher
8
+ let flushIndex = 0
9
+
10
+ const pendingPreFlushCbs = []
11
+ let activePreFlushCbs = null
12
+ let preFlushIndex = 0
13
+
14
+ const pendingPostFlushCbs = []
15
+ let activePostFlushCbs = null
16
+ let postFlushIndex = 0
17
+
18
+ const resolvedPromise = Promise.resolve()
19
+ let currentFlushPromise = null
20
+
21
+ const RECURSION_LIMIT = 100
22
+
23
+ const getId = (job) => job.id == null ? Infinity : job.id
24
+
25
+ function findInsertionIndex (id) {
26
+ // the start index should be `flushIndex + 1`
27
+ let start = flushIndex + 1
28
+ let end = queue.length
29
+
30
+ while (start < end) {
31
+ const middle = (start + end) >>> 1
32
+ const middleJobId = getId(queue[middle])
33
+ middleJobId < id ? (start = middle + 1) : (end = middle)
34
+ }
35
+
36
+ return start
37
+ }
38
+
39
+ export function nextTick (fn) {
40
+ const p = currentFlushPromise || resolvedPromise
41
+ return fn ? p.then(this ? fn.bind(this) : fn) : p
42
+ }
43
+
44
+ export function queuePreFlushCb (cb) {
45
+ queueCb(cb, activePreFlushCbs, pendingPreFlushCbs, preFlushIndex)
46
+ }
47
+
48
+ export function queuePostFlushCb (cb) {
49
+ queueCb(cb, activePostFlushCbs, pendingPostFlushCbs, postFlushIndex)
50
+ }
51
+
52
+ function queueCb (cb, activeQueue, pendingQueue, index) {
53
+ if (isArray(cb)) {
54
+ pendingQueue.push(...cb)
55
+ } else if (
56
+ !activeQueue ||
57
+ !activeQueue.includes(cb, cb.allowRecurse ? index + 1 : index)
58
+ ) {
59
+ pendingQueue.push(cb)
60
+ }
61
+ queueFlush()
62
+ }
63
+
64
+ export function queueJob (job) {
65
+ // the dedupe search uses the startIndex argument of Array.includes()
66
+ // by default the search index includes the current job that is being run
67
+ // so it cannot recursively trigger itself again.
68
+ // if the job is a watch() callback, the search will start with a +1 index to
69
+ // allow it recursively trigger itself - it is the user's responsibility to
70
+ // ensure it doesn't end up in an infinite loop.
71
+ if (
72
+ !queue.length ||
73
+ !queue.includes(job, isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex)
74
+ ) {
75
+ if (job.id == null) {
76
+ queue.push(job)
77
+ } else {
78
+ queue.splice(findInsertionIndex(job.id), 0, job)
18
79
  }
80
+ queueFlush()
19
81
  }
20
- // 开启EXPORT_MPX.config.forceRunWatcherSync时,queueWatcher同步执行,便于调试排查问题
21
- if (EXPORT_MPX.config.forceRunWatcherSync) return watcher.run()
22
- if (!has[watcher.id] || watcher.id === Infinity) {
23
- has[watcher.id] = true
24
- if (!flushing) {
25
- queue.push(watcher)
26
- lockTask(flushQueue, resetQueue)
82
+ }
83
+
84
+ function queueFlush () {
85
+ if (!isFlushing && !isFlushPending) {
86
+ isFlushPending = true
87
+ if (Mpx.config.forceFlushSync) {
88
+ flushJobs()
27
89
  } else {
28
- let i = queue.length - 1
29
- while (i > curIndex && watcher.id < queue[i].id) {
30
- i--
31
- }
32
- queue.splice(i + 1, 0, watcher)
90
+ currentFlushPromise = resolvedPromise.then(flushJobs)
33
91
  }
34
92
  }
35
93
  }
36
94
 
37
- export function dequeueWatcher (watcher) {
38
- if (!watcher.id || !has[watcher.id]) return
39
- const index = queue.indexOf(watcher)
40
- if (index > -1) {
41
- queue.splice(index, 1)
42
- has[watcher.id] = false
95
+ export function flushPreFlushCbs (seen) {
96
+ if (pendingPreFlushCbs.length) {
97
+ activePreFlushCbs = [...new Set(pendingPreFlushCbs)]
98
+ pendingPreFlushCbs.length = 0
99
+ if (isDev) seen = seen || new Map()
100
+ for (
101
+ preFlushIndex = 0;
102
+ preFlushIndex < activePreFlushCbs.length;
103
+ preFlushIndex++
104
+ ) {
105
+ if (isDev && checkRecursiveUpdates(seen, activePreFlushCbs[preFlushIndex])) continue
106
+ activePreFlushCbs[preFlushIndex]()
107
+ }
108
+ activePreFlushCbs = null
109
+ preFlushIndex = 0
110
+ // recursively flush until it drains
111
+ flushPreFlushCbs(seen)
112
+ }
113
+ }
114
+
115
+ export function flushPostFlushCbs (seen) {
116
+ if (pendingPostFlushCbs.length) {
117
+ activePostFlushCbs = [...new Set(pendingPostFlushCbs)]
118
+ pendingPostFlushCbs.length = 0
119
+ if (isDev) seen = seen || new Map()
120
+
121
+ // activePostFlushCbs.sort((a, b) => getId(a) - getId(b))
122
+ for (
123
+ postFlushIndex = 0;
124
+ postFlushIndex < activePostFlushCbs.length;
125
+ postFlushIndex++
126
+ ) {
127
+ if (isDev && checkRecursiveUpdates(seen, activePostFlushCbs[postFlushIndex])) continue
128
+ activePostFlushCbs[postFlushIndex]()
129
+ }
130
+ activePostFlushCbs = null
131
+ postFlushIndex = 0
132
+ // recursively flush until it drains
133
+ flushPostFlushCbs(seen)
43
134
  }
44
135
  }
45
136
 
46
- function flushQueue () {
47
- flushing = true
48
- queue.sort((a, b) => a.id - b.id)
49
- for (curIndex = 0; curIndex < queue.length; curIndex++) {
50
- const watcher = queue[curIndex]
51
- const id = watcher.id
52
- if (id !== Infinity) {
53
- delete has[id]
54
- if (process.env.NODE_ENV !== 'production') {
55
- circular[id] = (circular[id] || 0) + 1
56
- if (circular[id] > MAX_UPDATE_COUNT) {
57
- let location = watcher.vm && watcher.vm.options && watcher.vm.options.mpxFileResource
58
- error(`You may have a dead circular update in watcher with expression [${watcher.expression}], please check!`, location)
59
- break
60
- }
137
+ function flushJobs (seen) {
138
+ isFlushPending = false
139
+ isFlushing = true
140
+
141
+ if (isDev) seen = seen || new Map()
142
+
143
+ flushPreFlushCbs(seen)
144
+
145
+ queue.sort((a, b) => getId(a) - getId(b))
146
+
147
+ try {
148
+ for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {
149
+ const job = queue[flushIndex]
150
+ if (job && job.active !== false) {
151
+ if (isDev && checkRecursiveUpdates(seen, job)) continue
152
+ callWithErrorHandling(job, null, 'render job')
61
153
  }
62
154
  }
63
- watcher.run()
155
+ } finally {
156
+ flushIndex = 0
157
+ queue.length = 0
158
+
159
+ flushPostFlushCbs(seen)
160
+
161
+ isFlushing = false
162
+ currentFlushPromise = null
163
+ // some postFlushCb queued jobs!
164
+ // keep flushing until it drains.
165
+ if (
166
+ queue.length ||
167
+ pendingPreFlushCbs.length ||
168
+ pendingPostFlushCbs.length
169
+ ) {
170
+ flushJobs(seen)
171
+ }
64
172
  }
65
- resetQueue()
66
173
  }
67
174
 
68
- function resetQueue () {
69
- flushing = false
70
- curIndex = queue.length = 0
71
- has = {}
72
- if (process.env.NODE_ENV !== 'production') {
73
- circular = {}
175
+ function checkRecursiveUpdates (seen, fn) {
176
+ if (!seen.has(fn)) {
177
+ seen.set(fn, 1)
178
+ } else {
179
+ const count = seen.get(fn)
180
+ if (count > RECURSION_LIMIT) {
181
+ warn(
182
+ 'Maximum recursive updates exceeded.\n' +
183
+ 'This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself'
184
+ )
185
+ return true
186
+ } else {
187
+ seen.set(fn, count + 1)
188
+ }
74
189
  }
75
190
  }