@@ -144,18 +144,40 @@ function lex(text){
144144 fn :function ( ) { return number ; } } ) ;
145145 }
146146 function readIdent ( ) {
147- var ident = "" ;
148- var start = index ;
149- var fn ;
147+ var ident = "" ,
148+ start = index ,
149+ fn , lastDot , peekIndex , methodName ;
150+
150151 while ( index < text . length ) {
151152 var ch = text . charAt ( index ) ;
152153 if ( ch == '.' || isIdent ( ch ) || isNumber ( ch ) ) {
154+ if ( ch == '.' ) lastDot = index ;
153155 ident += ch ;
154156 } else {
155157 break ;
156158 }
157159 index ++ ;
158160 }
161+
162+ //check if this is not a method invocation and if it is back out to last dot
163+ if ( lastDot ) {
164+ peekIndex = index
165+ while ( peekIndex < text . length ) {
166+ var ch = text . charAt ( peekIndex ) ;
167+ if ( ch == '(' ) {
168+ methodName = ident . substr ( lastDot - start + 1 ) ;
169+ ident = ident . substr ( 0 , lastDot - start ) ;
170+ index = peekIndex ;
171+ break ;
172+ }
173+ if ( isWhitespace ( ch ) ) {
174+ peekIndex ++ ;
175+ } else {
176+ break ;
177+ }
178+ }
179+ }
180+
159181 fn = OPERATORS [ ident ] ;
160182 tokens . push ( {
161183 index :start ,
@@ -167,6 +189,19 @@ function lex(text){
167189 }
168190 } )
169191 } ) ;
192+
193+ if ( methodName ) {
194+ tokens . push ( {
195+ index :lastDot ,
196+ text : '.' ,
197+ json : false
198+ } ) ;
199+ tokens . push ( {
200+ index : lastDot + 1 ,
201+ text : methodName ,
202+ json : false
203+ } ) ;
204+ }
170205 }
171206
172207 function readString ( quote ) {
@@ -490,13 +525,17 @@ function parser(text, json, $filter){
490525 throwError ( "not a primary expression" , token ) ;
491526 }
492527 }
493- var next ;
528+
529+ var next , context ;
494530 while ( ( next = expect ( '(' , '[' , '.' ) ) ) {
495531 if ( next . text === '(' ) {
496- primary = functionCall ( primary ) ;
532+ primary = functionCall ( primary , context ) ;
533+ context = null ;
497534 } else if ( next . text === '[' ) {
535+ context = primary ;
498536 primary = objectIndex ( primary ) ;
499537 } else if ( next . text === '.' ) {
538+ context = primary ;
500539 primary = fieldAccess ( primary ) ;
501540 } else {
502541 throwError ( "IMPOSSIBLE" ) ;
@@ -544,7 +583,7 @@ function parser(text, json, $filter){
544583 } ) ;
545584 }
546585
547- function _functionCall ( fn ) {
586+ function _functionCall ( fn , contextGetter ) {
548587 var argsFn = [ ] ;
549588 if ( peekToken ( ) . text != ')' ) {
550589 do {
@@ -553,14 +592,16 @@ function parser(text, json, $filter){
553592 }
554593 consume ( ')' ) ;
555594 return function ( self ) {
556- var args = [ ] ;
595+ var args = [ ] ,
596+ context = contextGetter ? contextGetter ( self ) : self ;
597+
557598 for ( var i = 0 ; i < argsFn . length ; i ++ ) {
558599 args . push ( argsFn [ i ] ( self ) ) ;
559600 }
560601 var fnPtr = fn ( self ) || noop ;
561602 // IE stupidity!
562603 return fnPtr . apply
563- ? fnPtr . apply ( self , args )
604+ ? fnPtr . apply ( context , args )
564605 : fnPtr ( args [ 0 ] , args [ 1 ] , args [ 2 ] , args [ 3 ] , args [ 4 ] ) ;
565606 } ;
566607 }
@@ -691,11 +732,7 @@ function getterFn(path) {
691732 code += 'if(!s) return s;\n' +
692733 'l=s;\n' +
693734 's=s' + key + ';\n' +
694- 'if(typeof s=="function" && !(s instanceof RegExp)) {\n' +
695- ' fn=function(){ return l' + key + '.apply(l, arguments); };\n' +
696- ' fn.$unboundFn=s;\n' +
697- ' s=fn;\n' +
698- '} else if (s && s.then) {\n' +
735+ 'if (s && s.then) {\n' +
699736 ' if (!("$$v" in s)) {\n' +
700737 ' p=s;\n' +
701738 ' p.$$v = undefined;\n' +
0 commit comments