Skip to content

Commit 4c0cf27

Browse files
authored
Merge pull request #5334 from CodinGame/webgl-renderer-shadow-dom
Support shadow dom in webgl renderer
2 parents c4b707e + 149527d commit 4c0cf27

File tree

3 files changed

+57
-8
lines changed

3 files changed

+57
-8
lines changed

addons/addon-webgl/src/WebglRenderer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
139139

140140
[this._rectangleRenderer.value, this._glyphRenderer.value] = this._initializeWebGLState();
141141

142-
this._isAttached = this._coreBrowserService.window.document.body.contains(this._core.screenElement!);
142+
this._isAttached = this._core.screenElement!.isConnected;
143143

144144
this._register(toDisposable(() => {
145145
for (const l of this._renderLayers) {
@@ -322,7 +322,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
322322

323323
public renderRows(start: number, end: number): void {
324324
if (!this._isAttached) {
325-
if (this._coreBrowserService.window.document.body.contains(this._core.screenElement!) && this._charSizeService.width && this._charSizeService.height) {
325+
if (this._core.screenElement?.isConnected && this._charSizeService.width && this._charSizeService.height) {
326326
this._updateDimensions();
327327
this._refreshCharAtlas();
328328
this._isAttached = true;

test/playwright/SharedRendererTests.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,10 +1280,10 @@ enum CellColorPosition {
12801280
* treatment.
12811281
*/
12821282
export function injectSharedRendererTestsStandalone(ctx: ISharedRendererTestContext, setupCb: () => Promise<void> | void): void {
1283-
test.describe('standalone tests', () => {
1283+
const setupTests = ({ shadowDom }: { shadowDom: boolean }): void => {
12841284
test.beforeEach(async () => {
12851285
// Recreate terminal
1286-
await openTerminal(ctx.value);
1286+
await openTerminal(ctx.value, {}, { useShadowDom: shadowDom });
12871287
await ctx.value.page.evaluate(`
12881288
window.term.options.minimumContrastRatio = 1;
12891289
window.term.options.allowTransparency = false;
@@ -1308,6 +1308,13 @@ export function injectSharedRendererTestsStandalone(ctx: ISharedRendererTestCont
13081308
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 0, 255]);
13091309
});
13101310
});
1311+
};
1312+
1313+
test.describe('standalone tests', () => {
1314+
setupTests({ shadowDom: false });
1315+
});
1316+
test.describe('standalone tests (Shadow dom)', () => {
1317+
setupTests({ shadowDom: true });
13111318
});
13121319
}
13131320

test/playwright/TestUtils.ts

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,14 @@ class TerminalCoreProxy {
412412
}
413413
}
414414

415-
export async function openTerminal(ctx: ITestContext, options: ITerminalOptions | ITerminalInitOnlyOptions = {}, testOptions: { loadUnicodeGraphemesAddon: boolean } = { loadUnicodeGraphemesAddon: true }): Promise<void> {
415+
export async function openTerminal(
416+
ctx: ITestContext,
417+
options: ITerminalOptions | ITerminalInitOnlyOptions = {},
418+
testOptions: { useShadowDom?: boolean, loadUnicodeGraphemesAddon?: boolean } = {}
419+
): Promise<void> {
420+
testOptions.useShadowDom ??= false;
421+
testOptions.loadUnicodeGraphemesAddon ??= true;
422+
416423
await ctx.page.evaluate(`
417424
if ('term' in window) {
418425
try {
@@ -423,10 +430,45 @@ export async function openTerminal(ctx: ITestContext, options: ITerminalOptions
423430
// HACK: Tests may have side effects that could cause the terminal not to be removed. This
424431
// assertion catches this case early.
425432
strictEqual(await ctx.page.evaluate(`document.querySelector('#terminal-container').children.length`), 0, 'there must be no terminals on the page');
426-
await ctx.page.evaluate(`
433+
434+
let script = `
427435
window.term = new window.Terminal(${JSON.stringify({ allowProposedApi: true, ...options })});
428-
window.term.open(document.querySelector('#terminal-container'));
429-
`);
436+
let element = document.querySelector('#terminal-container');
437+
438+
// Remove shadow root if it exists
439+
const newElement = element.cloneNode(false);
440+
element.replaceWith(newElement);
441+
element = newElement
442+
`;
443+
444+
445+
if (testOptions.useShadowDom) {
446+
script += `
447+
const shadowRoot = element.attachShadow({ mode: "open" });
448+
449+
// Copy parent styles to shadow DOM
450+
const styles = Array.from(document.querySelectorAll('link[rel="stylesheet"]'));
451+
styles.forEach((styleEl) => {
452+
const clone = document.createElement('link');
453+
clone.rel = 'stylesheet';
454+
clone.href = styleEl.href;
455+
shadowRoot.appendChild(clone);
456+
});
457+
458+
// Create new element inside the shadow DOM
459+
element = document.createElement('div');
460+
element.style.width = '100%';
461+
element.style.height = '100%';
462+
shadowRoot.appendChild(element);
463+
`;
464+
}
465+
466+
script += `
467+
window.term.open(element);
468+
`;
469+
470+
await ctx.page.evaluate(script);
471+
430472
// HACK: This is a soft layer breaker that's temporarily included until unicode graphemes have
431473
// more complete integration tests. See https://github.com/xtermjs/xterm.js/pull/4519#discussion_r1285234453
432474
if (testOptions.loadUnicodeGraphemesAddon) {

0 commit comments

Comments
 (0)