Uh oh!
There was an error while loading. Please reload this page.
url: use SafeSet to filter known special protocols - #24703
Conversation
devsnek
commented
Nov 28, 2018
can they just be changed to maps? |
mikesamuel
commented
Nov 28, 2018
@devsnek, They could be changed to Sets. There's no need to lookup a value. Would you prefer that? |
devsnek
commented
Nov 28, 2018
@mikesamuel i would definitely prefer using sets |
This seems to make the code harder to understand. We usually just go with |
I think the reason to no use null prototype objects was lookup performance. I don't know if it's still faster. |
mikesamuel
commented
Nov 28, 2018
Reworking to use sets. @lpinca, Re performance, https://github.com/anvaka/set-vs-object#conclusion is one microbenchmark. |
mikesamuel
commented
Nov 28, 2018
I changed it to use SafeSet (thanks @joyeecheung), squashed the commits, and changed the PR description to reflect that. |
mikesamuel
commented
Nov 28, 2018
I think my squash broke Travis's first commit message check :( |
@mikesamuel Can you update the commit message to something that describes the current approach? (e.g. something like |
Avoids a maintenance hazard when reviewers assume that
`hostlessProtocol` and `slashedProtocol` are disjoint.
The following may be counter-intuitive:
```js
// These objects seem to have no keys in common
const hostlessProtocol = { 'javascript': true };
const slashedProtocol = { 'http': true };
// A reasonable reviewer may assumes bothTrue is never truthy
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
// But
console.log(Boolean(bothTrue('constructor'))); // true
```
This change uses SafeSet instead of plain-old objects.
----
Rejected alternative:
We could have used object with a `null` prototype as lookup tables
so that `lowerProto` is never treated as a key into `Object.prototype`.
```js
const hostlessProtocol = { __proto__: null, 'javascript': true };
const slashedProtocol = { __proto__: null, 'http': true };
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
console.log(Boolean(bothTrue('constructor'))); // false
```mikesamuel
commented
Nov 29, 2018
@joyeecheung, done |
joyeecheung
commented
Nov 29, 2018
joyeecheung
commented
Nov 30, 2018
Trott
commented
Dec 1, 2018
Trott
commented
Dec 1, 2018
(Benchmark tradeoffs look perfectly acceptable to me, but second opinion welcome.) |
Trott
commented
Dec 1, 2018
Resume Build CI: https://ci.nodejs.org/job/node-test-pull-request/19114/ |
Avoids a maintenance hazard when reviewers assume that
`hostlessProtocol` and `slashedProtocol` are disjoint.
The following may be counter-intuitive:
```js
// These objects seem to have no keys in common
const hostlessProtocol = { 'javascript': true };
const slashedProtocol = { 'http': true };
// A reasonable reviewer may assumes bothTrue is never truthy
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
// But
console.log(Boolean(bothTrue('constructor'))); // true
```
This change uses SafeSet instead of plain-old objects.
----
Rejected alternative:
We could have used object with a `null` prototype as lookup tables
so that `lowerProto` is never treated as a key into `Object.prototype`.
```js
const hostlessProtocol = { __proto__: null, 'javascript': true };
const slashedProtocol = { __proto__: null, 'http': true };
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
console.log(Boolean(bothTrue('constructor'))); // false
```
PR-URL: nodejs#24703
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>Trott
commented
Dec 1, 2018
Landed in 0d23118. Thanks for the contribution! 🎉 |
Post-mortem: benchmark results. The most significant ones (with Benchmark resultsSignificant impact |
Avoids a maintenance hazard when reviewers assume that
`hostlessProtocol` and `slashedProtocol` are disjoint.
The following may be counter-intuitive:
```js
// These objects seem to have no keys in common
const hostlessProtocol = { 'javascript': true };
const slashedProtocol = { 'http': true };
// A reasonable reviewer may assumes bothTrue is never truthy
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
// But
console.log(Boolean(bothTrue('constructor'))); // true
```
This change uses SafeSet instead of plain-old objects.
----
Rejected alternative:
We could have used object with a `null` prototype as lookup tables
so that `lowerProto` is never treated as a key into `Object.prototype`.
```js
const hostlessProtocol = { __proto__: null, 'javascript': true };
const slashedProtocol = { __proto__: null, 'http': true };
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
console.log(Boolean(bothTrue('constructor'))); // false
```
PR-URL: #24703
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>Avoids a maintenance hazard when reviewers assume that
`hostlessProtocol` and `slashedProtocol` are disjoint.
The following may be counter-intuitive:
```js
// These objects seem to have no keys in common
const hostlessProtocol = { 'javascript': true };
const slashedProtocol = { 'http': true };
// A reasonable reviewer may assumes bothTrue is never truthy
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
// But
console.log(Boolean(bothTrue('constructor'))); // true
```
This change uses SafeSet instead of plain-old objects.
----
Rejected alternative:
We could have used object with a `null` prototype as lookup tables
so that `lowerProto` is never treated as a key into `Object.prototype`.
```js
const hostlessProtocol = { __proto__: null, 'javascript': true };
const slashedProtocol = { __proto__: null, 'http': true };
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
console.log(Boolean(bothTrue('constructor'))); // false
```
PR-URL: nodejs#24703
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>Avoids a maintenance hazard when reviewers assume that
`hostlessProtocol` and `slashedProtocol` are disjoint.
The following may be counter-intuitive:
```js
// These objects seem to have no keys in common
const hostlessProtocol = { 'javascript': true };
const slashedProtocol = { 'http': true };
// A reasonable reviewer may assumes bothTrue is never truthy
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
// But
console.log(Boolean(bothTrue('constructor'))); // true
```
This change uses SafeSet instead of plain-old objects.
----
Rejected alternative:
We could have used object with a `null` prototype as lookup tables
so that `lowerProto` is never treated as a key into `Object.prototype`.
```js
const hostlessProtocol = { __proto__: null, 'javascript': true };
const slashedProtocol = { __proto__: null, 'http': true };
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
console.log(Boolean(bothTrue('constructor'))); // false
```
PR-URL: #24703
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>Avoids a maintenance hazard when reviewers assume that
`hostlessProtocol` and `slashedProtocol` are disjoint.
The following may be counter-intuitive:
```js
// These objects seem to have no keys in common
const hostlessProtocol = { 'javascript': true };
const slashedProtocol = { 'http': true };
// A reasonable reviewer may assumes bothTrue is never truthy
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
// But
console.log(Boolean(bothTrue('constructor'))); // true
```
This change uses SafeSet instead of plain-old objects.
----
Rejected alternative:
We could have used object with a `null` prototype as lookup tables
so that `lowerProto` is never treated as a key into `Object.prototype`.
```js
const hostlessProtocol = { __proto__: null, 'javascript': true };
const slashedProtocol = { __proto__: null, 'http': true };
function bothTrue(lowerProto) {
return hostlessProtocol[lowerProto] && slashedProtocol[lowerProto];
}
console.log(Boolean(bothTrue('constructor'))); // false
```
PR-URL: #24703
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Checklist
make -j4 test(UNIX), orvcbuild test(Windows) passesAvoids a maintenance hazard when reviewers assume that
hostlessProtocolandslashedProtocolare disjoint.The following may be counter-intuitive:
This change uses SafeSet instead of plain-old objects.
Rejected alternative:
We could have used object with a
nullprototype as lookup tablesso that
lowerProtois never treated as a key intoObject.prototype.