diff --git a/src/language/JSUtils.js b/src/language/JSUtils.js index 509402daacc..3763e5f44ab 100644 --- a/src/language/JSUtils.js +++ b/src/language/JSUtils.js @@ -262,7 +262,10 @@ define(function (require, exports, module) { rangeResults = []; docEntries.forEach(function (docEntry) { - if (docEntry.functions.hasOwnProperty(functionName)) { + // Need to call CollectionUtils.hasProperty here since docEntry.functions could + // have an entry for "hasOwnProperty", which results in an error if trying to + // invoke docEntry.functions.hasOwnProperty(). + if (CollectionUtils.hasProperty(docEntry.functions, functionName)) { var functionsInDocument = docEntry.functions[functionName]; matchedDocuments.push({doc: docEntry.doc, fileInfo: docEntry.fileInfo, functions: functionsInDocument}); } diff --git a/src/utils/CollectionUtils.js b/src/utils/CollectionUtils.js index c9145a509af..1e338976a8a 100644 --- a/src/utils/CollectionUtils.js +++ b/src/utils/CollectionUtils.js @@ -62,7 +62,21 @@ define(function (require, exports, module) { } } + /** + * Returns true if the object has the specified property. + * This calls the Object.prototype.hasOwnProperty function directly, rather than + * depending on the object having a function named "hasOwnProperty". This way the + * object *can* have a property named "hasOwnProperty" that is not a function. + * @param {*} object The object to test + * @param {string} property The name of the property to query + * @return {boolean} True if the object contains the property + */ + function hasProperty(object, property) { + return Object.prototype.hasOwnProperty.apply(object, [property]); + } + // Define public API exports.indexOf = indexOf; exports.forEach = forEach; + exports.hasProperty = hasProperty; }); diff --git a/src/utils/StringMatch.js b/src/utils/StringMatch.js index 760dbdd382f..9471185d0f9 100644 --- a/src/utils/StringMatch.js +++ b/src/utils/StringMatch.js @@ -805,7 +805,7 @@ define(function (require, exports, module) { } // Load up the cached specials information (or build it if this is our first time through). - var special = this._specialsCache.hasOwnProperty(str) ? this._specialsCache[str] : undefined; + var special = CollectionUtils.hasProperty(this._specialsCache, str) ? this._specialsCache[str] : undefined; if (special === undefined) { special = findSpecialCharacters(str); this._specialsCache[str] = special; diff --git a/test/spec/JSUtils-test-files/tricky.js b/test/spec/JSUtils-test-files/tricky.js index 8131d1b3590..16ccf52f32e 100644 --- a/test/spec/JSUtils-test-files/tricky.js +++ b/test/spec/JSUtils-test-files/tricky.js @@ -7,3 +7,8 @@ function toString() { function length() { return 0; } + +// This function's name collides with an Object.prototype member +function hasOwnProperty() { + return false; +} diff --git a/test/spec/JSUtils-test.js b/test/spec/JSUtils-test.js index 0a8cf1cd974..4b0e8eb82e2 100644 --- a/test/spec/JSUtils-test.js +++ b/test/spec/JSUtils-test.js @@ -260,6 +260,7 @@ define(function (require, exports, module) { runs(function () { expectFunctionRanges(this, this.fileJsContent, "toString", [ {start: 1, end: 3} ]); expectFunctionRanges(this, this.fileJsContent, "length", [ {start: 6, end: 8} ]); + expectFunctionRanges(this, this.fileJsContent, "hasOwnProperty", [ {start: 11, end: 13} ]); }); }); @@ -462,6 +463,15 @@ define(function (require, exports, module) { expect(functions[0].lineStart).toBe(6); expect(functions[0].lineEnd).toBe(8); }); + + indexAndFind(function (fileInfos) { + return JSUtils.findMatchingFunctions("hasOwnProperty", fileInfos); + }); + runs(function () { + expect(functions.length).toBe(1); + expect(functions[0].lineStart).toBe(11); + expect(functions[0].lineEnd).toBe(13); + }); }); }); diff --git a/test/spec/StringMatch-test.js b/test/spec/StringMatch-test.js index 89eee836375..27e77dd60f1 100644 --- a/test/spec/StringMatch-test.js +++ b/test/spec/StringMatch-test.js @@ -641,6 +641,10 @@ define(function (require, exports, module) { // Array.prototype has length var lengthResult = matcher.match("length", "l"); expect(lengthResult).toBeTruthy(); + + // Object.prototype has hasOwnProperty + var hasOwnPropertyResult = matcher.match("hasOwnProperty", "h"); + expect(hasOwnPropertyResult).toBeTruthy(); }); }); });