Skip to content

TextBuffer: Pre-built Buffer attrs converted to RGB(0,0,0) by object2attr #270

@KJ7LNW

Description

@KJ7LNW

Description

TextBuffer methods that accept attr parameters check typeof attr === "object" before calling object2attr(). When using ScreenBufferHD, pre-built 10-byte Buffer attrs pass this check and get incorrectly processed by object2attr, which expects {color: {r,g,b}} format. Since Buffer lacks a .color property, object2attr defaults to RGB(0,0,0).

This affects TextBox, EditableTextBox, and any widget using TextBuffer with ScreenBufferHD.

Expected Behavior

const attr = Buffer.allocUnsafe(10);
attr[0] = 255; attr[1] = 255; attr[2] = 255; attr[3] = 255; // white fg
attr[4] = 0; attr[5] = 0; attr[6] = 0; attr[7] = 255;       // black bg
attr[8] = 0; attr[9] = 0;                                    // misc/style

textBuffer.setText("Hello", false, attr);

Text renders as white on black.

Actual Behavior

Text renders as black on black (invisible). The Buffer attr is passed to object2attr which returns RGB(0,0,0) because Buffer has no .color property.

Root Cause

TextBuffer.js uses this pattern in multiple methods:

// Line 272 (setText), 710 (setDefaultAttr), 721 (setVoidAttr), 
// 730 (setAttrAt), 754 (setAttrRegion), etc.
if (typeof attr === "object") { 
    attr = this.object2attr(attr); 
}

Buffer is typeof "object", so it enters this branch. But Buffer attrs are already in the correct 10-byte ScreenBufferHD format and need no conversion.

ScreenBufferHD.object2attr (line 835-901) only handles:

  • Objects with .color string (hex)
  • Objects with .color object ({r,g,b})

Buffer falls through to the else branch → RGB(0,0,0).

Related

This is related to #265 (markup colors) but affects a different code path. Both stem from ScreenBufferHD attr handling not accounting for all input formats.

Suggested Fix

Add Buffer check before object2attr conversion in TextBuffer methods:

// Before
if (typeof attr === "object") { 
    attr = this.object2attr(attr); 
}

// After  
if (attr !== null && typeof attr === "object" && !Buffer.isBuffer(attr)) {
    attr = this.object2attr(attr);
}

Alternatively, add the check in TextBuffer.prototype.object2attr:

TextBuffer.prototype.object2attr = function(attrObject, colorNameToIndex, legacyColor) {
    if (Buffer.isBuffer(attrObject)) {
        return attrObject;  // Already in correct format
    }
    return this.ScreenBuffer.object2attr(attrObject, colorNameToIndex, legacyColor);
};

Environment

  • terminal-kit: 3.1.2
  • Node.js: v22
  • Using ScreenBufferHD Document Model with TextBox widget

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions