Skip to content

Commit b46191e

Browse files
committed
[devtools] allow non-coercible objects in formatConsoleArgumentsToSingleString
1 parent e137890 commit b46191e

File tree

2 files changed

+22
-3
lines changed

2 files changed

+22
-3
lines changed

packages/react-devtools-shared/src/__tests__/utils-test.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ describe('utils', () => {
155155
'Symbol(abc) 123',
156156
);
157157
});
158+
159+
it('should gracefully handle objects with no prototype', () => {
160+
expect(
161+
formatConsoleArgumentsToSingleString('%o', Object.create(null)),
162+
).toEqual('%o [object Object]');
163+
});
158164
});
159165

160166
describe('formatWithStyles', () => {

packages/react-devtools-shared/src/backend/utils/index.js

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,19 @@ export function serializeToString(data: any): string {
167167
);
168168
}
169169

170+
function safeToString(val: any): string {
171+
try {
172+
return String(val);
173+
} catch (err) {
174+
if (typeof val === 'object') {
175+
// An object with no prototype and no `[Symbol.toPrimitive]()`, `toString()`, and `valueOf()` methods would throw.
176+
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion
177+
return '[object Object]';
178+
}
179+
throw err;
180+
}
181+
}
182+
170183
// based on https://github.com/tmpfs/format-util/blob/0e62d430efb0a1c51448709abd3e2406c14d8401/format.js#L1
171184
// based on https://developer.mozilla.org/en-US/docs/Web/API/console#Using_string_substitutions
172185
// Implements s, d, i and f placeholders
@@ -176,7 +189,7 @@ export function formatConsoleArgumentsToSingleString(
176189
): string {
177190
const args = inputArgs.slice();
178191

179-
let formatted: string = String(maybeMessage);
192+
let formatted: string = safeToString(maybeMessage);
180193

181194
// If the first argument is a string, check for substitutions.
182195
if (typeof maybeMessage === 'string') {
@@ -211,14 +224,14 @@ export function formatConsoleArgumentsToSingleString(
211224
// Arguments that remain after formatting.
212225
if (args.length) {
213226
for (let i = 0; i < args.length; i++) {
214-
formatted += ' ' + String(args[i]);
227+
formatted += ' ' + safeToString(args[i]);
215228
}
216229
}
217230

218231
// Update escaped %% values.
219232
formatted = formatted.replace(/%{2,2}/g, '%');
220233

221-
return String(formatted);
234+
return String();
222235
}
223236

224237
export function isSynchronousXHRSupported(): boolean {

0 commit comments

Comments
 (0)