Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7989c7d24a | |||
| 5c36f466e1 | |||
| f8151afd90 | |||
| 74120eaa0f | |||
| b370fac4fc | |||
| 23fc73081f | |||
| e5e69d9b90 | |||
| fa722447f8 | |||
| 81d10e819e | |||
| 809ca94e1c | |||
| 824eab9029 | |||
| d503dfe99b |
@@ -1,3 +1,21 @@
|
||||
# <angular/> 0.9.7 sonic-scream (2010-12-10) #
|
||||
|
||||
### Bug Fixes
|
||||
- $defer service should always call $eval on the root scope after a callback runs (issue #189)
|
||||
- fix for failed assignments of form obj[0].name=value (issue #169)
|
||||
- significant parser improvements that resulted in lower memory usage
|
||||
(commit 23fc73081feb640164615930b36ef185c23a3526)
|
||||
|
||||
### Docs
|
||||
- small docs improvements (mainly docs for the $resource service)
|
||||
|
||||
### Breaking changes
|
||||
- Angular expressions in the view used to support regular expressions. This feature was rarely
|
||||
used and added unnecessary complexity. It not a good idea to have regexps in the view anyway,
|
||||
so we removed this support. If you had any regexp in your views, you will have to move them to
|
||||
your controllers. (commit e5e69d9b90850eb653883f52c76e28dd870ee067)
|
||||
|
||||
|
||||
# <angular/> 0.9.6 night-vision (2010-12-06) #
|
||||
|
||||
### Security
|
||||
|
||||
+1
-1
@@ -208,7 +208,7 @@ function propertyTag(doc, name, value) {
|
||||
}
|
||||
|
||||
function returnsTag(doc, name, value) {
|
||||
var match = value.match(/^{(\S+)}\s+(.*)?/);
|
||||
var match = value.match(/^{(\S+)}\s+([\s\S]*)?/);
|
||||
|
||||
if (match) {
|
||||
var tag = {
|
||||
|
||||
+7
-8
@@ -42,7 +42,7 @@ a {
|
||||
#api-list {
|
||||
position: absolute;
|
||||
top: 3em;
|
||||
bottom: 0;
|
||||
bottom: 1em;
|
||||
overflow-y: scroll;
|
||||
padding-right: 0.8em;
|
||||
}
|
||||
@@ -225,25 +225,24 @@ a {
|
||||
|
||||
::-webkit-scrollbar{
|
||||
width:0.8em;
|
||||
height:0.8em;
|
||||
border-left: 1px solid #ccc;
|
||||
margin: 0.2em 0em;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar:hover{
|
||||
background-color:#eee;
|
||||
}
|
||||
::-webkit-resizer{
|
||||
-webkit-border-radius:0.3em;
|
||||
background-color:#666;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb{
|
||||
min-height:0.8em;
|
||||
min-width:0.8em;
|
||||
-webkit-border-radius:0.3em;
|
||||
-webkit-border-radius:0.5em;
|
||||
background-color: #ddd;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:hover{
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb:active{
|
||||
background-color:#888;
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@
|
||||
<div id="header">
|
||||
<h1>
|
||||
<span class="main-title">{{getTitle()}}</span>
|
||||
<a href="index.html"><span class="angular"><angular/></span> Docs</a>
|
||||
<a href="#"><span class="angular"><angular/></span> Docs</a>
|
||||
</h1>
|
||||
</div>
|
||||
<div id="sidebar">
|
||||
|
||||
@@ -182,6 +182,12 @@ describe('collect', function(){
|
||||
TAG.returns(doc, 'returns', '{string} descrip *tion*');
|
||||
expect(doc.returns).toEqual({type: 'string', description: 'descrip <em>tion</em>'});
|
||||
});
|
||||
|
||||
it('should support multiline content', function() {
|
||||
TAG.returns(doc, 'returns', '{string} description\n new line\n another line');
|
||||
expect(doc.returns).
|
||||
toEqual({type: 'string', description: 'description\n new line\n another line'});
|
||||
});
|
||||
});
|
||||
|
||||
describe('@description', function(){
|
||||
|
||||
+1
-1
@@ -699,7 +699,7 @@ function concat(array1, array2, index) {
|
||||
*
|
||||
* @param {Object} self Context in which `fn` should be evaluated in.
|
||||
* @param {function()} fn Function to be bound.
|
||||
* @param {(...*)=} args Optional arguments to be prebound to the `fn` function call.
|
||||
* @param {...*} args Optional arguments to be prebound to the `fn` function call.
|
||||
* @returns {function()} Function that wraps the `fn` with all the specified bindings.
|
||||
*/
|
||||
function bind(self, fn) {
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ function getterFn(path){
|
||||
code += 'if(!s) return s;\n' +
|
||||
'l=s;\n' +
|
||||
's=s' + key + ';\n' +
|
||||
'if(typeof s=="function") s = function(){ return l'+key+'.apply(l, arguments); };\n';
|
||||
'if(typeof s=="function" && !(s instanceof RegExp)) s = function(){ return l'+key+'.apply(l, arguments); };\n';
|
||||
if (key.charAt(1) == '$') {
|
||||
// special code for super-imposed functions
|
||||
var name = key.substr(2);
|
||||
|
||||
+71
-138
@@ -9,7 +9,7 @@ var OPERATORS = {
|
||||
'/':function(self, a,b){return a/b;},
|
||||
'%':function(self, a,b){return a%b;},
|
||||
'^':function(self, a,b){return a^b;},
|
||||
'=':function(self, a,b){return setter(self, a, b);},
|
||||
'=':noop,
|
||||
'==':function(self, a,b){return a==b;},
|
||||
'!=':function(self, a,b){return a!=b;},
|
||||
'<':function(self, a,b){return a<b;},
|
||||
@@ -32,7 +32,7 @@ function lex(text, parseStringsForObjects){
|
||||
index = 0,
|
||||
json = [],
|
||||
ch,
|
||||
lastCh = ':'; // can start regexp
|
||||
lastCh = ':';
|
||||
|
||||
while (index < text.length) {
|
||||
ch = text.charAt(index);
|
||||
@@ -40,8 +40,6 @@ function lex(text, parseStringsForObjects){
|
||||
readString(ch);
|
||||
} else if (isNumber(ch) || is('.') && isNumber(peek())) {
|
||||
readNumber();
|
||||
} else if ( was('({[:,;') && is('/') ) {
|
||||
readRegexp();
|
||||
} else if (isIdent(ch)) {
|
||||
readIdent();
|
||||
if (was('{,') && json[0]=='{' &&
|
||||
@@ -73,6 +71,9 @@ function lex(text, parseStringsForObjects){
|
||||
lastCh = ch;
|
||||
}
|
||||
return tokens;
|
||||
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
||||
function is(chars) {
|
||||
return chars.indexOf(ch) != -1;
|
||||
@@ -97,10 +98,6 @@ function lex(text, parseStringsForObjects){
|
||||
'A' <= ch && ch <= 'Z' ||
|
||||
'_' == ch || ch == '$';
|
||||
}
|
||||
function isExpOperator(ch) {
|
||||
return ch == '-' || ch == '+' || isNumber(ch);
|
||||
}
|
||||
|
||||
function throwError(error, start, end) {
|
||||
end = end || index;
|
||||
throw Error("Lexer Error: " + error + " at column" +
|
||||
@@ -109,128 +106,61 @@ function lex(text, parseStringsForObjects){
|
||||
" " + end) +
|
||||
" in expression [" + text + "].");
|
||||
}
|
||||
|
||||
function consume(regexp, processToken, errorMsg) {
|
||||
var match = text.substr(index).match(regexp);
|
||||
var token = {index: index};
|
||||
var start = index;
|
||||
if (!match) throwError(errorMsg);
|
||||
index += match[0].length;
|
||||
processToken(token, token.text = match[0], start);
|
||||
tokens.push(token);
|
||||
}
|
||||
|
||||
function readNumber() {
|
||||
var number = "";
|
||||
var start = index;
|
||||
while (index < text.length) {
|
||||
var ch = lowercase(text.charAt(index));
|
||||
if (ch == '.' || isNumber(ch)) {
|
||||
number += ch;
|
||||
} else {
|
||||
var peekCh = peek();
|
||||
if (ch == 'e' && isExpOperator(peekCh)) {
|
||||
number += ch;
|
||||
} else if (isExpOperator(ch) &&
|
||||
peekCh && isNumber(peekCh) &&
|
||||
number.charAt(number.length - 1) == 'e') {
|
||||
number += ch;
|
||||
} else if (isExpOperator(ch) &&
|
||||
(!peekCh || !isNumber(peekCh)) &&
|
||||
number.charAt(number.length - 1) == 'e') {
|
||||
throwError('Invalid exponent');
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
number = 1 * number;
|
||||
tokens.push({index:start, text:number, json:true,
|
||||
fn:function(){return number;}});
|
||||
consume(/^(\d+)?(\.\d+)?([eE][+-]?\d+)?/, function(token, number){
|
||||
token.text = number = 1 * number;
|
||||
token.json = true;
|
||||
token.fn = valueFn(number);
|
||||
}, "Not a valid number");
|
||||
}
|
||||
|
||||
function readIdent() {
|
||||
var ident = "";
|
||||
var start = index;
|
||||
while (index < text.length) {
|
||||
var ch = text.charAt(index);
|
||||
if (ch == '.' || isIdent(ch) || isNumber(ch)) {
|
||||
ident += ch;
|
||||
} else {
|
||||
break;
|
||||
consume(/^[\w_\$][\w_\$\d]*(\.[\w_\$][\w_\$\d]*)*/, function(token, ident){
|
||||
fn = OPERATORS[ident];
|
||||
if (!fn) {
|
||||
fn = getterFn(ident);
|
||||
fn.isAssignable = ident;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
var fn = OPERATORS[ident];
|
||||
if (!fn) {
|
||||
fn = getterFn(ident);
|
||||
fn.isAssignable = ident;
|
||||
}
|
||||
tokens.push({index:start, text:ident, fn:fn, json: OPERATORS[ident]});
|
||||
token.fn = OPERATORS[ident]||extend(getterFn(ident), {
|
||||
assign:function(self, value){
|
||||
return setter(self, ident, value);
|
||||
}
|
||||
});
|
||||
token.json = OPERATORS[ident];
|
||||
});
|
||||
}
|
||||
|
||||
function readString(quote) {
|
||||
var start = index;
|
||||
index++;
|
||||
var string = "";
|
||||
var rawString = quote;
|
||||
var escape = false;
|
||||
while (index < text.length) {
|
||||
var ch = text.charAt(index);
|
||||
rawString += ch;
|
||||
if (escape) {
|
||||
if (ch == 'u') {
|
||||
var hex = text.substring(index + 1, index + 5);
|
||||
if (!hex.match(/[\da-f]{4}/i))
|
||||
throwError( "Invalid unicode escape [\\u" + hex + "]");
|
||||
index += 4;
|
||||
string += String.fromCharCode(parseInt(hex, 16));
|
||||
} else {
|
||||
var rep = ESCAPE[ch];
|
||||
if (rep) {
|
||||
string += rep;
|
||||
} else {
|
||||
string += ch;
|
||||
}
|
||||
}
|
||||
escape = false;
|
||||
} else if (ch == '\\') {
|
||||
escape = true;
|
||||
} else if (ch == quote) {
|
||||
index++;
|
||||
tokens.push({index:start, text:rawString, string:string, json:true,
|
||||
fn:function(){
|
||||
return (string.length == dateParseLength) ?
|
||||
angular['String']['toDate'](string) : string;
|
||||
}});
|
||||
return;
|
||||
} else {
|
||||
string += ch;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
throwError("Unterminated quote", start);
|
||||
}
|
||||
function readRegexp(quote) {
|
||||
var start = index;
|
||||
index++;
|
||||
var regexp = "";
|
||||
var escape = false;
|
||||
while (index < text.length) {
|
||||
var ch = text.charAt(index);
|
||||
if (escape) {
|
||||
regexp += ch;
|
||||
escape = false;
|
||||
} else if (ch === '\\') {
|
||||
regexp += ch;
|
||||
escape = true;
|
||||
} else if (ch === '/') {
|
||||
index++;
|
||||
var flags = "";
|
||||
if (isIdent(text.charAt(index))) {
|
||||
readIdent();
|
||||
flags = tokens.pop().text;
|
||||
}
|
||||
var compiledRegexp = new RegExp(regexp, flags);
|
||||
tokens.push({index:start, text:regexp, flags:flags,
|
||||
fn:function(){return compiledRegexp;}});
|
||||
return;
|
||||
} else {
|
||||
regexp += ch;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
throwError("Unterminated RegExp", start);
|
||||
consume(/^(('(\\'|[^'])*')|("(\\"|[^"])*"))/, function(token, rawString, start){
|
||||
var hasError;
|
||||
var string = token.string = rawString.substr(1, rawString.length - 2).
|
||||
replace(/(\\u(.?.?.?.?))|(\\(.))/g,
|
||||
function(match, wholeUnicode, unicode, wholeEscape, escape){
|
||||
if (unicode && !unicode.match(/[\da-fA-F]{4}/))
|
||||
hasError = hasError || bind(null, throwError, "Invalid unicode escape [\\u" + unicode + "]", start);
|
||||
return unicode ?
|
||||
String.fromCharCode(parseInt(unicode, 16)) :
|
||||
ESCAPE[escape] || escape;
|
||||
});
|
||||
(hasError||noop)();
|
||||
token.json = true;
|
||||
token.fn = function(){
|
||||
return (string.length == dateParseLength) ?
|
||||
angular['String']['toDate'](string) :
|
||||
string;
|
||||
};
|
||||
}, "Unterminated string");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,14 +314,17 @@ function parser(text, json){
|
||||
|
||||
function assignment(){
|
||||
var left = logicalOR();
|
||||
var right;
|
||||
var token;
|
||||
if (token = expect('=')) {
|
||||
if (!left.isAssignable) {
|
||||
if (!left.assign) {
|
||||
throwError("implies assignment but [" +
|
||||
text.substring(0, token.index) + "] can not be assigned to", token);
|
||||
}
|
||||
var ident = function(){return left.isAssignable;};
|
||||
return binaryFn(ident, token.fn, logicalOR());
|
||||
right = logicalOR();
|
||||
return function(self){
|
||||
return left.assign(self, right(self));
|
||||
};
|
||||
} else {
|
||||
return left;
|
||||
}
|
||||
@@ -518,28 +451,28 @@ function parser(text, json){
|
||||
function fieldAccess(object) {
|
||||
var field = expect().text;
|
||||
var getter = getterFn(field);
|
||||
var fn = function (self){
|
||||
return extend(function (self){
|
||||
return getter(object(self));
|
||||
};
|
||||
fn.isAssignable = field;
|
||||
return fn;
|
||||
}, {
|
||||
assign:function(self, value){
|
||||
return setter(object(self), field, value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function objectIndex(obj) {
|
||||
var indexFn = expression();
|
||||
consume(']');
|
||||
if (expect('=')) {
|
||||
var rhs = expression();
|
||||
return function (self){
|
||||
return obj(self)[indexFn(self)] = rhs(self);
|
||||
};
|
||||
} else {
|
||||
return function (self){
|
||||
return extend(
|
||||
function (self){
|
||||
var o = obj(self);
|
||||
var i = indexFn(self);
|
||||
return (o) ? o[i] : _undefined;
|
||||
};
|
||||
}
|
||||
}, {
|
||||
assign:function(self, value){
|
||||
return obj(self)[indexFn(self)] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function functionCall(fn) {
|
||||
|
||||
+33
-15
@@ -819,12 +819,16 @@ angularServiceInject('$xhr.bulk', function($xhr, $error, $log){
|
||||
* @param {function()} fn A function, who's execution should be deferred.
|
||||
*/
|
||||
angularServiceInject('$defer', function($browser, $exceptionHandler) {
|
||||
var scope = this;
|
||||
|
||||
return function(fn) {
|
||||
$browser.defer(function() {
|
||||
try {
|
||||
fn();
|
||||
} catch(e) {
|
||||
$exceptionHandler(e);
|
||||
} finally {
|
||||
scope.$eval();
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -888,7 +892,7 @@ angularServiceInject('$xhr.cache', function($xhr, $defer){
|
||||
|
||||
/**
|
||||
* @workInProgress
|
||||
* @ngdoc service
|
||||
* @ngdoc function
|
||||
* @name angular.service.$resource
|
||||
* @requires $xhr
|
||||
*
|
||||
@@ -934,6 +938,33 @@ angularServiceInject('$xhr.cache', function($xhr, $defer){
|
||||
expect(newCard.id).toEqual(789);
|
||||
* </pre>
|
||||
*
|
||||
* The object returned from this function execution is a resource "class" which has "static" method
|
||||
* for each action in the definition.
|
||||
*
|
||||
* Calling these methods invoke `$xhr` on the `url` template with the given `method` and `params`.
|
||||
* When the data is returned from the server then the object is an instance of the resource type and
|
||||
* all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
|
||||
* operations (create, read, update, delete) on server-side data.
|
||||
|
||||
<pre>
|
||||
var User = $resource('/user/:userId', {userId:'@id'});
|
||||
var user = User.get({userId:123}, function(){
|
||||
user.abc = true;
|
||||
user.$save();
|
||||
});
|
||||
</pre>
|
||||
*
|
||||
* It's worth noting that the callback for `get`, `query` and other method gets passed in the
|
||||
* response that came from the server, so one could rewrite the above example as:
|
||||
*
|
||||
<pre>
|
||||
var User = $resource('/user/:userId', {userId:'@id'});
|
||||
User.get({userId:123}, function(u){
|
||||
u.abc = true;
|
||||
u.$save();
|
||||
});
|
||||
</pre>
|
||||
*
|
||||
*
|
||||
* @param {string} url A parameterized URL template with parameters prefixed by `:` as in
|
||||
* `/user/:username`.
|
||||
@@ -964,20 +995,7 @@ angularServiceInject('$xhr.cache', function($xhr, $defer){
|
||||
'delete': {method:'DELETE'} };
|
||||
* </pre>
|
||||
*
|
||||
* @returns {Object} A resource "class" which has "static" method for each action in the definition.
|
||||
* Calling these methods invoke `$xhr` on the `url` template with the given `method` and
|
||||
* `params`. When the data is returned from the server then the object is an instance of the
|
||||
* resource type and all of the non-GET methods are available with `$` prefix. This allows you
|
||||
* to easily support CRUD operations (create, read, update, delete) on server-side data.
|
||||
|
||||
<pre>
|
||||
var User = $resource('/user/:userId', {userId:'@id'});
|
||||
var user = User.get({userId:123}, function(){
|
||||
user.abc = true;
|
||||
user.$save();
|
||||
});
|
||||
</pre>
|
||||
*
|
||||
* @returns {Object} A resource "class".
|
||||
*
|
||||
* @example
|
||||
<script>
|
||||
|
||||
+2
-1
@@ -13,8 +13,9 @@ extend(angularValidator, {
|
||||
* @css ng-validation-error
|
||||
*
|
||||
* @example
|
||||
* <script> var ssn = /^\d\d\d-\d\d-\d\d\d\d$/; </script>
|
||||
* Enter valid SSN:
|
||||
* <input name="ssn" value="123-45-6789" ng:validate="regexp:/^\d\d\d-\d\d-\d\d\d\d$/" >
|
||||
* <input name="ssn" value="123-45-6789" ng:validate="regexp:$window.ssn" >
|
||||
*
|
||||
* @scenario
|
||||
* it('should invalidate non ssn', function(){
|
||||
|
||||
+16
-37
@@ -59,14 +59,6 @@ describe('parser', function() {
|
||||
expect(undefined).toEqual(tokens[i].fn());
|
||||
});
|
||||
|
||||
it('should tokenize RegExp', function() {
|
||||
var tokens = lex("/r 1/");
|
||||
var i = 0;
|
||||
expect(tokens[i].index).toEqual(0);
|
||||
expect(tokens[i].text).toEqual('r 1');
|
||||
expect("r 1".match(tokens[i].fn())[0]).toEqual('r 1');
|
||||
});
|
||||
|
||||
it('should tokenize quoted string', function() {
|
||||
var str = "['\\'', \"\\\"\"]";
|
||||
var tokens = lex(str);
|
||||
@@ -90,26 +82,15 @@ describe('parser', function() {
|
||||
expect(tokens.length).toEqual(1);
|
||||
expect(tokens[0].string).toEqual('\u00a0');
|
||||
});
|
||||
|
||||
it('should tokenize RegExp with options', function() {
|
||||
var tokens = lex("/r/g");
|
||||
var i = 0;
|
||||
expect(tokens[i].index).toEqual(0);
|
||||
expect(tokens[i].text).toEqual('r');
|
||||
expect(tokens[i].flags).toEqual('g');
|
||||
expect("rr".match(tokens[i].fn()).length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should tokenize RegExp with escaping', function() {
|
||||
var tokens = lex("/\\/\\d/");
|
||||
var i = 0;
|
||||
expect(tokens[i].index).toEqual(0);
|
||||
expect(tokens[i].text).toEqual('\\/\\d');
|
||||
expect("/1".match(tokens[i].fn())[0]).toEqual('/1');
|
||||
|
||||
it('should error when non terminated string', function(){
|
||||
expect(function(){
|
||||
lex('ignore "text');
|
||||
}).toThrow(new Error('Lexer Error: Unterminated string at column 7 in expression [ignore "text].'));
|
||||
});
|
||||
|
||||
it('should ignore whitespace', function() {
|
||||
var tokens = lex("a \t \n \r b");
|
||||
var tokens = lex("a \t \n \r \u00A0 b");
|
||||
expect(tokens[0].text).toEqual('a');
|
||||
expect(tokens[1].text).toEqual('b');
|
||||
});
|
||||
@@ -155,16 +136,6 @@ describe('parser', function() {
|
||||
expect(tokens[0].text).toEqual(0.5E+10);
|
||||
});
|
||||
|
||||
it('should throws exception for invalid exponent', function() {
|
||||
expect(function() {
|
||||
lex("0.5E-");
|
||||
}).toThrow(new Error('Lexer Error: Invalid exponent at column 4 in expression [0.5E-].'));
|
||||
|
||||
expect(function() {
|
||||
lex("0.5E-A");
|
||||
}).toThrow(new Error('Lexer Error: Invalid exponent at column 4 in expression [0.5E-A].'));
|
||||
});
|
||||
|
||||
it('should tokenize number starting with a dot', function() {
|
||||
var tokens = lex(".5");
|
||||
expect(tokens[0].text).toEqual(0.5);
|
||||
@@ -172,8 +143,8 @@ describe('parser', function() {
|
||||
|
||||
it('should throw error on invalid unicode', function() {
|
||||
expect(function() {
|
||||
lex("'\\u1''bla'");
|
||||
}).toThrow(new Error("Lexer Error: Invalid unicode escape [\\u1''b] at column 2 in expression ['\\u1''bla']."));
|
||||
lex("'\\u1xbla'");
|
||||
}).toThrow(new Error("Lexer Error: Invalid unicode escape [\\u1xbl] at columns 0-9 ['\\u1xbla'] in expression ['\\u1xbla']."));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -413,4 +384,12 @@ describe('parser', function() {
|
||||
expect(scope.$eval("a=undefined")).not.toBeDefined();
|
||||
expect(scope.$get("a")).not.toBeDefined();
|
||||
});
|
||||
|
||||
it('should allow assignment after array dereference', function(){
|
||||
scope = angular.scope();
|
||||
scope.obj = [{}];
|
||||
scope.$eval('obj[0].name=1');
|
||||
expect(scope.obj.name).toBeUndefined();
|
||||
expect(scope.obj[0].name).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -52,6 +52,11 @@ describe('scope/model', function(){
|
||||
model.$eval('name="works"');
|
||||
expect(model.name).toEqual('works');
|
||||
});
|
||||
|
||||
it('should not bind regexps', function(){
|
||||
model.exp = /abc/;
|
||||
expect(model.$eval('exp')).toEqual(model.exp);
|
||||
});
|
||||
|
||||
it('should do nothing on empty string and not update view', function(){
|
||||
var onEval = jasmine.createSpy('onEval');
|
||||
|
||||
+49
-1
@@ -361,12 +361,41 @@ describe("service", function(){
|
||||
|
||||
|
||||
it('should delegate exception to the $exceptionHandler service', function() {
|
||||
$defer(function() { throw "Test Error"; });
|
||||
$defer(function() {throw "Test Error";});
|
||||
expect($exceptionHandler).not.toHaveBeenCalled();
|
||||
|
||||
$browser.defer.flush();
|
||||
expect($exceptionHandler).toHaveBeenCalledWith("Test Error");
|
||||
});
|
||||
|
||||
|
||||
it('should call eval after each callback is executed', function() {
|
||||
var eval = this.spyOn(scope, '$eval').andCallThrough();
|
||||
|
||||
$defer(function() {});
|
||||
expect(eval).wasNotCalled();
|
||||
|
||||
$browser.defer.flush();
|
||||
expect(eval).wasCalled();
|
||||
|
||||
eval.reset(); //reset the spy;
|
||||
|
||||
$defer(function() {});
|
||||
$defer(function() {});
|
||||
$browser.defer.flush();
|
||||
expect(eval.callCount).toBe(2);
|
||||
});
|
||||
|
||||
|
||||
it('should call eval even if an exception is thrown in callback', function() {
|
||||
var eval = this.spyOn(scope, '$eval').andCallThrough();
|
||||
|
||||
$defer(function() {throw "Test Error"});
|
||||
expect(eval).wasNotCalled();
|
||||
|
||||
$browser.defer.flush();
|
||||
expect(eval).wasCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -543,6 +572,25 @@ describe("service", function(){
|
||||
$browser.defer.flush();
|
||||
expect(log).toEqual('"+";"+";'); //callback has executed
|
||||
});
|
||||
|
||||
it('should call eval after callbacks for both cache hit and cache miss execute', function() {
|
||||
var eval = this.spyOn(scope, '$eval').andCallThrough();
|
||||
|
||||
$browserXhr.expectGET('/url').respond('+');
|
||||
cache('GET', '/url', null, callback);
|
||||
expect(eval).wasNotCalled();
|
||||
|
||||
$browserXhr.flush();
|
||||
expect(eval).wasCalled();
|
||||
|
||||
eval.reset(); //reset the spy
|
||||
|
||||
cache('GET', '/url', null, callback);
|
||||
expect(eval).wasNotCalled();
|
||||
|
||||
$browser.defer.flush();
|
||||
expect(eval).wasCalled();
|
||||
})
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -13,6 +13,8 @@ if (window.jstestdriver) {
|
||||
}
|
||||
|
||||
beforeEach(function(){
|
||||
// This is to reset parsers global cache of expressions.
|
||||
compileCache = {};
|
||||
this.addMatchers({
|
||||
toBeInvalid: function(){
|
||||
var element = jqLite(this.actual);
|
||||
|
||||
+10
-3
@@ -41,6 +41,13 @@ describe("widget", function(){
|
||||
expect(scope.$get('name')).toEqual('Kai');
|
||||
expect(scope.$get('count')).toEqual(2);
|
||||
});
|
||||
|
||||
it('should allow complex refernce binding', function(){
|
||||
compile('<div ng:init="obj={abc:{}}">'+
|
||||
'<input type="Text" name="obj[\'abc\'].name" value="Misko""/>'+
|
||||
'</div>');
|
||||
expect(scope.obj['abc'].name).toEqual('Misko');
|
||||
});
|
||||
|
||||
describe("ng:format", function(){
|
||||
|
||||
@@ -564,8 +571,8 @@ describe("widget", function(){
|
||||
|
||||
// this one should really be just '1', but due to lack of real events things are not working
|
||||
// properly. see discussion at: http://is.gd/ighKk
|
||||
expect(element.text()).toEqual('2');
|
||||
dealoc(scope);
|
||||
expect(element.text()).toEqual('4');
|
||||
dealoc(element);
|
||||
});
|
||||
|
||||
it('should evaluate onload expression when a partial is loaded', function() {
|
||||
@@ -580,7 +587,7 @@ describe("widget", function(){
|
||||
scope.$inject('$browser').defer.flush();
|
||||
expect(element.text()).toEqual('my partial');
|
||||
expect(scope.loaded).toBe(true);
|
||||
dealoc(scope);
|
||||
dealoc(element);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
# <angular/> build config file
|
||||
---
|
||||
version: 0.9.6
|
||||
codename: night-vision
|
||||
version: 0.9.7
|
||||
codename: sonic-scream
|
||||
|
||||
Reference in New Issue
Block a user