-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Custom elements created with "new" are not :defined #1297
Comments
Tentatively I think the fix is that HTMLElement() step 4 should get a new substep that sets the element's state to "custom". Step 4.1 definitely does not imply "create an element". It's meant to be the lower-level Web IDL-ish operation for creating an instance of a given interface. (Via magic, without ever calling its constructor.) |
This would also mean we could remove https://dom.spec.whatwg.org/#concept-create-element step 6.1.11 since it would happen automatically in 6.1.2. |
This has the nice side effect that |
I don't think |
@rniwa I don't think we have a choice. Given |
Oh I see, that's a good point. |
As discussed in #1297, the spec previously did not correctly set custom element state to "custom" for the case of new CustomElement(). The correct place to do this is in the HTMLElement constructor (invoked by the super() call), since that is the last place user agent code is invoked, and so our last chance to change the state. In practice, this affects the behavior of the :defined pseudo-class. Fixes #1297. Also fixes a typo in the same algorithms, where the variable names "element" and "interface" were accidentally both used.
Yay! |
As discussed in #1297, the spec previously did not correctly set custom element state to "custom" for the case of new CustomElement(). The correct place to do this is in the HTMLElement constructor (invoked by the super() call), since that is the last place user agent code is invoked, and so our last chance to change the state. In practice, this affects the behavior of the :defined pseudo-class. Fixes #1297. Also fixes a typo in the same algorithms, where the variable names "element" and "interface" were accidentally both used.
Ah, I think there may be a wrinkle with this we failed to anticipate. First, I think it's 100% right to set "custom" in the HTMLElement constructor. It's the universal, consistent point to do that. However this has the effect that attributeChangedCallbacks and so on start happening at that point. This means that if the constructor sets an attribute, two attributeChanged callbacks will be enqueued—one by the CEReactions tickled by the attribute setting, and a second as the upgrade steps are finishing. The same goes for connectedCallback. I think upgrade should queue those notifications before running the constructor. That way the author gets a consistent sequence of notifications. The side effect of attribute setting in the constructor causing reactions will continue to exist though. I don't see any way out of that, given we can't hook when the author's constructor or Reflect.construct call returns without changing ES6 semantics. |
So to make sure I understand, the proposal would be to move the attributeChanged and connected calls in steps 8 and 9 of https://html.spec.whatwg.org/multipage/scripting.html#concept-upgrade-an-element to before step 3? That seems to work OK:
I briefly considered the idea of saving the current set of attributes before step 3, but still firing in step 8. But then you get B then A in the last example, which is bad. I think this is the best we can do if people do things they're explicitly advised not to do (viz. adding attributes, or in general touching the DOM in a way that would trigger CEReactions, inside constructors). |
As pointed out in #1297 (comment), the setup introduced in #1309 allows custom element reactions to happen during custom element constructors. This is unavoidable, but the spec did not account for its consequences, leading to cases where a custom element reaction would be called twice for the same attribute (or the same element being connected). By moving these steps to the top of the algorithm, we ensure that reactions are only enqueued for the state of the world before the constructor runs, and that any reactions caused by actions inside the constructor are then taken care of by the usual mechanisms. Closes #1297 again.
Yes, the effects you describe are correct! I think the situation for connected is similar. |
As pointed out in #1297 (comment), the setup introduced in #1309 allows custom element reactions to happen during custom element constructors. This is unavoidable, but the spec did not account for its consequences, leading to cases where a custom element reaction would be called twice for the same attribute (or the same element being connected). By moving these steps to the top of the algorithm, we ensure that reactions are only enqueued for the state of the world before the constructor runs, and that any reactions caused by actions inside the constructor are then taken care of by the usual mechanisms. Closes #1297 again.
whatwg/html#1297 led to a series of changes which cause the custom element state to be set to "defined" by the HTMLElement constructor. This invalidates the super()-then-throw example. We instead replace it with an example that fails to call super(). Fixes whatwg/html#1396.
whatwg/html#1297 led to a series of changes which cause the custom element state to be set to "defined" by the HTMLElement constructor. This invalidates the super()-then-throw example. We instead replace it with an example that fails to call super(). Fixes whatwg/html#1396.
Compare the steps for creating a custom element is created with 'new' using the HTMLElement constructor, versus creating one with create element or upgrading one.
Both create element and upgrade set custom element state; the HTML constructor doesn't. This means custom elements created with
new
will not match:defined
.On the other hand, if you were to tell me that the HTMLElement constructor step 4.1 implies doing create element, I would tell you I think that implies running the author's constructor a second time. I assume step 4.1 does not mean create element specifically.
The text was updated successfully, but these errors were encountered: