зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1231489 - Use content prototype for autocompletion of String, Number and Array literals; r=bgrins.
When provided a string, number or array literals, we use to simply return the properties from String.prototype, Number.prototype and Array.prototype. This is working fine unless the content prototypes are modified. In order to make it work properly, we retrieve the actual content prototype. The js-property-provider unit test is modified to ensure this is working as expected. Differential Revision: https://phabricator.services.mozilla.com/D15843 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
273cf84cc9
Коммит
09c8a73d83
|
@ -290,6 +290,7 @@ function JSPropertyProvider({
|
|||
return null;
|
||||
}
|
||||
|
||||
const env = environment || dbgObject.asEnvironment();
|
||||
const completionPart = lastStatement;
|
||||
const lastDotIndex = completionPart.lastIndexOf(".");
|
||||
const lastOpeningBracketIndex = isElementAccess ? completionPart.lastIndexOf("[") : -1;
|
||||
|
@ -319,12 +320,12 @@ function JSPropertyProvider({
|
|||
let matchingObject;
|
||||
|
||||
if (astExpression.type === "ArrayExpression") {
|
||||
matchingObject = Array.prototype;
|
||||
matchingObject = getContentPrototypeObject(env, "Array");
|
||||
} else if (
|
||||
astExpression.type === "Literal" &&
|
||||
typeof astExpression.value === "string"
|
||||
) {
|
||||
matchingObject = String.prototype;
|
||||
matchingObject = getContentPrototypeObject(env, "String");
|
||||
} else if (
|
||||
astExpression.type === "Literal" &&
|
||||
Number.isFinite(astExpression.value)
|
||||
|
@ -338,7 +339,7 @@ function JSPropertyProvider({
|
|||
!Number.isInteger(astExpression.value) ||
|
||||
/\d[^\.]{0}\.$/.test(completionPart) === false
|
||||
) {
|
||||
matchingObject = Number.prototype;
|
||||
matchingObject = getContentPrototypeObject(env, "Number");
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
@ -353,7 +354,7 @@ function JSPropertyProvider({
|
|||
search = matchProp.replace(startQuoteRegex, "");
|
||||
}
|
||||
|
||||
let props = getMatchedProps(matchingObject, search);
|
||||
let props = getMatchedPropsInDbgObject(matchingObject, search);
|
||||
if (isElementAccess) {
|
||||
props = wrapMatchesInQuotes(props, elementAccessQuote);
|
||||
}
|
||||
|
@ -398,11 +399,6 @@ function JSPropertyProvider({
|
|||
}
|
||||
|
||||
let obj = dbgObject;
|
||||
|
||||
// The first property must be found in the environment of the paused debugger
|
||||
// or of the global lexical scope.
|
||||
const env = environment || obj.asEnvironment();
|
||||
|
||||
if (properties.length === 0) {
|
||||
return {
|
||||
isElementAccess,
|
||||
|
@ -514,6 +510,29 @@ function JSPropertyProvider({
|
|||
return prepareReturnedObject(getMatchedPropsInDbgObject(obj, search));
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given environment and constructor name, returns its Debugger.Object wrapped
|
||||
* prototype.
|
||||
*
|
||||
* @param {Environment} env
|
||||
* @param {String} name: Name of the constructor object we want the prototype of.
|
||||
* @returns {Debugger.Object|null} the prototype, or null if it not found.
|
||||
*/
|
||||
function getContentPrototypeObject(env, name) {
|
||||
// Retrieve the outermost environment to get the global object.
|
||||
let outermostEnv = env;
|
||||
while (outermostEnv && outermostEnv.parent) {
|
||||
outermostEnv = outermostEnv.parent;
|
||||
}
|
||||
|
||||
const constructorObj = DevToolsUtils.getProperty(outermostEnv.object, name);
|
||||
if (!constructorObj) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return DevToolsUtils.getProperty(constructorObj, "prototype");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} ast: An AST representing a property access (e.g. `foo.bar["baz"].x`)
|
||||
* @returns {Array|null} An array representing the property access
|
||||
|
|
|
@ -67,6 +67,12 @@ function run_test() {
|
|||
const dbg = new Debugger();
|
||||
const dbgObject = dbg.addDebuggee(sandbox);
|
||||
const dbgEnv = dbgObject.asEnvironment();
|
||||
Cu.evalInSandbox(`
|
||||
const hello = Object.create(null, Object.getOwnPropertyDescriptors({world: 1}));
|
||||
String.prototype.hello = hello;
|
||||
Number.prototype.hello = hello;
|
||||
Array.prototype.hello = hello;
|
||||
`, sandbox);
|
||||
Cu.evalInSandbox(testArray, sandbox);
|
||||
Cu.evalInSandbox(testObject, sandbox);
|
||||
Cu.evalInSandbox(testHyphenated, sandbox);
|
||||
|
@ -149,6 +155,12 @@ function runChecks(dbgObject, environment, sandbox) {
|
|||
results = propertyProvider("[1,2,3].");
|
||||
test_has_result(results, "indexOf");
|
||||
|
||||
results = propertyProvider("[1,2,3].h");
|
||||
test_has_result(results, "hello");
|
||||
|
||||
results = propertyProvider("[1,2,3].hello.w");
|
||||
test_has_result(results, "world");
|
||||
|
||||
info("Test that suggestions are given for literal arrays with newlines.");
|
||||
results = propertyProvider("[1,2,3,\n4\n].");
|
||||
test_has_result(results, "indexOf");
|
||||
|
@ -168,6 +180,10 @@ function runChecks(dbgObject, environment, sandbox) {
|
|||
test_has_result(results, "charAt");
|
||||
results = propertyProvider("'[1,2,3]'.");
|
||||
test_has_result(results, "charAt");
|
||||
results = propertyProvider("'foo'.h");
|
||||
test_has_result(results, "hello");
|
||||
results = propertyProvider("'foo'.hello.w");
|
||||
test_has_result(results, "world");
|
||||
|
||||
info("Test that suggestions are not given for syntax errors.");
|
||||
results = propertyProvider("'foo\"");
|
||||
|
@ -349,6 +365,12 @@ function runChecks(dbgObject, environment, sandbox) {
|
|||
results = propertyProvider("(1)['toFixed");
|
||||
test_has_exact_results(results, ["'toFixed'"]);
|
||||
|
||||
results = propertyProvider("(1).h");
|
||||
test_has_result(results, "hello");
|
||||
|
||||
results = propertyProvider("(1).hello.w");
|
||||
test_has_result(results, "world");
|
||||
|
||||
info("Test access on dot-notation invalid property name");
|
||||
results = propertyProvider("testHyphenated.prop");
|
||||
Assert.ok(!results.matches.has("prop-A"),
|
||||
|
|
Загрузка…
Ссылка в новой задаче