console
console copied to clipboard
Discuss supporting a %j formatting specifier?
In Node.js, a %j formatting specifier runs JSON.stringify() on the related arg. I am unsure what checks it makes other than '[Circular]', but I can take a look.
Example:
$ node
> console.log('JSON: %j', { greeting: 'hello!' })
JSON: {"greeting":"hello!"}
More information can be found in our docs on util.format(format[, ...args]) (Effectively our equivalent of the spec's Format function.)
This seems similar to how a non-interactive console might implement %O.
%OElement is displayed as an expanded JavaScript object; potentially interactive
Given that this is in only one of the five implementations, it seems best for Node.js to remove it, so that people can write interoperable code using %O or %o, instead of code that only works in Node.js using %j.
Possibly. Does anyone think printing JSON as a formatter is useful?
I filed an issue that we should do this in Safari / WebKit a while back. It would not be hard to implement and seems reasonable to me.
It sounds like it's more complicated than just JSON.stringify unfortunately, so until Node manages to put together a spec for their behavior, I would hold off on creating a second divergent implementation.
I don't suggest following us unless we decide it is useful / a good idea.
These are the relative code bits for %j in Node.js:
https://github.com/nodejs/node/blob/7b924f1713006219e20ae7f011405d18b3ac7426/lib/util.js#L95-L102 & https://github.com/nodejs/node/blob/7b924f1713006219e20ae7f011405d18b3ac7426/lib/util.js#L60-L66
Which are really quite simple:
// Within "Format"
1 // f = string to be formatted
2 // i = index of the % character
3 switch (f.charCodeAt(i + 1)) {
4 case 106: // The 'j' character
5 // a = argument index to be inserted
6 if (a >= argLen)
7 break;
8 // lastPos = previous i, + 2 (0 at the start)
9 // str = the formatted string to return
10 if (lastPos < i)
11 str += f.slice(lastPos, i);
12 str += tryStringify(arguments[a++]);
13 lastPos = i = i + 2;
14 continue;
//
15 function tryStringify(arg) {
16 try {
17 return JSON.stringify(arg);
18 } catch (_) {
19 return '[Circular]';
20 }
21 }
My spec language isn't good but that case could be maybe summed up as:
- (3) If the specifier is
j... - (6 - 7) Check that there is a value to be inserted.
- (10 - 11) Get the string up until this formatting specifier.
- (12 ...) Attempt to stringify the next value from args via
tryStringify().- (16 - 17) Try to
JSON.stringify()and return it. - (18 - 19) If there is an error in the previous step, return
'[Circular]'.
- (16 - 17) Try to
- (... 12) Append the stringified next value to string from (10 - 11).
- (13) Prepare for the next formating specifier.
The spec says
%O Element is displayed as an expanded JavaScript object; potentially interactive
Why not just alias %j to %O and spec out non-interactive object? two birds one stone
An important thing to consider in standardization discussions is the concept of the shortest path to interop. If Node simply removes %j, we have achieved interop. Whereas if we try to get the four other consoles to implement it, we don't achieve interop for a much longer time (maybe never, since so far we have interest only from WebKit), and we increase the likelihood of people writing code that only works in some environments in the meantime.
So, that's why aliasing %j to %O is not a super-great option. It would move us from a simple short path to interop that the current spec provides (only one console needs to change), to a very long one (involving changes to all 5 consoles).
An important thing to consider in standardization discussions is the concept of the shortest path to interop. If Node simply removes %j, we have achieved interop.
Removing features from platforms is pretty painful compared to adding features, unfortunately. :/
We can spec out what exists in most common first but I think this discussion is still valuable to be had since we've had it for a long time AFAIK.
Why not just alias %j to %O and spec out non-interactive object? two birds one stone
I think it's more of a question if anyone finds the JSON output useful enough to perhaps have that as an option in browsers to.
I'm personally not sure how useful it is, but idk maybe someone can think of a better use than myself.
Hello guy, newcomer here. I'm not here to argue, and I'm only bringing my POV.
An important thing to consider in standardization discussions is the concept of the shortest path to interop. If Node simply removes %j, we have achieved interop.
@domenic I believe that statement could be improved if you add the idea of pain to it, as in shortest and least painful path to interop.
I'm a big believer in standardization, but IMHO it's hard to achieve if it requires breaking existing user's code or experiences.
Also (and I'm sure it was mentioned before) it's not as simple as to say node is 1/5 implementations, since it's 1/1 server side implementations, and is 1/1 non interactive implementations.
Sure, these are all reasonable points. On the other hand, if one implementation goes out and adds something without a standard in place to support it, it's pretty unlikely that other implementations will follow along, and it's a bad precedent to set. We've done it sometimes (especially in the IE6 days), but in general we prefer a more collaborative working mode.