Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle errors when serializing logged objects in console plugin #760

Merged
merged 2 commits into from
Oct 17, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 36 additions & 21 deletions plugins/debug-console.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @author jaiperdu
// @name Debug console tab
// @category Debug
// @version 0.1.1
// @version 0.2.0
// @description Add a debug console tab

/* exported setup, changelog --eslint */
Expand All @@ -10,7 +10,7 @@
var changelog = [
{
version: '0.2.0',
changes: ['Use channel new API', 'Handle multiline messages'],
changes: ['Use channel new API', 'Handle multiline messages', 'Handle errors when serializing logged objects'],
},
{
version: '0.1.1',
Expand Down Expand Up @@ -47,56 +47,71 @@ debugTab.create = function () {
};

debugTab.renderLine = function (errorType, args) {
// Convert arguments to an array
args = Array.prototype.slice.call(args);
var text = [];

// Function to safely stringify objects with depth limitation
function safeStringify(obj, depth = 5) {
let cache = [];
return JSON.stringify(obj, function (key, value) {
if (typeof value === 'object' && value !== null) {
// Detect circular references or if the depth exceeds the limit
if (cache.indexOf(value) !== -1 || cache.length > depth) {
return '[Circular]'; // Return a placeholder for circular references
}
// Store object in cache for future reference
cache.push(value);
}
return value;
});
}

args.forEach(function (v) {
// If v is not a string or number, attempt to stringify
if (typeof v !== 'string' && typeof v !== 'number') {
var cache = [];
v = JSON.stringify(v, function (key, value) {
if (typeof value === 'object' && value !== null) {
if (cache.indexOf(value) !== -1) {
// Circular reference found, discard key
return;
}
// Store value in our collection
cache.push(value);
}
return value;
});
cache = null;
try {
v = safeStringify(v);
} catch {
// In case of error, return error message with the object's string representation
v = 'error rendering: ' + String(v);
}
}
// Add the value to the text array
text.push(v);
});

// Join text array into a single string with spaces between values
text = text.join(' ');

// Time
// Time element creation
var time = document.createElement('time');
var d = new Date();
time.textContent = d.toLocaleTimeString();
time.title = d.toLocaleString();
time.dataset.timestamp = d.getTime();

// Type
// Type element creation (for log type)
var type = document.createElement('mark');
type.textContent = errorType;
type.className = errorType;

// Text
// Text element creation (for the log message)
var pre = document.createElement('pre');
pre.textContent = text;

// Check if the last message is visible
// Check if the last message is visible (scroll position)
var debugContainer = document.getElementById('chatdebug');
var isAtBottom = debugContainer.scrollTop >= debugContainer.scrollTopMax;

// Insert Row
// Insert a new row in the debug table
var table = document.querySelector('#chatdebug table');
var row = table.insertRow();
row.insertCell().append(time);
row.insertCell().append(type);
row.insertCell().append(pre);

// Auto-scroll to bottom
// Auto-scroll to the bottom if the user was at the bottom
if (isAtBottom) debugContainer.scrollTo(0, debugContainer.scrollTopMax);
};

Expand Down
Loading