@@ -37,13 +37,14 @@ function Compiler (vm, options) {
37
37
var el = compiler . setupElement ( options )
38
38
log ( '\nnew VM instance:' , el . tagName , '\n' )
39
39
40
- // copy scope properties to vm
41
- var scope = options . scope
42
- if ( scope ) utils . extend ( vm , scope , true )
40
+ // init scope
41
+ var scope = compiler . scope = options . scope || { }
42
+ utils . extend ( vm , scope , true )
43
43
44
44
compiler . vm = vm
45
45
def ( vm , '$' , makeHash ( ) )
46
46
def ( vm , '$el' , el )
47
+ def ( vm , '$scope' , scope )
47
48
def ( vm , '$compiler' , compiler )
48
49
49
50
// keep track of directives and expressions
@@ -85,36 +86,23 @@ function Compiler (vm, options) {
85
86
86
87
// beforeCompile hook
87
88
compiler . execHook ( 'beforeCompile' , 'created' )
88
-
89
- // create bindings for things already in scope
90
- var key , keyPrefix
91
- for ( key in vm ) {
92
- keyPrefix = key . charAt ( 0 )
93
- if ( keyPrefix !== '$' && keyPrefix !== '_' ) {
94
- compiler . createBinding ( key )
95
- }
96
- }
89
+ // the user might have set some props on the vm
90
+ // so copy it back to the scope...
91
+ utils . extend ( scope , vm )
92
+ // observe the scope
93
+ Observer . observe ( scope , '' , compiler . observer )
97
94
98
95
// for repeated items, create an index binding
99
96
// which should be inenumerable but configurable
100
97
if ( compiler . repeat ) {
101
- vm . $index = compiler . repeatIndex
102
- def ( vm , '$collection' , compiler . repeatCollection )
98
+ scope . $index = compiler . repeatIndex
103
99
compiler . createBinding ( '$index' )
104
100
}
105
101
106
102
// now parse the DOM, during which we will create necessary bindings
107
103
// and bind the parsed directives
108
104
compiler . compile ( el , true )
109
105
110
- // observe root values so that they emit events when
111
- // their nested values change (for an Object)
112
- // or when they mutate (for an Array)
113
- var i = observables . length , binding
114
- while ( i -- ) {
115
- binding = observables [ i ]
116
- Observer . observe ( binding . value , binding . key , compiler . observer )
117
- }
118
106
// extract dependencies for computed properties
119
107
if ( computed . length ) DepsParser . parse ( computed )
120
108
@@ -374,24 +362,25 @@ CompilerProto.bindDirective = function (directive) {
374
362
var binding ,
375
363
compiler = this ,
376
364
key = directive . key ,
377
- baseKey = key . split ( '.' ) [ 0 ] ,
378
- ownerCompiler = traceOwnerCompiler ( directive , compiler )
365
+ baseKey = key . split ( '.' ) [ 0 ]
379
366
380
367
if ( directive . isExp ) {
381
368
// expression bindings are always created on current compiler
382
369
binding = compiler . createBinding ( key , true , directive . isFn )
383
- } else if ( ownerCompiler . vm . hasOwnProperty ( baseKey ) ) {
384
- // If the directive's owner compiler's VM has the key,
385
- // it belongs there. Create the binding if it's not already
386
- // created, and return it.
387
- binding = hasOwn . call ( ownerCompiler . bindings , key )
388
- ? ownerCompiler . bindings [ key ]
389
- : ownerCompiler . createBinding ( key )
370
+ } else if (
371
+ hasOwn . call ( compiler . scope , baseKey ) ||
372
+ hasOwn . call ( compiler . vm , baseKey )
373
+ ) {
374
+ // If the directive's compiler's VM has the base key,
375
+ // it belongs here. Create the binding if it's not created already.
376
+ binding = hasOwn . call ( compiler . bindings , key )
377
+ ? compiler . bindings [ key ]
378
+ : compiler . createBinding ( key )
390
379
} else {
391
380
// due to prototypal inheritance of bindings, if a key doesn't exist
392
- // on the owner compiler's VM , then it doesn't exist in the whole
381
+ // on the bindings object , then it doesn't exist in the whole
393
382
// prototype chain. In this case we create the new binding at the root level.
394
- binding = ownerCompiler . bindings [ key ] || compiler . rootCompiler . createBinding ( key )
383
+ binding = compiler . bindings [ key ] || compiler . rootCompiler . createBinding ( key )
395
384
}
396
385
397
386
binding . instances . push ( directive )
@@ -419,6 +408,7 @@ CompilerProto.bindDirective = function (directive) {
419
408
CompilerProto . createBinding = function ( key , isExp , isFn ) {
420
409
421
410
var compiler = this ,
411
+ scope = compiler . scope ,
422
412
bindings = compiler . bindings ,
423
413
binding = new Binding ( compiler , key , isExp , isFn )
424
414
@@ -443,7 +433,8 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
443
433
// this is a root level binding. we need to define getter/setters for it.
444
434
compiler . define ( key , binding )
445
435
} else {
446
- Observer . ensurePath ( compiler . vm , key )
436
+ // ensure path in scope so it can be observed
437
+ Observer . ensurePath ( scope , key )
447
438
var parentKey = key . slice ( 0 , key . lastIndexOf ( '.' ) )
448
439
if ( ! hasOwn . call ( bindings , parentKey ) ) {
449
440
// this is a nested value binding, but the binding for its parent
@@ -464,52 +455,35 @@ CompilerProto.define = function (key, binding) {
464
455
log ( ' defined root binding: ' + key )
465
456
466
457
var compiler = this ,
458
+ scope = compiler . scope ,
467
459
vm = compiler . vm ,
468
- ob = compiler . observer ,
469
- value = binding . value = vm [ key ] , // save the value before redefinening it
470
- type = utils . typeOf ( value )
460
+ value = binding . value = scope [ key ] // save the value before redefinening it
471
461
472
- if ( type === 'Object' && value . $get ) {
473
- // computed property
462
+ if ( utils . typeOf ( value ) === 'Object' && value . $get ) {
474
463
compiler . markComputed ( binding )
475
- } else if ( type === 'Object' || type === 'Array' ) {
476
- // observe objects later, because there might be more keys
477
- // to be added to it during Observer.ensurePath().
478
- // we also want to emit all the set events after all values
479
- // are available.
480
- compiler . observables . push ( binding )
464
+ }
465
+
466
+ if ( ! ( key in scope ) ) {
467
+ scope [ key ] = undefined
468
+ }
469
+
470
+ if ( scope . __observer__ ) {
471
+ Observer . convert ( scope , key )
481
472
}
482
473
483
474
Object . defineProperty ( vm , key , {
484
- enumerable : true ,
485
475
get : function ( ) {
486
- var value = binding . value
487
- if ( depsOb . active && ( ! binding . isComputed && ( ! value || ! value . __observer__ ) ) ||
488
- Array . isArray ( value ) ) {
489
- // only emit non-computed, non-observed (primitive) values, or Arrays.
490
- // because these are the cleanest dependencies
491
- ob . emit ( 'get' , key )
492
- }
476
+ var val = scope [ key ]
493
477
return binding . isComputed
494
- ? value . $get ( )
495
- : value
478
+ ? val . $get ( )
479
+ : val
496
480
} ,
497
481
set : function ( newVal ) {
498
- var value = binding . value
482
+ var val = scope [ key ]
499
483
if ( binding . isComputed ) {
500
- if ( value . $set ) {
501
- value . $set ( newVal )
502
- }
503
- } else if ( newVal !== value ) {
504
- // unwatch the old value
505
- Observer . unobserve ( value , key , ob )
506
- // set new value
507
- binding . value = newVal
508
- ob . emit ( 'set' , key , newVal )
509
- Observer . ensurePaths ( key , newVal , compiler . bindings )
510
- // now watch the new value, which in turn emits 'set'
511
- // for all its nested values
512
- Observer . observe ( newVal , key , ob )
484
+ if ( val . $set ) val . $set ( newVal )
485
+ } else {
486
+ scope [ key ] = newVal
513
487
}
514
488
}
515
489
} )
@@ -631,28 +605,14 @@ CompilerProto.destroy = function () {
631
605
632
606
// Helpers --------------------------------------------------------------------
633
607
634
- /**
635
- * determine which viewmodel a key belongs to based on nesting symbols
636
- */
637
- function traceOwnerCompiler ( key , compiler ) {
638
- if ( key . nesting ) {
639
- var levels = key . nesting
640
- while ( compiler . parentCompiler && levels -- ) {
641
- compiler = compiler . parentCompiler
642
- }
643
- } else if ( key . root ) {
644
- while ( compiler . parentCompiler ) {
645
- compiler = compiler . parentCompiler
646
- }
647
- }
648
- return compiler
649
- }
650
-
651
608
/**
652
609
* shorthand for getting root compiler
653
610
*/
654
611
function getRoot ( compiler ) {
655
- return traceOwnerCompiler ( { root : true } , compiler )
612
+ while ( compiler . parentCompiler ) {
613
+ compiler = compiler . parentCompiler
614
+ }
615
+ return compiler
656
616
}
657
617
658
618
module . exports = Compiler
0 commit comments