Skip to content

Conversation

@silentroach
Copy link
Contributor

querystring.encode unexpected behavior on objects, see #5309

here is specs for encodeURIComponent - http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.4, so object must be casted to string via toString, not via valueOf.

const qs = require('querystring'); const testObject ={toString: () => 'test', valueOf: () => 5 }; console.log('expected', encodeURIComponent(testObject)); // 'test' console.log('actual', qs.escape(testObject)); // 5 

Here is why:

> '' +{toString: () => 'test', valueOf: () => 5} 5 String({toString: () => 'test', valueOf: () => 5}) 'test' 

@vkurchatkinvkurchatkin added the semver-major PRs that contain breaking changes and should be released in the next major version. label Feb 20, 2016
@silentroachsilentroach changed the title using toString for objects on querystring.escape (refs #5309)querystring: using toString for objects on querystring.escapeFeb 20, 2016
@mscdexmscdex added the querystring Issues and PRs related to the built-in querystring module. label Feb 20, 2016
@mscdex
Copy link
Contributor

I just ran some quick benchmarks and it seems that using the String() constructor is currently significantly slower on objects than simply calling its .toString(). It would need further benchmarking, but perhaps putting an extra conditional to avoid that particular case might help things.

@silentroach
Copy link
ContributorAuthor

@mscdex rewritten with typecheck

@jacobp100
Copy link

Not quite.

const x = Symbol('test'); '' + x; // throws String(x) // 'Symbol(test)' 

@silentroach
Copy link
ContributorAuthor

@jacobp100 the same with encodeURIComponent:

> encodeURIComponent(Symbol('test')) TypeError: Cannot convert a Symbol value to a string > '' + Symbol('test') TypeError: Cannot convert a Symbol value to a string 

so the current solution is better than String constructor. Thank you for additional test case :)

@jacobp100
Copy link

You’re correct, good catch. Just checked, per spec, ToString should throw for symbols.

@jasnell
Copy link
Member

LGTM

@Fishrock123
Copy link
Contributor

Are there any cases we can test where this would make a difference even if you are not setting toString()/valueOf()?

@mscdex
Copy link
Contributor

@Fishrock123 What do you mean? There will always be a toString() of some kind, whether you explicitly set one or not (if you don't, Object.prototype.toString() will get used).

@jacobp100
Copy link

Nah, he's right. If toString is not callable, then you need to try valueOf. If that's also not callable, you need to throw an error.

@silentroach
Copy link
ContributorAuthor

Fixed. + more tests

Seems like it is better to use String constructor instead all of these checks. What do you think about last commit, @mscdex?

@jasnell
Copy link
Member

@mscdex @nodejs/ctc ... ping

Copy link
Contributor

Choose a reason for hiding this comment

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

This should be moved to the next line.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

but why? is there any reason to add empty string to str if it is already a string?

please check out tests below, maybe I forgot some cases?

Copy link
Contributor

Choose a reason for hiding this comment

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

No, I meant this as a style nit: moving the str += ''; to the next line instead of on the same line as the else.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

oh. will fix in 5 minutes, thank you

@silentroach
Copy link
ContributorAuthor

@mscdex your variant will fail for this test

// toString is not callable, must throw an error assert.throws(() => qs.escape({toString: 5})); 

and in my version there is no problem with encoding symbols - it will throw as with encodeURIComponent

@mscdex
Copy link
Contributor

LGTM with one minor nit

@mscdex
Copy link
Contributor

@jasnell
Copy link
Member

One failure in CI that looks unrelated.

@jasnell
Copy link
Member

@mscdex ... any further comments on this one?

@jasnell
Copy link
Member

@silentroach ... can you update the commit log to follow our style guidelines here: https://github.com/nodejs/node/blob/master/CONTRIBUTING.md#step-3-commit

@mscdex
Copy link
Contributor

@jasnell Nope, other than commit message needs to be formatted correctly

@silentroach
Copy link
ContributorAuthor

@jasnell, @mscdex fixed. Is it ok now?

This commit fixes an inconsistency in querystring.escape objects handling compared to native encodeURIComponent function. Fixes: #5309 PR-URL: #5341
@jasnell
Copy link
Member

Yep, LGTM

@jasnell
Copy link
Member

New CI, just to be extra careful ;-) https://ci.nodejs.org/job/node-test-pull-request/2244/

jasnell pushed a commit that referenced this pull request Apr 12, 2016
This commit fixes an inconsistency in querystring.escape objects handling compared to native encodeURIComponent function. Fixes: #5309 PR-URL: #5341 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Brian White <[email protected]>
@jasnell
Copy link
Member

Landed in 5dafb43

@jasnelljasnell closed this Apr 12, 2016
@silentroach
Copy link
ContributorAuthor

Thank you :}

jasnell pushed a commit that referenced this pull request Apr 26, 2016
This commit fixes an inconsistency in querystring.escape objects handling compared to native encodeURIComponent function. Fixes: #5309 PR-URL: #5341 Reviewed-By: James M Snell <[email protected]> Reviewed-By: Brian White <[email protected]>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

querystringIssues and PRs related to the built-in querystring module.semver-majorPRs that contain breaking changes and should be released in the next major version.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@silentroach@mscdex@jacobp100@jasnell@Fishrock123@vkurchatkin