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

Parse loop vars #15954

Closed
wants to merge 4 commits 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
12 changes: 10 additions & 2 deletions src/ng/directive/ngOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,9 @@ var ngOptionsMinErr = minErr('ngOptions');
*/

/* eslint-disable max-len */
// //00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555555000000000666666666666600000007777777777777000000000000000888888888800000000000000000009999999999
var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([$\w][$\w]*)|(?:\(\s*([$\w][$\w]*)\s*,\s*([$\w][$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
// Changed groups 5-7 like this: ([$\w][$\w]*) => ([^\s(),]+). 02.05.17 E.P.
//00001111111111000000000002222222222000000000000000000000333333333300000000000000000000000004444444444400000000000005555555555500000000066666666666000000077777777777000000000000000888888888800000000000000000009999999999
var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([^\s(),]+)|(?:\(\s*([^\s(),]+)\s*,\s*([^\s(),]+)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
// 1: value expression (valueFn)
// 2: label expression (displayFn)
// 3: group by expression (groupByFn)
Expand Down Expand Up @@ -268,6 +269,13 @@ var ngOptionsDirective = ['$compile', '$document', '$parse', function($compile,
// The variable name for the key of the item in the collection
var keyName = match[6];

// Use $parse service to check identifiers. 02.05.17 E.P.
if (!$parse.is_valid_identifier(valueName))
throw ngOptionsMinErr('badident', 'Not valid option value identifier: \'{0}\'.', valueName);

if (keyName && !$parse.is_valid_identifier(keyName))
throw ngOptionsMinErr('badident', 'Not valid option key identifier: \'{0}\'.', keyName);

// An expression that generates the viewValue for an option if there is a label expression
var selectAs = / as /.test(match[0]) && match[1];
// An expression that is used to track the id of each object in the options collection
Expand Down
12 changes: 10 additions & 2 deletions src/ng/directive/ngRepeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,8 @@ var ngRepeatDirective = ['$parse', '$animate', '$compile', function($parse, $ani
var aliasAs = match[3];
var trackByExp = match[4];

match = lhs.match(/^(?:(\s*[$\w]+)|\(\s*([$\w]+)\s*,\s*([$\w]+)\s*\))$/);
// Changed groups like this: ([$\w]+) => ([^\s(),]+). 02.05.17 E.P.
match = lhs.match(/^(?:\s*([^\s(),]+)|\(\s*([^\s(),]+)\s*,\s*([^\s(),]+)\s*\))$/);

if (!match) {
throw ngRepeatMinErr('iidexp', '\'_item_\' in \'_item_ in _collection_\' should be an identifier or \'(_key_, _value_)\' expression, but got \'{0}\'.',
Expand All @@ -394,7 +395,14 @@ var ngRepeatDirective = ['$parse', '$animate', '$compile', function($parse, $ani
var valueIdentifier = match[3] || match[1];
var keyIdentifier = match[2];

if (aliasAs && (!/^[$a-zA-Z_][$a-zA-Z0-9_]*$/.test(aliasAs) ||
// Use $parse service to check identifiers. 01.05.17 E.P.
if (!$parse.is_valid_identifier(valueIdentifier))
throw ngRepeatMinErr('badident', 'Not valid loop value identifier: \'{0}\'.', valueIdentifier);

if (keyIdentifier && !$parse.is_valid_identifier(keyIdentifier))
throw ngRepeatMinErr('badident', 'Not valid loop key identifier: \'{0}\'.', keyIdentifier);

if (aliasAs && (!$parse.is_valid_identifier(aliasAs) ||
/^(null|undefined|this|\$index|\$first|\$middle|\$last|\$even|\$odd|\$parent|\$root|\$id)$/.test(aliasAs))) {
throw ngRepeatMinErr('badident', 'alias \'{0}\' is invalid --- must be a valid JS identifier which is not a reserved name.',
aliasAs);
Expand Down
31 changes: 31 additions & 0 deletions src/ng/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,37 @@ function $ParseProvider() {
isIdentifierStart: isFunction(identStart) && identStart,
isIdentifierContinue: isFunction(identContinue) && identContinue
};

// Check if given text is a valid identifier. 01.05.17 E.P.
var valid_identifier_lexer;
$parse.is_valid_identifier = function(
var_name
) {
// Check argument
if (!var_name ||
typeof var_name !== 'string'
) return false;
//console.log('$parse.is_valid_identifier entry "' + var_name + '"');

// Instantiate lexer once, when required
if (valid_identifier_lexer === undefined)
valid_identifier_lexer = new Lexer($parseOptions);

// Parse given text into tokens
var tokens = valid_identifier_lexer.lex(var_name);
//console.log('$parse.is_valid_identifier tokens = ' + JSON.stringify(tokens));

// The whole text expected to be one token of "identifier" type
var result = (
tokens &&
tokens.length === 1 &&
tokens[0].index === 0 &&
tokens[0].text === var_name &&
tokens[0].identifier === true);
//console.log('$parse.is_valid_identifier result = ' + result);
return result;
};

return $parse;

function $parse(exp, interceptorFn) {
Expand Down