Skip to content

Commit 5b30f3e

Browse files
committed
Revert "simplify array change detection"
This reverts commit 5590378.
1 parent f3970f8 commit 5b30f3e

File tree

3 files changed

+64
-14
lines changed

3 files changed

+64
-14
lines changed

src/runtime/observer/patch-array.js src/runtime/observer/array.js

+22-13
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
1-
import { def, toArray } from '../util/index'
1+
import { def } from '../util/index'
22

33
const arrayProto = Array.prototype
4-
const mutationMethods = ['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse']
4+
export const arrayMethods = Object.create(arrayProto)
55

66
/**
7-
* Intercept mutating methods and notify change
7+
* Intercept mutating methods and emit events
88
*/
99

10-
mutationMethods.forEach(function (method) {
10+
;[
11+
'push',
12+
'pop',
13+
'shift',
14+
'unshift',
15+
'splice',
16+
'sort',
17+
'reverse'
18+
]
19+
.forEach(function (method) {
1120
// cache original method
1221
var original = arrayProto[method]
13-
14-
var interceptor = function arrayMutationInterceptor () {
15-
var args = toArray(arguments)
22+
def(arrayMethods, method, function mutator () {
23+
// avoid leaking arguments:
24+
// http://jsperf.com/closure-with-arguments
25+
var i = arguments.length
26+
var args = new Array(i)
27+
while (i--) {
28+
args[i] = arguments[i]
29+
}
1630
var result = original.apply(this, args)
1731
var ob = this.__ob__
1832
var inserted
@@ -31,12 +45,7 @@ mutationMethods.forEach(function (method) {
3145
// notify change
3246
ob.dep.notify()
3347
return result
34-
}
35-
36-
arrayProto[method] = function () {
37-
let fn = this && this.__ob__ ? interceptor : original
38-
return fn.apply(this, arguments)
39-
}
48+
})
4049
})
4150

4251
/**

src/runtime/observer/index.js

+39-1
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
import './patch-array'
21
import Dep from './dep'
2+
import { arrayMethods } from './array'
33
import {
44
def,
55
isArray,
66
isObject,
77
isPlainObject,
8+
hasProto,
89
hasOwn
910
} from '../util/index'
1011

12+
const arrayKeys = Object.getOwnPropertyNames(arrayMethods)
13+
1114
/**
1215
* By default, when a reactive property is set, the new value is
1316
* also converted to become reactive. However in certain cases, e.g.
@@ -40,6 +43,10 @@ export function Observer (value) {
4043
this.dep = new Dep()
4144
def(value, '__ob__', this)
4245
if (isArray(value)) {
46+
var augment = hasProto
47+
? protoAugment
48+
: copyAugment
49+
augment(value, arrayMethods, arrayKeys)
4350
this.observeArray(value)
4451
} else {
4552
this.walk(value)
@@ -111,6 +118,37 @@ Observer.prototype.removeVm = function (vm) {
111118
this.vms.$remove(vm)
112119
}
113120

121+
// helpers
122+
123+
/**
124+
* Augment an target Object or Array by intercepting
125+
* the prototype chain using __proto__
126+
*
127+
* @param {Object|Array} target
128+
* @param {Object} src
129+
*/
130+
131+
function protoAugment (target, src) {
132+
/* eslint-disable no-proto */
133+
target.__proto__ = src
134+
/* eslint-enable no-proto */
135+
}
136+
137+
/**
138+
* Augment an target Object or Array by defining
139+
* hidden properties.
140+
*
141+
* @param {Object|Array} target
142+
* @param {Object} proto
143+
*/
144+
145+
function copyAugment (target, src, keys) {
146+
for (var i = 0, l = keys.length; i < l; i++) {
147+
var key = keys[i]
148+
def(target, key, src[key])
149+
}
150+
}
151+
114152
/**
115153
* Attempt to create an observer instance for a value,
116154
* returns the new observer if successfully observed,

src/runtime/util/env.js

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
/* global MutationObserver */
22

3+
// can we use __proto__?
4+
export const hasProto = '__proto__' in {}
5+
36
// Browser environment sniffing
47
export const inBrowser =
58
typeof window !== 'undefined' &&

0 commit comments

Comments
 (0)