url: use SafeSet to filter known special protocols#24703
url: use SafeSet to filter known special protocols#24703mikesamuel wants to merge 1 commit intonodejs:masterfrom
Conversation
|
can they just be changed to maps? |
|
@devsnek, They could be changed to Sets. There's no need to lookup a value. Would you prefer that? |
|
@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. |
|
Reworking to use sets. @lpinca, Re performance, https://github.com/anvaka/set-vs-object#conclusion is one microbenchmark. |
|
I changed it to use SafeSet (thanks @joyeecheung), squashed the commits, and changed the PR description to reflect that. |
|
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
```
|
@joyeecheung, done |
|
(Benchmark tradeoffs look perfectly acceptable to me, but second opinion welcome.) |
|
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>
|
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.