Skip to content

Support shadow dom in webgl renderer #5334

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

CGNonofr
Copy link

@CGNonofr CGNonofr commented May 5, 2025

Similar to what has been done in #3239, but for the webgl renderer

fix #5338

@CGNonofr CGNonofr force-pushed the webgl-renderer-shadow-dom branch from 306427a to 08de2e9 Compare May 20, 2025 14:31
@@ -1280,10 +1280,10 @@ enum CellColorPosition {
* treatment.
*/
export function injectSharedRendererTestsStandalone(ctx: ISharedRendererTestContext, setupCb: () => Promise<void> | void): void {
test.describe('standalone tests', () => {
const run = (shadowDom: boolean): void => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setupTests({ useShadowDom: false }) would read better than this when it's called below, run(false) isn't easily understandable without following the symbol.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! updated and amended

@@ -1332,7 +1339,7 @@ function getCellColor(ctx: ITestContext, col: number, row: number, position: Cel
let frameDetails: { cols: number, rows: number, decoded: IImage32 } | undefined = undefined;
async function getFrameDetails(ctx: ITestContext): Promise<{ cols: number, rows: number, decoded: IImage32 }> {
const screenshotOptions: LocatorScreenshotOptions | undefined = process.env.DEBUG ? { path: 'out-esbuild-test/playwright/screenshot.png' } : undefined;
const buffer = await ctx.page.locator('#terminal-container .xterm-screen').screenshot(screenshotOptions);
const buffer = await ctx.page.locator('#terminal-container').locator('.xterm-screen').screenshot(screenshotOptions);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you switch this change back unless it does something useful?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, amended as well

await ctx.page.evaluate(`
window.unicode = new UnicodeGraphemesAddon();
window.term.loadAddon(window.unicode);
window.term.unicode.activeVersion = '15-graphemes';
`);
}
await ctx.page.waitForSelector('.xterm-rows');
await ctx.page.locator('.xterm-rows').waitFor();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you switch this change back unless it does something useful?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amended as well

note that the waitForSelector method comment suggests to use that syntax instead

@@ -412,7 +412,7 @@ class TerminalCoreProxy {
}
}

export async function openTerminal(ctx: ITestContext, options: ITerminalOptions | ITerminalInitOnlyOptions = {}, testOptions: { loadUnicodeGraphemesAddon: boolean } = { loadUnicodeGraphemesAddon: true }): Promise<void> {
export async function openTerminal(ctx: ITestContext, options: ITerminalOptions | ITerminalInitOnlyOptions = {}, { useShadowDom = false, loadUnicodeGraphemesAddon = true }: { loadUnicodeGraphemesAddon?: boolean, useShadowDom?: boolean } = { }): Promise<void> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you keep testOptions as it was?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then I'm not sure how to be able to:

  • keep the loadUnicodeGraphemesAddon default value
  • have a default value on useShadowDom
  • make it work when only providing the useShadowDom parameter

Without adding some boilerplate in the function itself 🤔 what is the issue with that syntax?

Comment on lines +430 to +434
// Remove shadow root if it exists
const newElement = element.cloneNode(false);
element.replaceWith(newElement);
element = newElement
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this stuff only happen if !!useShadowDom?

Copy link
Author

@CGNonofr CGNonofr May 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, because if the previous test was using shadow dom, the next test need to clean it no matter what (just like the call to dispose on any existing term instance a few line above)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(if an element has a shadow dom attached, it doesn't seem we can still continue injecting other elements in it)

Comment on lines 435 to 453
${useShadowDom ? `
const shadowRoot = element.attachShadow({ mode: "open" });

// Copy parent styles to shadow DOM
const styles = Array.from(document.querySelectorAll('link[rel="stylesheet"]'));
styles.forEach((styleEl) => {
const clone = document.createElement('link');
clone.rel = 'stylesheet';
clone.href = styleEl.href;
shadowRoot.appendChild(clone);
});

// Create new element inside the shadow DOM
element = document.createElement('div');
element.style.width = '100%';
element.style.height = '100%';
shadowRoot.appendChild(element);
`: `
`}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads hard, part of it is the indentation. Assembling the string before the evaluate call is a more readable way to handle this:

let script = '...'
if (useShadowDom) {
  script += '...';
}
script += '...';

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I won't agree on this one but It's not a big deal to me, changed and amended as well

@CGNonofr CGNonofr force-pushed the webgl-renderer-shadow-dom branch from 08de2e9 to 3ad83dd Compare May 21, 2025 19:51
@CGNonofr
Copy link
Author

ping @Tyriar ?

@CGNonofr
Copy link
Author

CGNonofr commented Jun 9, 2025

Is there anything I can do to make it move forward?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

WebGL renderer doesn't work in a shadow dom
2 participants