summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--devtools/shared/webconsole/js-property-provider.js16
-rw-r--r--devtools/shared/webconsole/test/unit/test_js_property_provider.js32
2 files changed, 48 insertions, 0 deletions
diff --git a/devtools/shared/webconsole/js-property-provider.js b/devtools/shared/webconsole/js-property-provider.js
index dff2af50a6..64b78673e0 100644
--- a/devtools/shared/webconsole/js-property-provider.js
+++ b/devtools/shared/webconsole/js-property-provider.js
@@ -178,6 +178,22 @@ function JSPropertyProvider(dbgObject, anEnvironment, inputValue, cursor) {
}
let completionPart = inputValue.substring(beginning.startPos);
+
+ // Strip optional chaining characters from completion part, which we check
+ // by looking if it has ?. and if there are no digits (marker for ternary).
+ let optionalChainRegex = /\?\./g;
+ let optionalElemAccessRegex = /\?\.\[/g;
+ let digitRegex = /\?\.\d/;
+ // Handle optional element access
+ if (optionalElemAccessRegex.test(completionPart)) {
+ completionPart = completionPart.replace(optionalElemAccessRegex, "[");
+ }
+ // Handle optional chaining characters
+ if (optionalChainRegex.test(completionPart) &&
+ !digitRegex.test(completionPart)) {
+ completionPart = completionPart.replace(optionalChainRegex, ".");
+ }
+
let lastDot = completionPart.lastIndexOf(".");
// Don't complete on just an empty string.
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 c360cf96d9..53fca33081 100644
--- a/devtools/shared/webconsole/test/unit/test_js_property_provider.js
+++ b/devtools/shared/webconsole/test/unit/test_js_property_provider.js
@@ -145,6 +145,38 @@ function runChecks(dbgObject, dbgEnv) {
do_print("Test that suggestions are not given if there is an hyphen in the chain.");
results = JSPropertyProvider(dbgObject, dbgEnv, "testHyphenated['prop-A'].");
do_check_null(results);
+
+ do_print("Test that expression with optional chaining operator are completed");
+ results = JSPropertyProvider(dbgObject, dbgEnv, "testObject?.prop");
+ test_has_result(results, "propA");
+
+ results = JSPropertyProvider(dbgObject, dbgEnv, "testObject?.propA[0]?.propB?.to");
+ test_has_result(results, "toString");
+
+ results = JSPropertyProvider(dbgObject, dbgEnv, "testObject?.propA?.[0]?.propB?.to");
+ test_has_result(results, "toString");
+
+ results = JSPropertyProvider(dbgObject, dbgEnv, "[1,2,3]?.");
+ test_has_result(results, "indexOf");
+
+ results = JSPropertyProvider(dbgObject, dbgEnv, "'foo'?.");
+ test_has_result(results, "charAt");
+
+ // Check this doesn't throw since `propC` is not defined.
+ results = JSPropertyProvider(dbgObject, dbgEnv, "testObject?.propC?.this?.does?.not?.exist?.d");
+
+ // Test more ternary
+ results = JSPropertyProvider(dbgObject, dbgEnv, "true ? t");
+ test_has_result(results, "testObject");
+
+ results = JSPropertyProvider(dbgObject, dbgEnv, "true ?? t");
+ test_has_result(results, "testObject");
+
+ results = JSPropertyProvider(dbgObject, dbgEnv, "true ? /* comment */ t");
+ test_has_result(results, "testObject");
+
+ results = JSPropertyProvider(dbgObject, dbgEnv, "true?<t");
+ test_has_no_results(results);
}
/**