main
js 96 lines 2.67 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 */
9
10 // Do not add / import anything to this file.
11 // This function could be used from multiple places, including hook.
12
13 // Skips CSS and object arguments, inlines other in the first argument as a template string
14 export default function formatConsoleArguments(
15 maybeMessage: any,
16 ...inputArgs: $ReadOnlyArray<any>
17 ): $ReadOnlyArray<any> {
18 if (inputArgs.length === 0 || typeof maybeMessage !== 'string') {
19 return [maybeMessage, ...inputArgs];
20 }
21
22 const args = inputArgs.slice();
23
24 let template = '';
25 let argumentsPointer = 0;
26 for (let i = 0; i < maybeMessage.length; ++i) {
27 const currentChar = maybeMessage[i];
28 if (currentChar !== '%') {
29 template += currentChar;
30 continue;
31 }
32
33 const nextChar = maybeMessage[i + 1];
34 ++i;
35
36 // Only keep CSS and objects, inline other arguments
37 switch (nextChar) {
38 case 'c':
39 case 'O':
40 case 'o': {
41 ++argumentsPointer;
42 template += `%${nextChar}`;
43
44 break;
45 }
46 case 'd':
47 case 'i': {
48 if (argumentsPointer >= args.length) {
49 // No argument left for this specifier. Keep it as a literal, like
50 // the browser console does, rather than emitting 'NaN'.
51 template += `%${nextChar}`;
52 break;
53 }
54 const [arg] = args.splice(argumentsPointer, 1);
55 template += parseInt(arg, 10).toString();
56
57 break;
58 }
59 case 'f': {
60 if (argumentsPointer >= args.length) {
61 // No argument left for this specifier. Keep it as a literal, like
62 // the browser console does, rather than emitting 'NaN'.
63 template += `%${nextChar}`;
64 break;
65 }
66 const [arg] = args.splice(argumentsPointer, 1);
67 template += parseFloat(arg).toString();
68
69 break;
70 }
71 case 's': {
72 if (argumentsPointer >= args.length) {
73 // No argument left for this specifier. Keep it as a literal, like
74 // the browser console does, rather than emitting 'undefined'.
75 template += `%${nextChar}`;
76 break;
77 }
78 const [arg] = args.splice(argumentsPointer, 1);
79 template += String(arg);
80
81 break;
82 }
83
84 default:
85 if (nextChar === undefined) {
86 // A trailing '%' with no following character. Keep it as a literal
87 // '%' rather than emitting the string 'undefined'.
88 template += '%';
89 } else {
90 template += `%${nextChar}`;
91 }
92 }
93 }
94
95 return [template, ...args];
96 }