diff --git a/src/ng/parse.js b/src/ng/parse.js index 125119cf728b..cddde467bc59 100644 --- a/src/ng/parse.js +++ b/src/ng/parse.js @@ -48,23 +48,22 @@ function ensureSafeMemberName(name, fullExpression) { return name; } -function getStringValue(name, fullExpression) { - // From the JavaScript docs: +function getStringValue(name) { // Property names must be strings. This means that non-string objects cannot be used // as keys in an object. Any non-string object, including a number, is typecasted // into a string via the toString method. + // -- MDN, https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Property_accessors#Property_names // - // So, to ensure that we are checking the same `name` that JavaScript would use, - // we cast it to a string, if possible. - // Doing `name + ''` can cause a repl error if the result to `toString` is not a string, - // this is, this will handle objects that misbehave. - name = name + ''; - if (!isString(name)) { - throw $parseMinErr('iseccst', - 'Cannot convert object to primitive value! ' - + 'Expression: {0}', fullExpression); - } - return name; + // So, to ensure that we are checking the same `name` that JavaScript would use, we cast it + // to a string. It's not always possible. If `name` is an object and its `toString` method is + // 'broken' (doesn't return a string, isn't a function, etc.), an error will be thrown: + // + // TypeError: Cannot convert object to primitive value + // + // For performance reasons, we don't catch this error here and allow it to propagate up the call + // stack. Note that you'll get the same error in JavaScript if you try to access a property using + // such a 'broken' object as a key. + return name + ''; } function ensureSafeObject(obj, fullExpression) { @@ -1231,7 +1230,7 @@ ASTCompiler.prototype = { }, getStringValue: function(item) { - this.assign(item, 'getStringValue(' + item + ',text)'); + this.assign(item, 'getStringValue(' + item + ')'); }, ensureSafeAssignContext: function(item) { diff --git a/test/ng/parseSpec.js b/test/ng/parseSpec.js index 1a1041c62d8e..a11cb6c06d0b 100644 --- a/test/ng/parseSpec.js +++ b/test/ng/parseSpec.js @@ -2201,6 +2201,19 @@ describe('parser', function() { expect(scope.$eval('true || false || run()')).toBe(true); }); + it('should throw TypeError on using a \'broken\' object as a key to access a property', function() { + scope.object = {}; + forEach([ + { toString: 2 }, + { toString: null }, + { toString: function() { return {}; } } + ], function(brokenObject) { + scope.brokenObject = brokenObject; + expect(function() { + scope.$eval('object[brokenObject]'); + }).toThrow(); + }); + }); it('should support method calls on primitive types', function() { scope.empty = '';