Open NullVoxPopuli opened 4 months ago
import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { modifier } from 'ember-modifier'; const attachShadow = modifier((element: Element, [set]: [(shadowRoot: ShadowRoot) => void]) => { let shadow = element.attachShadow({ mode: 'open' }); set(shadow); }); // index.html has the production-fingerprinted references to these links // Ideally, we'd have some pre-processor scan everything for references to // assets in public, but idk how to set that up const getStyles = () => [...document.head.querySelectorAll('link')].map((link) => link.href); export class Shadowed extends Component<{ Element: HTMLDivElement; Args: { omitStyles?: boolean; }; Blocks: { default: [] }; }> { @tracked shadow: ShadowRoot | undefined; setShadow = async (shadowRoot: ShadowRoot) => { await Promise.resolve(); this.shadow = shadowRoot; } <template> <div data-shadow {{attachShadow this.setShadow}} ...attributes></div> {{#if this.shadow}} {{#in-element this.shadow}} {{#unless @omitStyles}} {{#each (getStyles) as |styleHref|}} <link rel="stylesheet" href={{styleHref}} /> {{/each}} {{/unless}} {{yield}} {{/in-element}} {{/if}} </template> } export default Shadowed;
Used in this test:
import { find, render } from '@ember/test-helpers'; import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; import { Shadowed } from 'limber/components/shadowed'; module('Rendering | <Shadowed>', function (hooks) { setupRenderingTest(hooks); test('it works', async function (assert) { await render( <template> out of shadow <Shadowed> in shadow </Shadowed> </template> ); assert.dom().hasText('out of shadow'); assert.dom().doesNotContainText('in shadow'); // assort.dom forgot that ShadowDom is a thing // assert.dom(find('[data-shadow]')?.shadowRoot).hasText('in shadow'); assert.ok(find('[data-shadow]')?.shadowRoot?.textContent?.includes('in shadow')); }); });
Causes this error:
Error occurred: - While rendering: -top-level application index _shadowedTest Shadowed [runtime.js:5723](http://localhost:4201/assets/@glimmer/runtime.js) Error occurred: [runtime.js:4948](http://localhost:4201/assets/@glimmer/runtime.js) Uncaught (in promise) Error: Got [object ShadowRoot], expected: { nodeType: 1,tagName: typeof string,nextSibling: any } check debug.js:1512 # @glimmer/debug <anonymous> runtime.js:1508 evaluate runtime.js:1061
and doesn't actually render in to the shadow dom:
A clear and concise description of what you expected to happen.
I was able to get desired behavior at the cost of an extra div here:
import Component from '@glimmer/component'; import { tracked } from '@glimmer/tracking'; import { modifier } from 'ember-modifier'; const attachShadow = modifier((element: Element, [set]: [(shadowRoot: HTMLDivElement) => void]) => { let shadow = element.attachShadow({ mode: 'open' }); let div = document.createElement('div'); shadow.appendChild(div); set(div); }); // index.html has the production-fingerprinted references to these links // Ideally, we'd have some pre-processor scan everything for references to // assets in public, but idk how to set that up const getStyles = () => [...document.head.querySelectorAll('link')].map((link) => link.href); export class Shadowed extends Component<{ Element: HTMLDivElement; Args: { omitStyles?: boolean; }; Blocks: { default: [] }; }> { @tracked shadow: HTMLDivElement | undefined; setShadow = async (shadowRoot: HTMLDivElement) => { await Promise.resolve(); this.shadow = shadowRoot; } <template> <div data-shadow {{attachShadow this.setShadow}} ...attributes></div> {{#if this.shadow}} {{#in-element this.shadow}} {{#unless @omitStyles}} {{#each (getStyles) as |styleHref|}} <link rel="stylesheet" href={{styleHref}} /> {{/each}} {{/unless}} {{yield}} {{/in-element}} {{/if}} </template> } export default Shadowed;
(this change also makes the test pass, but again, at the cost of an extra div)
Repro: https://github.com/NullVoxPopuli/ember-source-5.6-broke-shadow-dom (check commits)
I have a hunch this has to do with Glimmer-vm changes :thinking:
🐞 Describe the Bug
😕 Actual Behavior
Used in this test:
Causes this error:
and doesn't actually render in to the shadow dom:![image](https://github.com/emberjs/ember.js/assets/199018/ad8bc3ef-38ed-4f08-9795-54c148d116dc)
🤔 Expected Behavior
A clear and concise description of what you expected to happen.
🌍 Environment
I was able to get desired behavior at the cost of an extra div here:
(this change also makes the test pass, but again, at the cost of an extra div)