Skip to content

Web component props are set before constructor call #1735

@pedro00dk

Description

@pedro00dk

Describe the bug

Not sure this is a bug or expected behavior, but I did not find any documentation about it.

When rendering a web component in solid, the web component properties are set before its constructor call.
If the web component defines getter/setter functions with the same name as the props, these are somehow overwritten when the props are set during render and cause the setter not to work.

Your Example Website or App

https://playground.solidjs.com/anonymous/4adb86fa-535a-4ecd-8b10-7fd72b33341d

Steps to Reproduce the Bug or Issue

  1. Go to the playground link
  2. Type into the input field

Note: because customElements.define can't be called twice with same component, if you make changes to the code, you need to click the reload button.

Expected behavior

I expected the webcomponent below the input field to display the input value as it is being typed.
In devtools, I expected to see a 'constructor' log, followed by 'setter' logs when I type in the input.

However, I only see the 'constructor' log, typing in the input does not call the value setter function, hence, it does not generate the 'setter' logs.

Screenshots or Videos

No response

Platform

  • OS: Linux
  • Browser: Chrome
  • Version: 113

Additional context

I tried debugging this issue for a while and had some discoveries about the issue.

The first issue was that when trying to run the output code (by coping it into main.tsx), there is a _$template call that created the elements, when I set the isCE flag in the _$template call to false, the component starts working again.
Now inspecting solid's code a bit, when isCE is set to true, the function uses a cloneNode call to return a copy of the element, when false, it uses document.insertNode.

I latter noticed that the call to document.importNode triggers the webcomponent constructor call, making it happen before the prop setting.
After looking looking at the docs I found out document.importNode works like cloneNode, but it also sets the onwerDocument of the element.
The nodes of a template's content have a ownerDocument that is not the page's document, and that document also has null as its defaultView (the window, where customElements are stored).

In solid's template function, if I change the cloneNode by a importNode call, it starts working again.
But since I cant really do that I also tried overriding Node.prototype.cloneNode function with a call to importNode, and it works too.
However, I can't use that in the environment I'm working on, there are other teams in a microfrontends setup and I can't change properties of prototypes.

This hack is also coded in the playground example, just uncomment it and the webcomponent starts working.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions