diff --git a/devtools/shared/webconsole/js-property-provider.js b/devtools/shared/webconsole/js-property-provider.js index e19d7501ec7d..812c0d176ac3 100644 --- a/devtools/shared/webconsole/js-property-provider.js +++ b/devtools/shared/webconsole/js-property-provider.js @@ -238,12 +238,18 @@ function JSPropertyProvider(aDbgObject, anEnvironment, aInputValue, aCursor) // We get the rest of the properties recursively starting from the Debugger.Object // that wraps the first property - for (let prop of properties) { - prop = prop.trim(); + for (let i = 0; i < properties.length; i++) { + let prop = properties[i].trim(); if (!prop) { return null; } + // Special case for 'this' since it's not part of the global's properties + // but we want autocompletion to work properly for it + if (prop === "this" && obj === aDbgObject && i === 0) { + continue; + } + if (/\[\d+\]$/.test(prop)) { // The property to autocomplete is a member of array. For example // list[i][j]..[n]. Traverse the array to get the actual element. @@ -263,7 +269,15 @@ function JSPropertyProvider(aDbgObject, anEnvironment, aInputValue, aCursor) return getMatchedProps(obj, matchProp); } - return getMatchedPropsInDbgObject(obj, matchProp); + let matchedProps = getMatchedPropsInDbgObject(obj, matchProp); + if (properties.length !== 0 || obj !== aDbgObject) { + let thisInd = matchedProps.matches.indexOf("this"); + if (thisInd > -1) { + matchedProps.matches.splice(thisInd, 1) + } + } + + return matchedProps; } /** @@ -482,7 +496,17 @@ var DebuggerObjectSupport = { getProperties: function(aObj) { - return aObj.getOwnPropertyNames(); + let names = aObj.getOwnPropertyNames(); + // Include 'this' in results (in sorted order). It will be removed + // in all cases except for the first property request on the global, but + // it needs to be added now so it can be filtered based on string input. + for (let i = 0; i < names.length; i++) { + if (i === names.length - 1 || names[i+1] > "this") { + names.splice(i+1, 0, "this"); + break; + } + } + return names; }, getProperty: function(aObj, aName, aRootObj) diff --git a/devtools/shared/webconsole/test/unit/test_js_property_provider.js b/devtools/shared/webconsole/test/unit/test_js_property_provider.js index d2d001458862..e00cec1d0013 100644 --- a/devtools/shared/webconsole/test/unit/test_js_property_provider.js +++ b/devtools/shared/webconsole/test/unit/test_js_property_provider.js @@ -33,8 +33,8 @@ function run_test() { Components.utils.evalInSandbox(testObject, sandbox); Components.utils.evalInSandbox(testHyphenated, sandbox); - let results = JSPropertyProvider(dbgObject, null, "testArray[0]."); do_print("Test that suggestions are given for 'foo[n]' where n is an integer."); + let results = JSPropertyProvider(dbgObject, null, "testArray[0]."); test_has_result(results, "propA"); do_print("Test that suggestions are given for multidimensional arrays."); @@ -49,6 +49,18 @@ function run_test() { results = JSPropertyProvider(dbgObject, null, "[1,2,3,\n4\n]."); test_has_result(results, "indexOf"); + do_print("Test that suggestions are given for 'this'"); + results = JSPropertyProvider(dbgObject, null, "t"); + test_has_result(results, "this"); + + do_print("Test that suggestions are given for 'this.'"); + results = JSPropertyProvider(dbgObject, null, "this."); + test_has_result(results, "testObject"); + + do_print("Test that no suggestions are given for 'this.this'"); + results = JSPropertyProvider(dbgObject, null, "this.this"); + test_has_no_results(results); + do_print("Test that suggestions are given for literal strings."); results = JSPropertyProvider(dbgObject, null, "'foo'."); test_has_result(results, "charAt");