mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-25 22:33:44 +00:00
Cleanup parser code to expose smaller API
This commit is contained in:
parent
bb67ee8d28
commit
0e17ade959
7 changed files with 31 additions and 54 deletions
|
|
@ -35,19 +35,14 @@ function toJson(obj, pretty) {
|
||||||
function fromJson(json, useNative) {
|
function fromJson(json, useNative) {
|
||||||
if (!isString(json)) return json;
|
if (!isString(json)) return json;
|
||||||
|
|
||||||
var obj, p, expression;
|
var obj;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (useNative && window.JSON && window.JSON.parse) {
|
if (useNative && window.JSON && window.JSON.parse) {
|
||||||
obj = JSON.parse(json);
|
obj = JSON.parse(json);
|
||||||
return transformDates(obj);
|
return transformDates(obj);
|
||||||
}
|
}
|
||||||
|
return parser(json, true).primary()();
|
||||||
p = parser(json, true);
|
|
||||||
expression = p.primary();
|
|
||||||
p.assertAllConsumed();
|
|
||||||
return expression();
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error("fromJson error: ", json, e);
|
error("fromJson error: ", json, e);
|
||||||
throw e;
|
throw e;
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,6 @@ function expressionCompile(exp){
|
||||||
if (!fn) {
|
if (!fn) {
|
||||||
var p = parser(exp);
|
var p = parser(exp);
|
||||||
var fnSelf = p.statements();
|
var fnSelf = p.statements();
|
||||||
p.assertAllConsumed();
|
|
||||||
fn = compileCache[exp] = extend(
|
fn = compileCache[exp] = extend(
|
||||||
function(){ return fnSelf(this);},
|
function(){ return fnSelf(this);},
|
||||||
{fnSelf: fnSelf});
|
{fnSelf: fnSelf});
|
||||||
|
|
|
||||||
|
|
@ -240,22 +240,29 @@ function parser(text, json){
|
||||||
function (){ throwError("is not valid json", {text:text, index:0}); };
|
function (){ throwError("is not valid json", {text:text, index:0}); };
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
assertAllConsumed: assertAllConsumed,
|
assignable: assertConsumed(assignable),
|
||||||
assignable: assignable,
|
primary: assertConsumed(primary),
|
||||||
primary: primary,
|
statements: assertConsumed(statements),
|
||||||
statements: statements,
|
validator: assertConsumed(validator),
|
||||||
validator: validator,
|
formatter: assertConsumed(formatter),
|
||||||
formatter: formatter,
|
filter: assertConsumed(filter)
|
||||||
filter: filter,
|
|
||||||
//TODO: delete me, since having watch in UI is logic in UI. (leftover form getangular)
|
|
||||||
watch: watch
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function assertConsumed(fn) {
|
||||||
|
return function(){
|
||||||
|
var value = fn();
|
||||||
|
if (tokens.length !== 0) {
|
||||||
|
throwError("is an unexpected token", tokens[0]);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
function throwError(msg, token) {
|
function throwError(msg, token) {
|
||||||
throw Error("Parse Error: Token '" + token.text +
|
throw Error("Syntax Error: Token '" + token.text +
|
||||||
"' " + msg + " at column " +
|
"' " + msg + " at column " +
|
||||||
(token.index + 1) + " of expression [" +
|
(token.index + 1) + " of the expression [" +
|
||||||
text + "] starting at [" + text.substring(token.index) + "].");
|
text + "] starting at [" + text.substring(token.index) + "].");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -313,12 +320,6 @@ function parser(text, json){
|
||||||
return tokens.length > 0;
|
return tokens.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertAllConsumed(){
|
|
||||||
if (tokens.length !== 0) {
|
|
||||||
throwError("is extra token not part of expression", tokens[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function statements(){
|
function statements(){
|
||||||
var statements = [];
|
var statements = [];
|
||||||
while(true) {
|
while(true) {
|
||||||
|
|
@ -639,24 +640,6 @@ function parser(text, json){
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: delete me, since having watch in UI is logic in UI. (leftover form getangular)
|
|
||||||
function watch () {
|
|
||||||
var decl = [];
|
|
||||||
while(hasTokens()) {
|
|
||||||
decl.push(watchDecl());
|
|
||||||
if (!expect(';')) {
|
|
||||||
assertAllConsumed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assertAllConsumed();
|
|
||||||
return function (self){
|
|
||||||
for ( var i = 0; i < decl.length; i++) {
|
|
||||||
var d = decl[i](self);
|
|
||||||
self.addListener(d.name, d.fn);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function watchDecl () {
|
function watchDecl () {
|
||||||
var anchorName = expect().text;
|
var anchorName = expect().text;
|
||||||
consume(":");
|
consume(":");
|
||||||
|
|
|
||||||
|
|
@ -581,7 +581,7 @@ describe('Binder', function(){
|
||||||
|
|
||||||
browserTrigger(second, 'click');
|
browserTrigger(second, 'click');
|
||||||
assertTrue(second.hasClass("ng-exception"));
|
assertTrue(second.hasClass("ng-exception"));
|
||||||
expect(errorLogs.shift()[0]).toMatchError(/Parse Error: Token ':' not a primary expression/);
|
expect(errorLogs.shift()[0]).toMatchError(/Syntax Error: Token ':' not a primary expression/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('ItShouldSelectTheCorrectRadioBox', function(){
|
it('ItShouldSelectTheCorrectRadioBox', function(){
|
||||||
|
|
|
||||||
|
|
@ -163,37 +163,37 @@ describe('json', function(){
|
||||||
describe('security', function(){
|
describe('security', function(){
|
||||||
it('should not allow naked expressions', function(){
|
it('should not allow naked expressions', function(){
|
||||||
expect(function(){fromJson('1+2');}).
|
expect(function(){fromJson('1+2');}).
|
||||||
toThrow(new Error("Parse Error: Token '+' is extra token not part of expression at column 2 of expression [1+2] starting at [+2]."));
|
toThrow(new Error("Syntax Error: Token '+' is an unexpected token at column 2 of the expression [1+2] starting at [+2]."));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow naked expressions group', function(){
|
it('should not allow naked expressions group', function(){
|
||||||
expect(function(){fromJson('(1+2)');}).
|
expect(function(){fromJson('(1+2)');}).
|
||||||
toThrow(new Error("Parse Error: Token '(' is not valid json at column 1 of expression [(1+2)] starting at [(1+2)]."));
|
toThrow(new Error("Syntax Error: Token '(' is not valid json at column 1 of the expression [(1+2)] starting at [(1+2)]."));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow expressions in objects', function(){
|
it('should not allow expressions in objects', function(){
|
||||||
expect(function(){fromJson('{a:abc()}');}).
|
expect(function(){fromJson('{a:abc()}');}).
|
||||||
toThrow(new Error("Parse Error: Token 'abc' is not valid json at column 4 of expression [{a:abc()}] starting at [abc()}]."));
|
toThrow(new Error("Syntax Error: Token 'abc' is not valid json at column 4 of the expression [{a:abc()}] starting at [abc()}]."));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow expressions in arrays', function(){
|
it('should not allow expressions in arrays', function(){
|
||||||
expect(function(){fromJson('[1+2]');}).
|
expect(function(){fromJson('[1+2]');}).
|
||||||
toThrow(new Error("Parse Error: Token '+' is not valid json at column 3 of expression [[1+2]] starting at [+2]]."));
|
toThrow(new Error("Syntax Error: Token '+' is not valid json at column 3 of the expression [[1+2]] starting at [+2]]."));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow vars', function(){
|
it('should not allow vars', function(){
|
||||||
expect(function(){fromJson('[1, x]');}).
|
expect(function(){fromJson('[1, x]');}).
|
||||||
toThrow(new Error("Parse Error: Token 'x' is not valid json at column 5 of expression [[1, x]] starting at [x]]."));
|
toThrow(new Error("Syntax Error: Token 'x' is not valid json at column 5 of the expression [[1, x]] starting at [x]]."));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow dereference', function(){
|
it('should not allow dereference', function(){
|
||||||
expect(function(){fromJson('["".constructor]');}).
|
expect(function(){fromJson('["".constructor]');}).
|
||||||
toThrow(new Error("Parse Error: Token '.' is not valid json at column 4 of expression [[\"\".constructor]] starting at [.constructor]]."));
|
toThrow(new Error("Syntax Error: Token '.' is not valid json at column 4 of the expression [[\"\".constructor]] starting at [.constructor]]."));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow expressions ofter valid json', function(){
|
it('should not allow expressions ofter valid json', function(){
|
||||||
expect(function(){fromJson('[].constructor');}).
|
expect(function(){fromJson('[].constructor');}).
|
||||||
toThrow(new Error("Parse Error: Token '.' is not valid json at column 3 of expression [[].constructor] starting at [.constructor]."));
|
toThrow(new Error("Syntax Error: Token '.' is not valid json at column 3 of the expression [[].constructor] starting at [.constructor]."));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not allow object dereference', function(){
|
it('should not allow object dereference', function(){
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,7 @@ describe('parser', function() {
|
||||||
|
|
||||||
expect(function() {
|
expect(function() {
|
||||||
scope.$eval("1|nonExistant");
|
scope.$eval("1|nonExistant");
|
||||||
}).toThrow(new Error("Parse Error: Token 'nonExistant' should be a function at column 3 of expression [1|nonExistant] starting at [nonExistant]."));
|
}).toThrow(new Error("Syntax Error: Token 'nonExistant' should be a function at column 3 of the expression [1|nonExistant] starting at [nonExistant]."));
|
||||||
|
|
||||||
scope.$set('offset', 3);
|
scope.$set('offset', 3);
|
||||||
expect(scope.$eval("'abcd'|upper._case")).toEqual("ABCD");
|
expect(scope.$eval("'abcd'|upper._case")).toEqual("ABCD");
|
||||||
|
|
|
||||||
|
|
@ -537,7 +537,7 @@ describe("widget", function(){
|
||||||
compile('<input type="text" name="throw \'\'" value="x"/>');
|
compile('<input type="text" name="throw \'\'" value="x"/>');
|
||||||
expect(element.hasClass('ng-exception')).toBeTruthy();
|
expect(element.hasClass('ng-exception')).toBeTruthy();
|
||||||
expect(scope.$service('$log').error.logs.shift()[0]).
|
expect(scope.$service('$log').error.logs.shift()[0]).
|
||||||
toMatchError(/Parse Error: Token '''' is extra token not part of expression/);
|
toMatchError(/Syntax Error: Token '''' is an unexpected token/);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should report error on ng:change exception', function(){
|
it('should report error on ng:change exception', function(){
|
||||||
|
|
@ -545,7 +545,7 @@ describe("widget", function(){
|
||||||
browserTrigger(element);
|
browserTrigger(element);
|
||||||
expect(element.hasClass('ng-exception')).toBeTruthy();
|
expect(element.hasClass('ng-exception')).toBeTruthy();
|
||||||
expect(scope.$service('$log').error.logs.shift()[0]).
|
expect(scope.$service('$log').error.logs.shift()[0]).
|
||||||
toMatchError(/Parse Error: Token '=' implies assignment but \[a-2\] can not be assigned to/);
|
toMatchError(/Syntax Error: Token '=' implies assignment but \[a-2\] can not be assigned to/);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue