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

Commit 8ddfa2a

Browse files
committed
fix($parse): correctly escape unsafe identifier characters
This commit also adds a couple of tests for `$parseProvider.setIdentifierFns()`. Closes #14942
1 parent d642380 commit 8ddfa2a

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

src/ng/parse.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1261,7 +1261,7 @@ ASTCompiler.prototype = {
12611261
},
12621262

12631263
nonComputedMember: function(left, right) {
1264-
var SAFE_IDENTIFIER = /[$_a-zA-Z][$_a-zA-Z0-9]*/;
1264+
var SAFE_IDENTIFIER = /^[$_a-zA-Z][$_a-zA-Z0-9]*$/;
12651265
var UNSAFE_CHARACTERS = /[^$_a-zA-Z0-9]/g;
12661266
if (SAFE_IDENTIFIER.test(right)) {
12671267
return left + '.' + right;

test/ng/parseSpec.js

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3897,4 +3897,92 @@ describe('parser', function() {
38973897
});
38983898
});
38993899
});
3900+
3901+
forEach([true, false], function(cspEnabled) {
3902+
describe('custom identifiers (csp: ' + cspEnabled + ')', function() {
3903+
var isIdentifierStartRe = /[#a-z]/;
3904+
var isIdentifierContinueRe = /[\-a-z]/;
3905+
var isIdentifierStartFn;
3906+
var isIdentifierContinueFn;
3907+
var scope;
3908+
3909+
beforeEach(module(function($parseProvider) {
3910+
isIdentifierStartFn = jasmine.
3911+
createSpy('isIdentifierStart').
3912+
and.callFake(function(ch, cp) { return isIdentifierStartRe.test(ch); });
3913+
isIdentifierContinueFn = jasmine.
3914+
createSpy('isIdentifierContinue').
3915+
and.callFake(function(ch, cp) { return isIdentifierContinueRe.test(ch); });
3916+
3917+
$parseProvider.setIdentifierFns(isIdentifierStartFn, isIdentifierContinueFn);
3918+
csp().noUnsafeEval = cspEnabled;
3919+
}));
3920+
3921+
beforeEach(inject(function($rootScope) {
3922+
scope = $rootScope;
3923+
}));
3924+
3925+
3926+
it('should allow specifying a custom `isIdentifierStart/Continue` functions', function() {
3927+
scope.x = {};
3928+
3929+
scope['#foo'] = 'foo';
3930+
scope.x['#foo'] = 'foo';
3931+
expect(scope.$eval('#foo')).toBe('foo');
3932+
expect(scope.$eval('x.#foo')).toBe('foo');
3933+
3934+
scope['bar--'] = 42;
3935+
scope.x['bar--'] = 42;
3936+
expect(scope.$eval('bar--')).toBe(42);
3937+
expect(scope.$eval('x.bar--')).toBe(42);
3938+
expect(scope['bar--']).toBe(42);
3939+
expect(scope.x['bar--']).toBe(42);
3940+
3941+
scope['#-'] = 'baz';
3942+
scope.x['#-'] = 'baz';
3943+
expect(scope.$eval('#-')).toBe('baz');
3944+
expect(scope.$eval('x.#-')).toBe('baz');
3945+
3946+
expect(function() { scope.$eval('##'); }).toThrow();
3947+
expect(function() { scope.$eval('x.##'); }).toThrow();
3948+
3949+
expect(function() { scope.$eval('--'); }).toThrow();
3950+
expect(function() { scope.$eval('x.--'); }).toThrow();
3951+
});
3952+
3953+
3954+
it('should pass the character and codepoint to the custom functions', function() {
3955+
scope.$eval('#-');
3956+
expect(isIdentifierStartFn).toHaveBeenCalledOnceWith('#', '#'.charCodeAt(0));
3957+
expect(isIdentifierContinueFn).toHaveBeenCalledOnceWith('-', '-'.charCodeAt(0));
3958+
3959+
isIdentifierStartFn.calls.reset();
3960+
isIdentifierContinueFn.calls.reset();
3961+
3962+
scope.$eval('#.foo.#-.bar-');
3963+
expect(isIdentifierStartFn).toHaveBeenCalledTimes(7);
3964+
expect(isIdentifierStartFn.calls.allArgs()).toEqual([
3965+
['#', '#'.charCodeAt(0)],
3966+
['.', '.'.charCodeAt(0)],
3967+
['f', 'f'.charCodeAt(0)],
3968+
['.', '.'.charCodeAt(0)],
3969+
['#', '#'.charCodeAt(0)],
3970+
['.', '.'.charCodeAt(0)],
3971+
['b', 'b'.charCodeAt(0)]
3972+
]);
3973+
expect(isIdentifierContinueFn).toHaveBeenCalledTimes(9);
3974+
expect(isIdentifierContinueFn.calls.allArgs()).toEqual([
3975+
['.', '.'.charCodeAt(0)],
3976+
['o', 'o'.charCodeAt(0)],
3977+
['o', 'o'.charCodeAt(0)],
3978+
['.', '.'.charCodeAt(0)],
3979+
['-', '-'.charCodeAt(0)],
3980+
['.', '.'.charCodeAt(0)],
3981+
['a', 'a'.charCodeAt(0)],
3982+
['r', 'r'.charCodeAt(0)],
3983+
['-', '-'.charCodeAt(0)]
3984+
]);
3985+
});
3986+
});
3987+
});
39003988
});

0 commit comments

Comments
 (0)