Skip to content

Commit 9259325

Browse files
committed
support frozen models (close vuejs#662)
1 parent 838c98a commit 9259325

File tree

4 files changed

+56
-23
lines changed

4 files changed

+56
-23
lines changed

src/instance/scope.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ exports._initData = function () {
7373
}
7474
}
7575
// observe data
76-
Observer.create(data).addVm(this)
76+
Observer.create(data, this)
7777
}
7878

7979
/**
@@ -121,7 +121,7 @@ exports._setData = function (newData) {
121121
}
122122
}
123123
oldData.__ob__.removeVm(this)
124-
Observer.create(newData).addVm(this)
124+
Observer.create(newData, this)
125125
this._digest()
126126
}
127127

src/observer/index.js

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,28 @@ var arrayMethods = require('./array')
55
var arrayKeys = Object.getOwnPropertyNames(arrayMethods)
66
require('./object')
77

8-
var uid = 0
9-
10-
/**
11-
* Type enums
12-
*/
13-
14-
var ARRAY = 0
15-
var OBJECT = 1
16-
178
/**
189
* Observer class that are attached to each observed
1910
* object. Once attached, the observer converts target
2011
* object's property keys into getter/setters that
2112
* collect dependencies and dispatches updates.
2213
*
2314
* @param {Array|Object} value
24-
* @param {Number} type
2515
* @constructor
2616
*/
2717

28-
function Observer (value, type) {
29-
this.id = ++uid
18+
function Observer (value) {
3019
this.value = value
3120
this.active = true
3221
this.deps = []
3322
_.define(value, '__ob__', this)
34-
if (type === ARRAY) {
23+
if (_.isArray(value)) {
3524
var augment = config.proto && _.hasProto
3625
? protoAugment
3726
: copyAugment
3827
augment(value, arrayMethods, arrayKeys)
3928
this.observeArray(value)
40-
} else if (type === OBJECT) {
29+
} else {
4130
this.walk(value)
4231
}
4332
}
@@ -50,25 +39,30 @@ function Observer (value, type) {
5039
* or the existing observer if the value already has one.
5140
*
5241
* @param {*} value
42+
* @param {Vue} [vm]
5343
* @return {Observer|undefined}
5444
* @static
5545
*/
5646

57-
Observer.create = function (value) {
47+
Observer.create = function (value, vm) {
48+
var ob
5849
if (
5950
value &&
6051
value.hasOwnProperty('__ob__') &&
6152
value.__ob__ instanceof Observer
6253
) {
63-
return value.__ob__
64-
} else if (_.isArray(value)) {
65-
return new Observer(value, ARRAY)
54+
ob = value.__ob__
6655
} else if (
67-
_.isPlainObject(value) &&
68-
!value._isVue // avoid Vue instance
56+
_.isObject(value) &&
57+
!Object.isFrozen(value) &&
58+
!value._isVue
6959
) {
70-
return new Observer(value, OBJECT)
60+
ob = new Observer(value)
61+
}
62+
if (ob && vm) {
63+
ob.addVm(vm)
7164
}
65+
return ob
7266
}
7367

7468
/**

test/unit/specs/misc_spec.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,40 @@ describe('Misc', function () {
140140
})
141141
})
142142

143+
it('frozen model, root', function (done) {
144+
var vm = new Vue({
145+
el: document.createElement('div'),
146+
template: '{{msg}}',
147+
data: Object.freeze({
148+
msg: 'hi!'
149+
})
150+
})
151+
expect(vm.$el.textContent).toBe('hi!')
152+
vm.msg = 'ho!'
153+
Vue.nextTick(function () {
154+
expect(vm.$el.textContent).toBe('hi!')
155+
done()
156+
})
157+
})
158+
159+
it('frozen model, non-root', function (done) {
160+
var vm = new Vue({
161+
el: document.createElement('div'),
162+
template: '{{msg}} {{frozen.msg}}',
163+
data: {
164+
msg: 'hi',
165+
frozen: Object.freeze({
166+
msg: 'frozen'
167+
})
168+
}
169+
})
170+
expect(vm.$el.textContent).toBe('hi frozen')
171+
vm.msg = 'ho'
172+
vm.frozen.msg = 'changed'
173+
Vue.nextTick(function () {
174+
expect(vm.$el.textContent).toBe('ho frozen')
175+
done()
176+
})
177+
})
178+
143179
})

test/unit/specs/observer/observer_spec.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ describe('Observer', function () {
1212
// avoid vue instance
1313
ob = Observer.create(new _.Vue())
1414
expect(ob).toBeUndefined()
15+
// avoid frozen objects
16+
ob = Observer.create(Object.freeze({}))
17+
expect(ob).toBeUndefined()
1518
})
1619

1720
it('create on object', function () {

0 commit comments

Comments
 (0)