handleResolveValues method
Resolves a list of CSS property values in the context of a node's render style. Params:
- nodeId: frontend node id
- declarations:
{ name: 'width', value: '50%' }, ...OR - text: 'width:50%; height: 10px;'
Returns: { resolved:
{ name: 'width', value: '160px' }, ...}
Implementation
void handleResolveValues(int? id, Map<String, dynamic> params) {
final ctx = dbgContext;
if (ctx == null) {
sendToFrontend(id, JSONEncodableMap({'results': [], 'resolved': []}));
return;
}
final int? frontendNodeId = params['nodeId'] as int?;
if (frontendNodeId == null) {
sendToFrontend(id, JSONEncodableMap({'results': [], 'resolved': []}));
return;
}
final targetId = ctx.getTargetIdByNodeId(frontendNodeId);
final BindingObject? obj = targetId != null && targetId != 0
? ctx.getBindingObject(Pointer.fromAddress(targetId))
: null;
final Element? element = obj is Element ? obj : null;
if (element == null) {
sendToFrontend(id, JSONEncodableMap({'results': [], 'resolved': []}));
return;
}
// Spec path: values + optional propertyName
if (params['values'] is List) {
final List<dynamic> values = params['values'] as List<dynamic>;
final String? propNameRaw = params['propertyName'] as String?;
final String? propName =
(propNameRaw != null && propNameRaw.isNotEmpty) ? camelize(propNameRaw) : null;
final results = <String>[];
for (final v0 in values) {
final input = v0?.toString() ?? '';
String out = input;
try {
dynamic resolved;
if (propName != null) {
resolved = element.renderStyle
.resolveValue(propName, input, baseHref: element.ownerDocument.controller.url);
} else {
// Combined syntax fallback not fully supported; leave as-is.
resolved = null;
}
if (resolved is CSSLengthValue) {
out = resolved.cssText();
} else if (resolved != null) {
out = resolved.toString();
}
} catch (_) {}
results.add(out);
}
sendToFrontend(id, JSONEncodableMap({'results': results}));
return;
}
// Backward-compat path: declarations/text (non-standard)
List<Map<String, String>> pairs = [];
final decls = params['declarations'];
if (decls is List) {
for (final d in decls) {
if (d is Map && d['name'] is String && d['value'] is String) {
pairs.add({'name': d['name'] as String, 'value': d['value'] as String});
}
}
} else {
final text = params['text'];
if (text is String && text.trim().isNotEmpty) {
final parts = _splitDeclarations(text);
for (final decl in parts) {
final int colon = decl.indexOf(':');
if (colon <= 0) continue;
final name = decl.substring(0, colon).trim();
final value = decl.substring(colon + 1).trim();
if (name.isEmpty) continue;
pairs.add({'name': name, 'value': value});
}
}
}
List<Map<String, String>> resolved = [];
for (final p in pairs) {
final origName = p['name']!;
final camel = camelize(origName);
final value = p['value']!;
try {
final v = element.renderStyle.resolveValue(camel, value, baseHref: element.ownerDocument.controller.url);
String text;
if (v is CSSLengthValue) {
text = v.cssText();
} else {
text = v?.toString() ?? value;
}
resolved.add({'name': origName, 'value': text});
} catch (_) {
resolved.add({'name': origName, 'value': value});
}
}
if (DebugFlags.enableDevToolsProtocolLogs) {
try {
devToolsProtocolLogger.finer('[DevTools] CSS.resolveValues node=$frontendNodeId count=${resolved.length}');
} catch (_) {}
}
sendToFrontend(id, JSONEncodableMap({'results': resolved.map((e) => e['value']).toList(), 'resolved': resolved}));
}