Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit f33d95c

Browse files
fpipitagkalpak
authored andcommitted
feat($parse): add a hidden interface to retrieve an expression's AST
This PR adds a new private method to the `$parse` service, `$$getAst`, which takes an Angular expression as its only argument and returns the computed AST. This feature is not meant to be part of the public API and might be subject to changes, so use it with caution. Closes #16253 Closes #16260
1 parent 57b626a commit f33d95c

File tree

2 files changed

+72
-10
lines changed

2 files changed

+72
-10
lines changed

src/ng/parse.js

+28-10
Original file line numberDiff line numberDiff line change
@@ -1644,11 +1644,26 @@ Parser.prototype = {
16441644
constructor: Parser,
16451645

16461646
parse: function(text) {
1647-
var ast = this.ast.ast(text);
1648-
var fn = this.astCompiler.compile(ast);
1649-
fn.literal = isLiteral(ast);
1650-
fn.constant = isConstant(ast);
1647+
var ast = this.getAst(text);
1648+
var fn = this.astCompiler.compile(ast.ast);
1649+
fn.literal = isLiteral(ast.ast);
1650+
fn.constant = isConstant(ast.ast);
1651+
fn.oneTime = ast.oneTime;
16511652
return fn;
1653+
},
1654+
1655+
getAst: function(exp) {
1656+
var oneTime = false;
1657+
exp = exp.trim();
1658+
1659+
if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
1660+
oneTime = true;
1661+
exp = exp.substring(2);
1662+
}
1663+
return {
1664+
ast: this.ast.ast(exp),
1665+
oneTime: oneTime
1666+
};
16521667
}
16531668
};
16541669

@@ -1771,10 +1786,11 @@ function $ParseProvider() {
17711786
isIdentifierStart: isFunction(identStart) && identStart,
17721787
isIdentifierContinue: isFunction(identContinue) && identContinue
17731788
};
1789+
$parse.$$getAst = $$getAst;
17741790
return $parse;
17751791

17761792
function $parse(exp, interceptorFn) {
1777-
var parsedExpression, oneTime, cacheKey;
1793+
var parsedExpression, cacheKey;
17781794

17791795
switch (typeof exp) {
17801796
case 'string':
@@ -1784,16 +1800,12 @@ function $ParseProvider() {
17841800
parsedExpression = cache[cacheKey];
17851801

17861802
if (!parsedExpression) {
1787-
if (exp.charAt(0) === ':' && exp.charAt(1) === ':') {
1788-
oneTime = true;
1789-
exp = exp.substring(2);
1790-
}
17911803
var lexer = new Lexer($parseOptions);
17921804
var parser = new Parser(lexer, $filter, $parseOptions);
17931805
parsedExpression = parser.parse(exp);
17941806
if (parsedExpression.constant) {
17951807
parsedExpression.$$watchDelegate = constantWatchDelegate;
1796-
} else if (oneTime) {
1808+
} else if (parsedExpression.oneTime) {
17971809
parsedExpression.$$watchDelegate = parsedExpression.literal ?
17981810
oneTimeLiteralWatchDelegate : oneTimeWatchDelegate;
17991811
} else if (parsedExpression.inputs) {
@@ -1811,6 +1823,12 @@ function $ParseProvider() {
18111823
}
18121824
}
18131825

1826+
function $$getAst(exp) {
1827+
var lexer = new Lexer($parseOptions);
1828+
var parser = new Parser(lexer, $filter, $parseOptions);
1829+
return parser.getAst(exp).ast;
1830+
}
1831+
18141832
function expressionInputDirtyCheck(newValue, oldValueOfValue, compareObjectIdentity) {
18151833

18161834
if (newValue == null || oldValueOfValue == null) { // null/undefined

test/ng/parseSpec.js

+44
Original file line numberDiff line numberDiff line change
@@ -3994,4 +3994,48 @@ describe('parser', function() {
39943994
});
39953995
});
39963996
});
3997+
3998+
describe('hidden/unsupported features', function() {
3999+
describe('$$getAst()', function() {
4000+
it('should be a method exposed on the `$parse` service', inject(function($parse) {
4001+
expect(isFunction($parse.$$getAst)).toBeTruthy();
4002+
}));
4003+
4004+
it('should accept a string expression argument and return the corresponding AST', inject(function($parse) {
4005+
var ast = $parse.$$getAst('foo.bar');
4006+
expect(ast).toEqual({
4007+
type: 'Program',
4008+
body: [
4009+
{
4010+
type: 'ExpressionStatement',
4011+
expression: {
4012+
type: 'MemberExpression',
4013+
object: { type: 'Identifier', name: 'foo' },
4014+
property: { type: 'Identifier', name: 'bar' },
4015+
computed: false
4016+
}
4017+
}
4018+
]
4019+
});
4020+
}));
4021+
4022+
it('should parse one time binding expressions', inject(function($parse) {
4023+
var ast = $parse.$$getAst('::foo.bar');
4024+
expect(ast).toEqual({
4025+
type: 'Program',
4026+
body: [
4027+
{
4028+
type: 'ExpressionStatement',
4029+
expression: {
4030+
type: 'MemberExpression',
4031+
object: { type: 'Identifier', name: 'foo' },
4032+
property: { type: 'Identifier', name: 'bar' },
4033+
computed: false
4034+
}
4035+
}
4036+
]
4037+
});
4038+
}));
4039+
});
4040+
});
39974041
});

0 commit comments

Comments
 (0)