diff --git a/packages/bruno-app/src/components/Devtools/Console/index.js b/packages/bruno-app/src/components/Devtools/Console/index.js
index 0e1de515a..b4c2aa574 100644
--- a/packages/bruno-app/src/components/Devtools/Console/index.js
+++ b/packages/bruno-app/src/components/Devtools/Console/index.js
@@ -67,14 +67,55 @@ const LogTimestamp = ({ timestamp }) => {
const LogMessage = ({ message, args }) => {
const { displayedTheme } = useTheme();
+ // Helper function to transform Bruno special types back to readable format
+ const transformBrunoTypes = obj => {
+ if (typeof obj !== 'object' || obj === null) {
+ return obj;
+ }
+
+ // Handle Bruno special types
+ if (obj.__brunoType) {
+ switch (obj.__brunoType) {
+ case 'Set':
+ return {
+ '[[Set]]': obj.__brunoValue,
+ 'size': obj.__brunoValue.length,
+ };
+ case 'Map':
+ return {
+ '[[Map]]': obj.__brunoValue,
+ 'size': obj.__brunoValue.length,
+ };
+ case 'Function':
+ return `[Function: ${obj.__brunoValue.split('\n')[0].substring(0, 50)}...]`;
+ case 'undefined':
+ return 'undefined';
+ default:
+ return obj;
+ }
+ }
+
+ // Recursively transform nested objects
+ if (Array.isArray(obj)) {
+ return obj.map(transformBrunoTypes);
+ }
+
+ const transformed = {};
+ for (const [key, value] of Object.entries(obj)) {
+ transformed[key] = transformBrunoTypes(value);
+ }
+ return transformed;
+ };
+
const formatMessage = (msg, originalArgs) => {
if (originalArgs && originalArgs.length > 0) {
return originalArgs.map((arg, index) => {
if (typeof arg === 'object' && arg !== null) {
+ const transformedArg = transformBrunoTypes(arg);
return (
{
+ if (arg instanceof Set) {
+ return {
+ __brunoType: 'Set',
+ __brunoValue: Array.from(arg),
+ size: arg.size
+ };
+ }
+ if (arg instanceof Map) {
+ return {
+ __brunoType: 'Map',
+ __brunoValue: Array.from(arg.entries()),
+ size: arg.size
+ };
+ }
+ return arg;
+ });
+ return originalConsoleLog.apply(this, processedArgs);
+ };
+
+ // Also override other console methods
+ ['debug', 'info', 'warn', 'error'].forEach(method => {
+ const originalMethod = console[method];
+ console[method] = function(...args) {
+ const processedArgs = args.map(arg => {
+ if (arg instanceof Set) {
+ return {
+ __brunoType: 'Set',
+ __brunoValue: Array.from(arg),
+ size: arg.size
+ };
+ }
+ if (arg instanceof Map) {
+ return {
+ __brunoType: 'Map',
+ __brunoValue: Array.from(arg.entries()),
+ size: arg.size
+ };
+ }
+ return arg;
+ });
+ return originalMethod.apply(this, processedArgs);
+ };
+ });
+
await bru.sleep(0);
try {
${externalScript}
diff --git a/packages/bruno-js/src/sandbox/quickjs/shims/console.js b/packages/bruno-js/src/sandbox/quickjs/shims/console.js
index 984422893..8a7101347 100644
--- a/packages/bruno-js/src/sandbox/quickjs/shims/console.js
+++ b/packages/bruno-js/src/sandbox/quickjs/shims/console.js
@@ -1,30 +1,151 @@
const addConsoleShimToContext = (vm, console) => {
if (!console) return;
+ // Helper function to convert QuickJS values to native values with Set/Map support
+ const dumpWithSetMapSupport = arg => {
+ try {
+ // First try to dump normally
+ const dumped = vm.dump(arg);
+
+ // Check if it's a Set by trying to access Set-specific properties
+ if (vm.typeof(arg) === 'object' && arg !== vm.null && arg !== vm.undefined) {
+ // Try to get the constructor name
+ const constructorProp = vm.getProp(arg, 'constructor');
+ if (constructorProp) {
+ const constructorNameProp = vm.getProp(constructorProp, 'name');
+ if (constructorNameProp) {
+ const constructorName = vm.dump(constructorNameProp);
+ constructorNameProp.dispose();
+
+ if (constructorName === 'Set') {
+ // It's a Set, convert to our special format
+ const sizeProp = vm.getProp(arg, 'size');
+ const size = sizeProp ? vm.dump(sizeProp) : 0;
+ sizeProp?.dispose();
+
+ // Get values by calling values() method
+ const valuesFn = vm.getProp(arg, 'values');
+ if (valuesFn) {
+ const valuesIterator = vm.callFunction(valuesFn, arg);
+ const values = [];
+
+ // Try to extract values (this is a simplified approach)
+ try {
+ // For now, we'll use a different approach - convert via Array.from
+ const arrayFromFn = vm.getProp(vm.global, 'Array');
+ if (arrayFromFn) {
+ const fromFn = vm.getProp(arrayFromFn, 'from');
+ if (fromFn) {
+ const arrayResult = vm.callFunction(fromFn, arrayFromFn, arg);
+ const arrayValues = vm.dump(arrayResult);
+ arrayResult.dispose();
+ fromFn.dispose();
+
+ constructorProp.dispose();
+ valuesFn.dispose();
+ valuesIterator?.dispose();
+ arrayFromFn.dispose();
+
+ return {
+ __brunoType: 'Set',
+ __brunoValue: arrayValues,
+ size: size,
+ };
+ }
+ fromFn?.dispose();
+ }
+ arrayFromFn?.dispose();
+ } catch (e) {
+ // Fallback to empty array
+ }
+
+ valuesFn.dispose();
+ valuesIterator?.dispose();
+
+ return {
+ __brunoType: 'Set',
+ __brunoValue: values,
+ size: size,
+ };
+ }
+ } else if (constructorName === 'Map') {
+ // It's a Map, convert to our special format
+ const sizeProp = vm.getProp(arg, 'size');
+ const size = sizeProp ? vm.dump(sizeProp) : 0;
+ sizeProp?.dispose();
+
+ // Try to convert via Array.from
+ try {
+ const arrayFromFn = vm.getProp(vm.global, 'Array');
+ if (arrayFromFn) {
+ const fromFn = vm.getProp(arrayFromFn, 'from');
+ if (fromFn) {
+ const arrayResult = vm.callFunction(fromFn, arrayFromFn, arg);
+ const arrayValues = vm.dump(arrayResult);
+ arrayResult.dispose();
+ fromFn.dispose();
+ arrayFromFn.dispose();
+
+ constructorProp.dispose();
+
+ return {
+ __brunoType: 'Map',
+ __brunoValue: arrayValues,
+ size: size,
+ };
+ }
+ fromFn?.dispose();
+ }
+ arrayFromFn?.dispose();
+ } catch (e) {
+ // Fallback
+ }
+
+ constructorProp.dispose();
+
+ return {
+ __brunoType: 'Map',
+ __brunoValue: [],
+ size: size,
+ };
+ }
+ }
+ constructorNameProp?.dispose();
+ }
+ constructorProp?.dispose();
+ }
+
+ return dumped;
+ } catch (e) {
+ // Fallback to normal dump
+ return vm.dump(arg);
+ }
+ };
+
const consoleHandle = vm.newObject();
const logHandle = vm.newFunction('log', (...args) => {
- const nativeArgs = args.map(vm.dump);
+ const nativeArgs = args.map(dumpWithSetMapSupport);
console?.log?.(...nativeArgs);
});
const debugHandle = vm.newFunction('debug', (...args) => {
- const nativeArgs = args.map(vm.dump);
+ const nativeArgs = args.map(dumpWithSetMapSupport);
console?.debug?.(...nativeArgs);
});
const infoHandle = vm.newFunction('info', (...args) => {
- const nativeArgs = args.map(vm.dump);
+ const nativeArgs = args.map(dumpWithSetMapSupport);
console?.info?.(...nativeArgs);
});
const warnHandle = vm.newFunction('warn', (...args) => {
- const nativeArgs = args.map(vm.dump);
+ const nativeArgs = args.map(dumpWithSetMapSupport);
console?.warn?.(...nativeArgs);
});
const errorHandle = vm.newFunction('error', (...args) => {
- const nativeArgs = args.map(vm.dump);
+ const nativeArgs = args.map(dumpWithSetMapSupport);
console?.error?.(...nativeArgs);
});