-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Invalid Web IDL: Sanitizer.config attribute type cannot be dictionary #107
Comments
Right. This was the reason for originally doing it as methods. However, we've repeatedly been told that this is bad API ergonomics, and that developers would expect to use attribute syntax ( At this point, I'm rather confused whether I'm using the syntax wrong -- that is, we can get our attribute syntax for Can I return a dictionary copy and get accessor syntax in WebIDL? How? |
a couple of non-fully-formed thoughts:
Paging @LeaVerou since this relates to the feedback she conveyed on the spec. |
Related TAG design principle: Attributes should behave like data properties which says "Ensure that obj.attribute === obj.attribute is always true. Don’t create a new value each time the getter is called". |
Does |
I don't think WebIDL has an opinion on that, since WebIDL is convinced this doen't exist. The 'naive' implementation (at least in Chromium) would indeed create a new value each time, but that could also be implemented differently by memo-izing the value once and then returning the same value each time |
re memoizing, whatwg/webidl#981 (comment) alludes to a would-be |
Oh, right. If we were to return the same dictionary, then that dictionary could be modified by a first caller, and the second caller would then see the same, modified dictionary. That's just a bad idea. So after a second thought, I'm going to say that |
I think it's fine to create a new object when the configuration actually changes, the spirit of the TAG guidance is that you should return the same object if the value hasn't changed. |
Well, Sanitizers don't change configurations anyways; configuration is a constructor thing. The point is that JavaScript doesn't have constant objects. I.e.: const s = new Sanitizer( ...bla bla...);
let c1 = s.config():
let c2 = s.config();
c1.hello = "world"; // Modify the dictionary we received.
"world" == c2.hello; // true., c1 & c2 are the same object, and thus c2 "sees" the modification of c1 That could be very extra suprising if some part of the code modifies the return value - for example, to build a new configuration - and then another part of the code tries to examine it. Example: const main_sanitizer = new Sanitizer(...); // A carefully configured sanitizer for our application.
// Somewhere in libary we want to be slightly more strict.
// Intent: Build a new sanitizer based on main_sanitizer.
// Reality: Have modified main_sanitizer's config.
let config = main_sanitizer.config;
config.blockElements.push("table", "td", "th", "tr"); // We hate tables.
const my_sanitizer = new Sanitizer(config);
// Somewhere else entirely:
let my_config = main_sanitizer.config. // Oops. Now we're really seeing my_sanitizer's config. Which is a pity, because the code above looks nice to me. That's how I'd want to use this. |
JavaScript has frozen objects, but I don't think that resolves the problem here because freezing an array won't stop someone calling push etc on it. |
@Sora2455 Yes, it will. You can try it out yourself:
|
Thanks for bringin up 'freeze'. Frozen is apparently shallow, so Lea's example will no longer work if it's an array as a dictionary value. But I guess we could freeze recursively. Is there precedent for relying on 'frozen' return values in JS APIs? |
I can't think of anything for objects, but there's a lot of precedent with lists of values. Here's the long ongoing related discussion. |
I'd strongly recommend using a method. There's no precedent for deeply frozen objects in JavaScript or web APIs (which is why the pattern is prohibited by Web IDL). |
The other usual alternative is flattening the properties, e.g. instead of using |
Hmm. So far, I'm not seeing a viable solution, or even consensus on a general direction. I'll revert PR #104 and close out this issue. Thanks all for the discussion, and please do feel free to re-open this if there's additional info or a good proposal on how to solve this. |
when reverting #104, I would suggest again that |
Reverted. Also renamed the methods to |
Coming here late, but +1 for using a function, I think that is the least surprising option. |
Refs: - github.com/WICG/sanitizer-api/issues/92 - github.com/WICG/sanitizer-api/issues/107 - WICG/sanitizer-api#108 Bug: 1213893 Change-Id: Ibbc89e2678107f835517af9743e5a1eeca3911d2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3015576 Reviewed-by: Yifan Luo <lyf@chromium.org> Commit-Queue: Daniel Vogelheim <vogelheim@chromium.org> Cr-Commit-Position: refs/heads/master@{#900407}
Refs: - github.com/WICG/sanitizer-api/issues/92 - github.com/WICG/sanitizer-api/issues/107 - WICG/sanitizer-api#108 Bug: 1213893 Change-Id: Ibbc89e2678107f835517af9743e5a1eeca3911d2 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3015576 Reviewed-by: Yifan Luo <lyf@chromium.org> Commit-Queue: Daniel Vogelheim <vogelheim@chromium.org> Cr-Commit-Position: refs/heads/master@{#900407} NOKEYCHECK=True GitOrigin-RevId: 66474c9aa1cf094fcbcf75ebea5d11255b17bd81
A recent commit switched config to be an attribute getter. However, that is forbidden in Web IDL: "the type of the attribute [...] must not be a nullable or non-nullable version of [...] a dictionary type".
(I suspect one reason for the rule is that devs expect attributes to return the same object, as in
obj.config === obj.config
, and that cannot easily be enforced when a readonly attribute returns a dictionary)The text was updated successfully, but these errors were encountered: