@@ -37,13 +37,14 @@ function Compiler (vm, options) {
3737 var el = compiler . setupElement ( options )
3838 log ( '\nnew VM instance:' , el . tagName , '\n' )
3939
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 )
4343
4444 compiler . vm = vm
4545 def ( vm , '$' , makeHash ( ) )
4646 def ( vm , '$el' , el )
47+ def ( vm , '$scope' , scope )
4748 def ( vm , '$compiler' , compiler )
4849
4950 // keep track of directives and expressions
@@ -85,36 +86,23 @@ function Compiler (vm, options) {
8586
8687 // beforeCompile hook
8788 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 )
9794
9895 // for repeated items, create an index binding
9996 // which should be inenumerable but configurable
10097 if ( compiler . repeat ) {
101- vm . $index = compiler . repeatIndex
102- def ( vm , '$collection' , compiler . repeatCollection )
98+ scope . $index = compiler . repeatIndex
10399 compiler . createBinding ( '$index' )
104100 }
105101
106102 // now parse the DOM, during which we will create necessary bindings
107103 // and bind the parsed directives
108104 compiler . compile ( el , true )
109105
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- }
118106 // extract dependencies for computed properties
119107 if ( computed . length ) DepsParser . parse ( computed )
120108
@@ -374,24 +362,25 @@ CompilerProto.bindDirective = function (directive) {
374362 var binding ,
375363 compiler = this ,
376364 key = directive . key ,
377- baseKey = key . split ( '.' ) [ 0 ] ,
378- ownerCompiler = traceOwnerCompiler ( directive , compiler )
365+ baseKey = key . split ( '.' ) [ 0 ]
379366
380367 if ( directive . isExp ) {
381368 // expression bindings are always created on current compiler
382369 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 )
390379 } else {
391380 // 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
393382 // 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 )
395384 }
396385
397386 binding . instances . push ( directive )
@@ -419,6 +408,7 @@ CompilerProto.bindDirective = function (directive) {
419408CompilerProto . createBinding = function ( key , isExp , isFn ) {
420409
421410 var compiler = this ,
411+ scope = compiler . scope ,
422412 bindings = compiler . bindings ,
423413 binding = new Binding ( compiler , key , isExp , isFn )
424414
@@ -443,7 +433,8 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
443433 // this is a root level binding. we need to define getter/setters for it.
444434 compiler . define ( key , binding )
445435 } else {
446- Observer . ensurePath ( compiler . vm , key )
436+ // ensure path in scope so it can be observed
437+ Observer . ensurePath ( scope , key )
447438 var parentKey = key . slice ( 0 , key . lastIndexOf ( '.' ) )
448439 if ( ! hasOwn . call ( bindings , parentKey ) ) {
449440 // this is a nested value binding, but the binding for its parent
@@ -464,52 +455,35 @@ CompilerProto.define = function (key, binding) {
464455 log ( ' defined root binding: ' + key )
465456
466457 var compiler = this ,
458+ scope = compiler . scope ,
467459 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
471461
472- if ( type === 'Object' && value . $get ) {
473- // computed property
462+ if ( utils . typeOf ( value ) === 'Object' && value . $get ) {
474463 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 )
481472 }
482473
483474 Object . defineProperty ( vm , key , {
484- enumerable : true ,
485475 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 ]
493477 return binding . isComputed
494- ? value . $get ( )
495- : value
478+ ? val . $get ( )
479+ : val
496480 } ,
497481 set : function ( newVal ) {
498- var value = binding . value
482+ var val = scope [ key ]
499483 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
513487 }
514488 }
515489 } )
@@ -631,28 +605,14 @@ CompilerProto.destroy = function () {
631605
632606// Helpers --------------------------------------------------------------------
633607
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-
651608/**
652609 * shorthand for getting root compiler
653610 */
654611function getRoot ( compiler ) {
655- return traceOwnerCompiler ( { root : true } , compiler )
612+ while ( compiler . parentCompiler ) {
613+ compiler = compiler . parentCompiler
614+ }
615+ return compiler
656616}
657617
658618module . exports = Compiler
0 commit comments