Skip to content

util: treat format arguments equally, add format string detection#23162

Closed
silverwind wants to merge 2 commits into
nodejs:masterfrom
silverwind:console-first-arg
Closed

util: treat format arguments equally, add format string detection#23162
silverwind wants to merge 2 commits into
nodejs:masterfrom
silverwind:console-first-arg

Conversation

@silverwind
Copy link
Copy Markdown
Contributor

@silverwind silverwind commented Sep 29, 2018

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • documentation is changed or added
  • commit message follows commit guidelines

Previously, a string first argument was treated as a format string even if it did not actually contain format specifiers. Now it will only be treated as a format string when it contains format specifiers which is in line with the Console Standard.

Additionally, this eliminates output inconsistencies in the non-format-string case where elements were output differently depending on their position in the argument list.

@nodejs-github-bot
Copy link
Copy Markdown
Collaborator

@nodejs-github-bot nodejs-github-bot added the util Issues and PRs related to the built-in util module. label Sep 29, 2018
@cjihrig cjihrig added the semver-major PRs that contain breaking changes and should be released in the next major version. label Sep 29, 2018
@vsemozhetbyt
Copy link
Copy Markdown
Contributor

vsemozhetbyt commented Sep 29, 2018

Should we update this note with something like this:

If the first argument is not a string then... ->
If the first argument is not a string or it does not contain any format specifiers then...?

@silverwind
Copy link
Copy Markdown
Contributor Author

silverwind commented Sep 29, 2018

@vsemozhetbyt thanks, updated docs quite a bit to be more accurate and also renamed placeholders to format specifiers.
@cjihrig you sure about this semver-major label? All our current tests pass and I think the only real change is the escaping of ' in strings.

@cjihrig
Copy link
Copy Markdown
Contributor

cjihrig commented Sep 29, 2018

I think it's an edge case, but still needs to be treated as semver major just to be safe. Our own test suite has not been a great measuring stick in the past for these things. If others feel strongly that it's not semver major, feel free to remove the label.

@silverwind
Copy link
Copy Markdown
Contributor Author

On second thought, I'm fine with keeping it major.

@silverwind
Copy link
Copy Markdown
Contributor Author

@vsemozhetbyt
Copy link
Copy Markdown
Contributor

From citgm, something changes independently of the first string parameter content:

 !!! Invalid input or expected stdout
 ---INPUT---
 {
     var o = {
         n: NaN
     };
     console.log(o.n == o.n, o.n === o.n, o.n != o.n, o.n !== o.n, typeof o.n);
 }
 ---EXPECTED STDOUT---
 false false true true 'number'
 ---ACTUAL STDOUT---
 false false true true number

@silverwind
Copy link
Copy Markdown
Contributor Author

silverwind commented Sep 30, 2018

Another one:

 ---INPUT---
 {
     var a = "32";
     !function() {
         var b = a + 1;
         !function(a) {
             console.log(a++, b);
         }(0);
     }();
 }
 ---EXPECTED STDOUT---
 0 '321'
 ---ACTUAL STDOUT---
 0 321

That may be because I use inspect instead of String on numbers, which I recall was necessary to get some of our own tests to pass. Will check.

@silverwind
Copy link
Copy Markdown
Contributor Author

Looks like the old implementation did use inspect on all arguments if the first argument is not a string. When first was a string, String was used on types other than objects and symbols.

Guess I have to reimplement this inconsistency for the sake of compatibilty.

@silverwind silverwind changed the title util: treat format arguments equally util: only treat format strings as such when they contain format specifiers Sep 30, 2018
@silverwind
Copy link
Copy Markdown
Contributor Author

silverwind commented Sep 30, 2018

I cannot fix above errors without re-introducing the issue that this was meant to fix.

Our current implementation of util.format outputs types other then object and symbol using String() when the first argument is a string. When the first argument is not a string, inspect is used on all arguments, which results in inconsistent output like this:

screenshot 2018-09-30 at 10 43 10

My implementation removes this inconsistency by always formatting arguments the same, regardless of their position in the argument list:

screenshot 2018-09-30 at 10 43 44

I think this is the best compromise we can do and it's worth the breaking change in the console output.

A even better way could be to run all types through util.inspect, but that would mean we'd have to remove string quotes and all strings in console output would become colored, which would probably break a ton of things.

@silverwind silverwind changed the title util: only treat format strings as such when they contain format specifiers util: treat format arguments equally, add format string detection Sep 30, 2018
@silverwind silverwind force-pushed the console-first-arg branch 2 times, most recently from 4ca4637 to 5e6c70d Compare October 1, 2018 20:18
@silverwind
Copy link
Copy Markdown
Contributor Author

Added a second changelog entry to clarify the details on the formatting change. If we disregard color, the only real difference in console/format output is on the arguments [nonstring, string] where previously, string would have been logged with quotes which are now gone.

@silverwind silverwind added the console Issues and PRs related to the console subsystem. label Oct 1, 2018
@addaleax
Copy link
Copy Markdown
Member

addaleax commented Oct 4, 2018

Looks like this needs a rebase? :/

Comment thread doc/api/util.md Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe move this to the next paragraph, that explains what happens to those.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah makes sense, I moved it after the code block.

Two changes here which bring us closer to the console standard:

- Arguments to `util.format` are no longer formatted differently
  depending on their order, with format strings being an exception.
- Format specifier formatting is now only triggered if the string
  actually contains a format string.

Under the hood, we now use a single shared function to format the given
arguments which will make the code easier to read and modify.

PR-URL: nodejs#23162
Fixes: nodejs#23137
@silverwind
Copy link
Copy Markdown
Contributor Author

silverwind commented Oct 16, 2018

Rebased and addressed @refack's comment on docs. Also, new commit message.

@silverwind
Copy link
Copy Markdown
Contributor Author

Thanks, Landed in c1b9be5.

@silverwind silverwind closed this Oct 17, 2018
@BethGriggs BethGriggs mentioned this pull request Mar 26, 2019
@BridgeAR BridgeAR mentioned this pull request Sep 17, 2019
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

console Issues and PRs related to the console subsystem. semver-major PRs that contain breaking changes and should be released in the next major version. util Issues and PRs related to the built-in util module.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants