diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index 0b4c08223..5b2c18105 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -1,5 +1,10 @@ ## 24.3.7-wip +- `callServiceExtension` now checks the runtime for the list of registered + service extensions. It also now throws a `RPCError` with + `RPCErrorKind.kMethodNotFound` when a service extension is not found instead + of throwing a JS evaluation error. + ## 24.3.6 - Bump minimum sdk version to 3.7.0 diff --git a/dwds/lib/src/debugging/inspector.dart b/dwds/lib/src/debugging/inspector.dart index b2a8fcdd1..7128adde0 100644 --- a/dwds/lib/src/debugging/inspector.dart +++ b/dwds/lib/src/debugging/inspector.dart @@ -115,8 +115,7 @@ class AppInspector implements AppInspectorInterface { await DartUri.initialize(); DartUri.recordAbsoluteUris(libraries.map((lib) => lib.uri).nonNulls); DartUri.recordAbsoluteUris(scripts.map((script) => script.uri).nonNulls); - - isolate.extensionRPCs?.addAll(await _getExtensionRpcs()); + await getExtensionRpcs(); } static IsolateRef _toIsolateRef(Isolate isolate) => IsolateRef( @@ -760,11 +759,16 @@ class AppInspector implements AppInspectorInterface { scriptId == null ? null : _scriptRefsById[scriptId]; /// Runs an eval on the page to compute all existing registered extensions. - Future> _getExtensionRpcs() async { + /// + /// Combines this with the RPCs registered in the [isolate]. Use this over + /// [Isolate.extensionRPCs] as this computes a live set. + /// + /// Updates [Isolate.extensionRPCs] to this set. + Future> getExtensionRpcs() async { final expression = globalToolConfiguration.loadStrategy.dartRuntimeDebugger .getDartDeveloperExtensionNamesJsExpression(); - final extensionRpcs = []; + final extensionRpcs = {}; final params = { 'expression': expression, 'returnByValue': true, @@ -784,6 +788,7 @@ class AppInspector implements AppInspectorInterface { s, ); } + isolate.extensionRPCs = List.of(extensionRpcs); return extensionRpcs; } diff --git a/dwds/lib/src/services/chrome_proxy_service.dart b/dwds/lib/src/services/chrome_proxy_service.dart index 93b9f6751..71f496b22 100644 --- a/dwds/lib/src/services/chrome_proxy_service.dart +++ b/dwds/lib/src/services/chrome_proxy_service.dart @@ -343,7 +343,7 @@ class ChromeProxyService implements VmServiceInterface { // TODO: We shouldn't need to fire these events since they exist on the // isolate, but devtools doesn't recognize extensions after a page refresh // otherwise. - for (final extensionRpc in inspector.isolate.extensionRPCs ?? []) { + for (final extensionRpc in await inspector.getExtensionRpcs()) { _streamNotify( 'Isolate', Event( @@ -509,6 +509,13 @@ class ChromeProxyService implements VmServiceInterface { v is String ? v : jsonEncode(v), ), ); + if (!(await inspector.getExtensionRpcs()).contains(method)) { + throw RPCError( + method, + RPCErrorKind.kMethodNotFound.code, + 'Unknown service method: $method', + ); + } final expression = globalToolConfiguration.loadStrategy.dartRuntimeDebugger .invokeExtensionJsExpression(method, jsonEncode(stringArgs)); final result = await inspector.jsEvaluate(expression, awaitPromise: true); diff --git a/dwds/test/common/chrome_proxy_service_common.dart b/dwds/test/common/chrome_proxy_service_common.dart index 1c165f620..178aed35a 100644 --- a/dwds/test/common/chrome_proxy_service_common.dart +++ b/dwds/test/common/chrome_proxy_service_common.dart @@ -298,6 +298,20 @@ void runTests({ ), }, ); + + test('not found', () async { + final serviceMethod = 'ext.test.missingServiceExtension'; + expect( + service.callServiceExtension(serviceMethod), + throwsA( + predicate( + (dynamic error) => + error is RPCError && + error.code == RPCErrorKind.kMethodNotFound.code, + ), + ), + ); + }); }); group('VMTimeline', () {