internalSetAttribute method
void
internalSetAttribute(})
Implementation
void internalSetAttribute(String qualifiedName, String value,
{bool invokedByAttributeSetter = false}) {
// Track previous value to avoid redundant DevTools events
final String? oldValue = attributes[qualifiedName];
final bool changed = oldValue != value;
attributes[qualifiedName] = value;
if (qualifiedName == 'class') {
// When called from setAttribute() and a property handler already ran
// (i.e., className setter), skip re-entering className to avoid double
// recalculation and duplicate index updates.
if (!invokedByAttributeSetter) {
// className setter performs necessary style recalculation
className = value;
}
} else {
final isNeedRecalculate = _checkRecalculateStyle([qualifiedName]);
if (DebugFlags.enableCssBatchRecalc) {
ownerDocument.markElementStyleDirty(this, reason: 'batch:attr:$qualifiedName');
} else {
recalculateStyle(rebuildNested: isNeedRecalculate);
}
}
// Maintain attribute presence index for presence selectors like [attr].
// Include class/id/name as well so stylesheet invalidation can target them.
_updateAttrPresenceIndex(qualifiedName, present: true);
// Emit CDP DOM.attributeModified for DevTools if something actually changed
if (changed) {
try {
final cb = ownerDocument.controller.view.devtoolsAttributeModified;
if (cb != null) {
cb(this, qualifiedName, value);
} else {
// Fallback to full tree refresh when incremental hooks are not set
ownerDocument.controller.view.debugDOMTreeChanged?.call();
}
} catch (_) {}
}
// Mark semantics dirty for accessibility-relevant attributes.
if (changed) _markSemanticsDirtyIfNeeded(qualifiedName);
}