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

feat($parse): Custom private field tagging #4859

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/content/error/parse/iresre.ngdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@ngdoc error
@name $parse:iresre
@fullName Invalid matching pattern for tagging private fields
@description

Occurs when a non-regexp expression is assigned as the
matching pattern used to tag private fields.

Example that will throw this error:

```
$parseProvider.restrictFieldsMatching('priv');
```

If you want to tag private fields with a 'priv' preffix
you should do this instead:
```
$parseProvider.restrictFieldsMatching(/priv/);
```
33 changes: 32 additions & 1 deletion src/ng/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
var $parseMinErr = minErr('$parse');
var promiseWarningCache = {};
var promiseWarning;
var restrictFieldsMatching = /^_|_$/;

// Sandboxing Angular Expressions
// ------------------------------
Expand Down Expand Up @@ -47,7 +48,7 @@ function ensureSafeMemberName(name, fullExpression, allowConstructor) {
'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}',
fullExpression);
}
if (name.charAt(0) === '_' || name.charAt(name.length-1) === '_') {
if (restrictFieldsMatching && (name.match(restrictFieldsMatching))) {
throw $parseMinErr('isecprv',
'Referencing private fields in Angular expressions is disallowed! Expression: {0}',
fullExpression);
Expand Down Expand Up @@ -1207,6 +1208,36 @@ function $ParseProvider() {
};


/**
* @ngdoc method
* @name ng.$parseProvider#restrictFieldsMatching
* @methodOf ng.$parseProvider
* @description
*
* Allows using a custom regular expression for tagging private fields. You
* can turn off private fields by passing `null` as a parameter.
*
* The default is set to `/$_|_^/` which means every fields that begins or ends with an
* underscore.
*
* @param {RegExp=} value New value.
* @returns {RegExp} Returns the current setting
*/
this.restrictFieldsMatching = function(value) {
if (isDefined(value)) {
if ((value === null) || (value instanceof RegExp)) {
restrictFieldsMatching = value;
}
else {
throw $parseMinErr('iresre',
'Invalid expression for matching private fields! Expression: {0}',
value);
}
}
return restrictFieldsMatching;
};


this.$get = ['$filter', '$sniffer', '$log', function($filter, $sniffer, $log) {
$parseOptions.csp = $sniffer.csp;

Expand Down
42 changes: 40 additions & 2 deletions test/ng/parseSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,11 @@ describe('parser', function() {
});
});

var $filterProvider, scope;
var $filterProvider, scope, $parseProvider;

beforeEach(module(['$filterProvider', function (filterProvider) {
beforeEach(module(['$filterProvider', '$parseProvider', function (filterProvider, parseProvider) {
$filterProvider = filterProvider;
$parseProvider = parseProvider;
}]));


Expand Down Expand Up @@ -592,6 +593,7 @@ describe('parser', function() {

describe('sandboxing', function() {
describe('private members', function() {

it('should NOT allow access to private members', function() {
forEach(['_name', 'name_', '_', '_name_'], function(name) {
function _testExpression(expression) {
Expand Down Expand Up @@ -640,6 +642,42 @@ describe('parser', function() {
testExpression('a["b"]["NAME"]'); testExpression('a["b"]["NAME"] = 1');
});
});

it('should allow disabling and custom tagging of private members', function() {
// test default behaviour
expect($parseProvider.restrictFieldsMatching()).toEqual(/^_|_$/);
scope._a = 1;
expect(function() {
scope.$eval('_a');
}).toThrowMinErr(
'$parse', 'isecprv', 'Referencing private fields in Angular expressions is disallowed! ' +
'Expression: _a');

// disable restricted field access
expect(function() {
$parseProvider.restrictFieldsMatching(null);
scope.$eval('_a');
}).not.toThrow();

// custom restricted fields
scope.privateVar = 1;
expect(function() {
$parseProvider.restrictFieldsMatching(/^priv/);
scope.$eval('privateVar');
}).toThrowMinErr(
'$parse', 'isecprv', 'Referencing private fields in Angular expressions is disallowed! ' +
'Expression: privateVar');

// invalid custom expression
expect(function() {
$parseProvider.restrictFieldsMatching('priv');
}).toThrowMinErr(
'$parse', 'iresre', 'Invalid expression for matching private fields! ' +
'Expression: priv');

// set default value again
$parseProvider.restrictFieldsMatching(/^_|_$/);
});
});

describe('Function constructor', function() {
Expand Down