lib: brand-check Navigator getters to throw ERR_INVALID_THIS#63601
lib: brand-check Navigator getters to throw ERR_INVALID_THIS#636013zrv wants to merge 5 commits into
Conversation
Fixes: nodejs#63513 Signed-off-by: Mohamed Sayed <k@3zrv.com>
|
Review requested:
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #63601 +/- ##
=========================================
Coverage 90.32% 90.32%
=========================================
Files 730 732 +2
Lines 234669 236681 +2012
Branches 43946 44577 +631
=========================================
+ Hits 211967 213792 +1825
- Misses 14417 14595 +178
- Partials 8285 8294 +9
🚀 New features to boost your workflow:
|
|
I don't think adding a check is worth it, I think the current behavior is fine actually, the spec requires a TypeError, we're throwing a TypeError (except for |
LiviaMedeiros
left a comment
There was a problem hiding this comment.
+1 on explicit ERR_INVALID_THIS over implicit private field access. Errors from private fields are misleading and not future-proof: it's too easy to break 'implicit throw' unintentionally (in fact, Navigator.prototype.language was initially introduced using private field, too).
It’s only true if that’s not covered by tests (which I would have expected WPT to cover, but I guess not, or at least not the subset we’re running) |
There was a problem hiding this comment.
In undici we are lenient with errors too with the expectation that a reviewer would notice if a change similar to the one that changed .language was made.
Since it's not reasonable here, I think the change is fine. Regarding the WPTs, brand checks should be implemented the same across globals in most platforms so the assumption is that if you have it implemented properly in one spec, it's also implemented correctly in the thousands of over browser globals.
Signed-off-by: Mohamed Sayed <k@3zrv.com>
|
Thanks for the reviews, the test now covers all getters via I'm more into keeping the explicit |
|
Here's what the error looks like on the browser side:
FWIW I'm in the Chromium camp, I think minimal effort is the appropriate amount of support we should spend on "passing an invalid |
|
are we still good to merge this? missing anything? @aduh95 @KhafraDev @LiviaMedeiros |
Signed-off-by: Mohamed Sayed <k@3zrv.com>
| // `language` does not read a private field, so brand-check explicitly | ||
| // to keep parity with the other getters when called on a non-Navigator | ||
| // receiver (e.g. `Navigator.prototype.language`). | ||
| if (!(#languages in this)) throw new ERR_INVALID_THIS('Navigator'); |
There was a problem hiding this comment.
We shouldn't do this. We explicitly avoided doing this because of performance in the past. We went through deprecation cycles multiple times because of this.
There was a problem hiding this comment.
Wouldn't not throwing here go against the specs?
There was a problem hiding this comment.
Accessing this.#attribute already throws
There was a problem hiding this comment.
This particular getter doesn't use private field anymore so currently it doesn't throw at all.
There was a problem hiding this comment.
@anonrig you can try it yourself: node -p Navigator.prototype.language exits with code 0 (while accessing the other properties e.g. node -p Navigator.prototype.languages has the expected TypeError)
There was a problem hiding this comment.
| if (!(#languages in this)) throw new ERR_INVALID_THIS('Navigator'); | |
| this.#languages; // eslint-disable-line no-unused-expressions |
LiviaMedeiros
left a comment
There was a problem hiding this comment.
LGTM. I'd still prefer if all errors were aligned, but as long as this approach doesn't preclude potential follow-up and is easier to reach consensus for, looks great.
Signed-off-by: Mohamed Sayed <k@3zrv.com>
Signed-off-by: Mohamed Sayed <k@3zrv.com>
Fixes: #63513
Add an explicit
#field in thisbrand check to each getter so a proper ERR_INVALID_THIS is thrown, matching browser behavior. This also fixeslanguage, which previously did not error at all on the prototype because it did not touch a private field.