diff options
Diffstat (limited to 'devtools')
-rw-r--r-- | devtools/shared/webconsole/js-property-provider.js | 16 | ||||
-rw-r--r-- | devtools/shared/webconsole/test/unit/test_js_property_provider.js | 32 |
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); } /** |