Skip to content

Commit

Permalink
Revert "simplify array change detection"
Browse files Browse the repository at this point in the history
This reverts commit 5590378.
  • Loading branch information
yyx990803 committed Apr 16, 2016
1 parent f3970f8 commit 5b30f3e
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,32 @@
import { def, toArray } from '../util/index'
import { def } from '../util/index'

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

/**
* Intercept mutating methods and notify change
* Intercept mutating methods and emit events
*/

mutationMethods.forEach(function (method) {
;[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
]
.forEach(function (method) {
// cache original method
var original = arrayProto[method]

var interceptor = function arrayMutationInterceptor () {
var args = toArray(arguments)
def(arrayMethods, method, function mutator () {
// avoid leaking arguments:
// http://jsperf.com/closure-with-arguments
var i = arguments.length
var args = new Array(i)
while (i--) {
args[i] = arguments[i]
}
var result = original.apply(this, args)
var ob = this.__ob__
var inserted
Expand All @@ -31,12 +45,7 @@ mutationMethods.forEach(function (method) {
// notify change
ob.dep.notify()
return result
}

arrayProto[method] = function () {
let fn = this && this.__ob__ ? interceptor : original
return fn.apply(this, arguments)
}
})
})

/**
Expand Down
40 changes: 39 additions & 1 deletion src/runtime/observer/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import './patch-array'
import Dep from './dep'
import { arrayMethods } from './array'
import {
def,
isArray,
isObject,
isPlainObject,
hasProto,
hasOwn
} from '../util/index'

const arrayKeys = Object.getOwnPropertyNames(arrayMethods)

/**
* By default, when a reactive property is set, the new value is
* also converted to become reactive. However in certain cases, e.g.
Expand Down Expand Up @@ -40,6 +43,10 @@ export function Observer (value) {
this.dep = new Dep()
def(value, '__ob__', this)
if (isArray(value)) {
var augment = hasProto
? protoAugment
: copyAugment
augment(value, arrayMethods, arrayKeys)
this.observeArray(value)
} else {
this.walk(value)
Expand Down Expand Up @@ -111,6 +118,37 @@ Observer.prototype.removeVm = function (vm) {
this.vms.$remove(vm)
}

// helpers

/**
* Augment an target Object or Array by intercepting
* the prototype chain using __proto__
*
* @param {Object|Array} target
* @param {Object} src
*/

function protoAugment (target, src) {
/* eslint-disable no-proto */
target.__proto__ = src
/* eslint-enable no-proto */
}

/**
* Augment an target Object or Array by defining
* hidden properties.
*
* @param {Object|Array} target
* @param {Object} proto
*/

function copyAugment (target, src, keys) {
for (var i = 0, l = keys.length; i < l; i++) {
var key = keys[i]
def(target, key, src[key])
}
}

/**
* Attempt to create an observer instance for a value,
* returns the new observer if successfully observed,
Expand Down
3 changes: 3 additions & 0 deletions src/runtime/util/env.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
/* global MutationObserver */

// can we use __proto__?
export const hasProto = '__proto__' in {}

// Browser environment sniffing
export const inBrowser =
typeof window !== 'undefined' &&
Expand Down

0 comments on commit 5b30f3e

Please sign in to comment.