mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-17 19:11:08 +00:00
parent
1268fc1a44
commit
39b3297fc3
5 changed files with 72 additions and 17 deletions
|
|
@ -686,7 +686,6 @@ function equals(o1, o2) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (t1 == 'function' && o1.$unboundFn) return o1.$unboundFn === o2.$unboundFn;
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -144,18 +144,40 @@ function lex(text){
|
||||||
fn:function() {return number;}});
|
fn:function() {return number;}});
|
||||||
}
|
}
|
||||||
function readIdent() {
|
function readIdent() {
|
||||||
var ident = "";
|
var ident = "",
|
||||||
var start = index;
|
start = index,
|
||||||
var fn;
|
fn, lastDot, peekIndex, methodName;
|
||||||
|
|
||||||
while (index < text.length) {
|
while (index < text.length) {
|
||||||
var ch = text.charAt(index);
|
var ch = text.charAt(index);
|
||||||
if (ch == '.' || isIdent(ch) || isNumber(ch)) {
|
if (ch == '.' || isIdent(ch) || isNumber(ch)) {
|
||||||
|
if (ch == '.') lastDot = index;
|
||||||
ident += ch;
|
ident += ch;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//check if this is not a method invocation and if it is back out to last dot
|
||||||
|
if (lastDot) {
|
||||||
|
peekIndex = index
|
||||||
|
while(peekIndex < text.length) {
|
||||||
|
var ch = text.charAt(peekIndex);
|
||||||
|
if (ch == '(') {
|
||||||
|
methodName = ident.substr(lastDot - start + 1);
|
||||||
|
ident = ident.substr(0, lastDot - start);
|
||||||
|
index = peekIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(isWhitespace(ch)) {
|
||||||
|
peekIndex++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn = OPERATORS[ident];
|
fn = OPERATORS[ident];
|
||||||
tokens.push({
|
tokens.push({
|
||||||
index:start,
|
index:start,
|
||||||
|
|
@ -167,6 +189,19 @@ function lex(text){
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (methodName) {
|
||||||
|
tokens.push({
|
||||||
|
index:lastDot,
|
||||||
|
text: '.',
|
||||||
|
json: false
|
||||||
|
});
|
||||||
|
tokens.push({
|
||||||
|
index: lastDot + 1,
|
||||||
|
text: methodName,
|
||||||
|
json: false
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function readString(quote) {
|
function readString(quote) {
|
||||||
|
|
@ -490,13 +525,17 @@ function parser(text, json, $filter){
|
||||||
throwError("not a primary expression", token);
|
throwError("not a primary expression", token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var next;
|
|
||||||
|
var next, context;
|
||||||
while ((next = expect('(', '[', '.'))) {
|
while ((next = expect('(', '[', '.'))) {
|
||||||
if (next.text === '(') {
|
if (next.text === '(') {
|
||||||
primary = functionCall(primary);
|
primary = functionCall(primary, context);
|
||||||
|
context = null;
|
||||||
} else if (next.text === '[') {
|
} else if (next.text === '[') {
|
||||||
|
context = primary;
|
||||||
primary = objectIndex(primary);
|
primary = objectIndex(primary);
|
||||||
} else if (next.text === '.') {
|
} else if (next.text === '.') {
|
||||||
|
context = primary;
|
||||||
primary = fieldAccess(primary);
|
primary = fieldAccess(primary);
|
||||||
} else {
|
} else {
|
||||||
throwError("IMPOSSIBLE");
|
throwError("IMPOSSIBLE");
|
||||||
|
|
@ -544,7 +583,7 @@ function parser(text, json, $filter){
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function _functionCall(fn) {
|
function _functionCall(fn, contextGetter) {
|
||||||
var argsFn = [];
|
var argsFn = [];
|
||||||
if (peekToken().text != ')') {
|
if (peekToken().text != ')') {
|
||||||
do {
|
do {
|
||||||
|
|
@ -553,14 +592,16 @@ function parser(text, json, $filter){
|
||||||
}
|
}
|
||||||
consume(')');
|
consume(')');
|
||||||
return function(self){
|
return function(self){
|
||||||
var args = [];
|
var args = [],
|
||||||
|
context = contextGetter ? contextGetter(self) : self;
|
||||||
|
|
||||||
for ( var i = 0; i < argsFn.length; i++) {
|
for ( var i = 0; i < argsFn.length; i++) {
|
||||||
args.push(argsFn[i](self));
|
args.push(argsFn[i](self));
|
||||||
}
|
}
|
||||||
var fnPtr = fn(self) || noop;
|
var fnPtr = fn(self) || noop;
|
||||||
// IE stupidity!
|
// IE stupidity!
|
||||||
return fnPtr.apply
|
return fnPtr.apply
|
||||||
? fnPtr.apply(self, args)
|
? fnPtr.apply(context, args)
|
||||||
: fnPtr(args[0], args[1], args[2], args[3], args[4]);
|
: fnPtr(args[0], args[1], args[2], args[3], args[4]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -691,11 +732,7 @@ function getterFn(path) {
|
||||||
code += 'if(!s) return s;\n' +
|
code += 'if(!s) return s;\n' +
|
||||||
'l=s;\n' +
|
'l=s;\n' +
|
||||||
's=s' + key + ';\n' +
|
's=s' + key + ';\n' +
|
||||||
'if(typeof s=="function" && !(s instanceof RegExp)) {\n' +
|
'if (s && s.then) {\n' +
|
||||||
' fn=function(){ return l' + key + '.apply(l, arguments); };\n' +
|
|
||||||
' fn.$unboundFn=s;\n' +
|
|
||||||
' s=fn;\n' +
|
|
||||||
'} else if (s && s.then) {\n' +
|
|
||||||
' if (!("$$v" in s)) {\n' +
|
' if (!("$$v" in s)) {\n' +
|
||||||
' p=s;\n' +
|
' p=s;\n' +
|
||||||
' p.$$v = undefined;\n' +
|
' p.$$v = undefined;\n' +
|
||||||
|
|
|
||||||
|
|
@ -741,7 +741,7 @@ var inputDirective = ['$defer', '$formFactory', function($defer, $formFactory) {
|
||||||
|
|
||||||
type = lowercase(type);
|
type = lowercase(type);
|
||||||
TypeController = (loadFromScope
|
TypeController = (loadFromScope
|
||||||
? (assertArgFn(modelScope.$eval(loadFromScope[1]), loadFromScope[1])).$unboundFn
|
? assertArgFn(modelScope.$eval(loadFromScope[1]), loadFromScope[1])
|
||||||
: angularInputType(type)) || noop;
|
: angularInputType(type)) || noop;
|
||||||
|
|
||||||
if (!HTML5_INPUTS_TYPES[type]) {
|
if (!HTML5_INPUTS_TYPES[type]) {
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,17 @@ describe('parser', function() {
|
||||||
expect(tokens[3].text).toEqual(';');
|
expect(tokens[3].text).toEqual(';');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should tokenize function invocation', function() {
|
||||||
|
var tokens = lex("a()")
|
||||||
|
expect(map(tokens, function(t) { return t.text;})).toEqual(['a', '(', ')']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should tokenize method invocation', function() {
|
||||||
|
var tokens = lex("a.b.c (d) - e.f()");
|
||||||
|
expect(map(tokens, function(t) { return t.text;})).
|
||||||
|
toEqual(['a.b', '.', 'c', '(', 'd', ')', '-', 'e', '.', 'f', '(', ')']);
|
||||||
|
});
|
||||||
|
|
||||||
it('should tokenize number', function() {
|
it('should tokenize number', function() {
|
||||||
var tokens = lex("0.5");
|
var tokens = lex("0.5");
|
||||||
expect(tokens[0].text).toEqual(0.5);
|
expect(tokens[0].text).toEqual(0.5);
|
||||||
|
|
@ -244,6 +255,12 @@ describe('parser', function() {
|
||||||
expect(scope.$eval("add(1,2)")).toEqual(3);
|
expect(scope.$eval("add(1,2)")).toEqual(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should evaluate function call from a return value', function() {
|
||||||
|
scope.val = 33;
|
||||||
|
scope.getter = function() { return function() { return this.val; }};
|
||||||
|
expect(scope.$eval("getter()()")).toBe(33);
|
||||||
|
});
|
||||||
|
|
||||||
it('should evaluate multiplication and division', function() {
|
it('should evaluate multiplication and division', function() {
|
||||||
scope.taxRate = 8;
|
scope.taxRate = 8;
|
||||||
scope.subTotal = 100;
|
scope.subTotal = 100;
|
||||||
|
|
@ -281,7 +298,7 @@ describe('parser', function() {
|
||||||
expect(toJson(scope.$eval("[{a:[]}, {b:1}]"))).toEqual('[{"a":[]},{"b":1}]');
|
expect(toJson(scope.$eval("[{a:[]}, {b:1}]"))).toEqual('[{"a":[]},{"b":1}]');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should evaluate multipple statements', function() {
|
it('should evaluate multiple statements', function() {
|
||||||
expect(scope.$eval("a=1;b=3;a+b")).toEqual(4);
|
expect(scope.$eval("a=1;b=3;a+b")).toEqual(4);
|
||||||
expect(scope.$eval(";;1;;")).toEqual(1);
|
expect(scope.$eval(";;1;;")).toEqual(1);
|
||||||
});
|
});
|
||||||
|
|
@ -296,6 +313,7 @@ describe('parser', function() {
|
||||||
|
|
||||||
scope.obj = new C();
|
scope.obj = new C();
|
||||||
expect(scope.$eval("obj.getA()")).toEqual(123);
|
expect(scope.$eval("obj.getA()")).toEqual(123);
|
||||||
|
expect(scope.$eval("obj['getA']()")).toEqual(123);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should evaluate methods in correct context (this) in argument', function() {
|
it('should evaluate methods in correct context (this) in argument', function() {
|
||||||
|
|
@ -311,6 +329,7 @@ describe('parser', function() {
|
||||||
|
|
||||||
scope.obj = new C();
|
scope.obj = new C();
|
||||||
expect(scope.$eval("obj.sum(obj.getA())")).toEqual(246);
|
expect(scope.$eval("obj.sum(obj.getA())")).toEqual(246);
|
||||||
|
expect(scope.$eval("obj['sum'](obj.getA())")).toEqual(246);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should evaluate objects on scope context', function() {
|
it('should evaluate objects on scope context', function() {
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ describe('Scope', function() {
|
||||||
module(provideLog);
|
module(provideLog);
|
||||||
inject(function($rootScope, log) {
|
inject(function($rootScope, log) {
|
||||||
$rootScope.fn = function() {return 'a'};
|
$rootScope.fn = function() {return 'a'};
|
||||||
$rootScope.$watch('fn', function(scope, fn) {
|
$rootScope.$watch('fn', function(fn) {
|
||||||
log(fn());
|
log(fn());
|
||||||
});
|
});
|
||||||
$rootScope.$digest();
|
$rootScope.$digest();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue