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

Commit 26cfc74

Browse files
committed
fix(events): fix property expression extraction code to not break $parse
1 parent cb55c9a commit 26cfc74

File tree

2 files changed

+58
-6
lines changed

2 files changed

+58
-6
lines changed

src/modules/events.js

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,43 @@
66
var ngEventAttributes = require('../lib/event-directives'),
77
MODULE_NAME = 'Events';
88

9+
/*
10+
* Remove string expressions except property accessors.
11+
* ex. abc["def"] = "gef"; // `removeStringExp` will remove "gef" but not "def".
12+
*/
13+
function removeStringExp(str) {
14+
return str.replace(/"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'/g,
15+
function(match, pos, full) {
16+
// this is our lookaround code so that our regex doesn't become so
17+
// complicated.
18+
if (pos !== 0 && (match.length + pos) !== full.length &&
19+
full[pos - 1] === '[' && full[pos + match.length] === ']') {
20+
return match;
21+
}
22+
return '';
23+
});
24+
}
925

1026
var getFunctionNames = function(str) {
1127
if (typeof str !== 'string') {
1228
return [];
1329
}
14-
var results = str.replace(/\s+/g, '').split(/[\+\-\/\|\<\>\^=&!%~;]/g).map(function(x) {
15-
if (isNaN(+x)) {
16-
if (x.match(/\w+\(.*\)$/)){
17-
return x.substr(0, x.indexOf('('));
30+
// There are still a bunch of corner cases here where we aren't going to be able to handle
31+
// but we shouldn't break the user's app and we should handle most common cases.
32+
// example of corner cases: we can't check for properties inside of function
33+
// arguments like `move(a.b.c)` with the current implementation
34+
// or property accessors with parentheses in them
35+
// like `prop["hello (world)"] = "test";`.
36+
// To fully fix these issues we would need a full blown expression parser.
37+
var results = removeStringExp(str.replace(/\s+/g, ''))
38+
.replace(/\(.*?\)/g, '')
39+
.split(/[\+\-\/\|\<\>\^=&!%~;]/g).map(function(x) {
40+
if (isNaN(+x)) {
41+
if (x.match(/\w+\(.*\)$/)){
42+
return x.substr(0, x.indexOf('('));
43+
}
44+
return x;
1845
}
19-
return x;
20-
}
2146
}).filter(function(x){
2247
return x;
2348
});

test/events.spec.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,33 @@ describe('hintEvents', function() {
5656
expect(angular.hint.emit).toHaveBeenCalledWith('Events:undef', 'a.b is undefined');
5757
});
5858

59+
it('should be able to check strings expressions with operator characters in angular expressions', function() {
60+
var elt = angular.element('<button ng-click="a.b.c = \'-hello>\';[\'array\']">Fake Increment</button>');
61+
$rootScope.a = { b: { c: '' } }
62+
$compile(elt)($rootScope);
63+
64+
$rootScope.$digest();
65+
expect(angular.hint.emit).not.toHaveBeenCalledWith('Events:undef', 'a.b.c is undefined');
66+
});
67+
68+
it('should be able to check multiple angular expressions including string expressions with operator characters', function() {
69+
var elt = angular.element('<button ng-click="j.f.k;x.y.z = \'-hello\'"></button>');
70+
$compile(elt)($rootScope);
71+
72+
$rootScope.$digest();
73+
expect(angular.hint.emit).toHaveBeenCalledWith('Events:undef', 'x.y.z is undefined');
74+
expect(angular.hint.emit).toHaveBeenCalledWith('Events:undef', 'j.f.k is undefined');
75+
});
76+
77+
it('should be able to check expressions with operator characters in function invocation', function() {
78+
var elt = angular.element('<button ng-click="showPanel(-1);move(a > b)"></button>');
79+
$compile(elt)($rootScope);
80+
81+
$rootScope.$digest();
82+
expect(angular.hint.emit).toHaveBeenCalledWith('Events:undef', 'showPanel is undefined');
83+
expect(angular.hint.emit).toHaveBeenCalledWith('Events:undef', 'move is undefined');
84+
});
85+
5986
// TODO: implement this
6087
it('should log a message if the path to handle an ng-event is not found', function() {
6188
var elt = angular.element('<button ng-click="a.b.c()">Fake Increment</button>');

0 commit comments

Comments
 (0)