Skip to content

Commit 1fc9487

Browse files
author
Loïc Mangeonjean
committed
fix: properly implement active element tracker
across shadow doms. Also remove layoutService dependency from context key service to prevent cyclic dependency error in some configurations
1 parent b29f17c commit 1fc9487

5 files changed

Lines changed: 132 additions & 82 deletions

vscode-patches/0061-feat-support-shadow-dom.patch

Lines changed: 111 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,99 @@ Date: Fri, 2 May 2025 10:13:06 +0200
44
Subject: [PATCH] feat: support shadow dom
55

66
---
7-
src/vs/base/browser/dom.ts | 28 +++++++++++++------
8-
src/vs/base/browser/domStylesheets.ts | 21 +++++++++++---
9-
src/vs/base/browser/keyboardEvent.ts | 12 +++++++-
7+
src/vs/base/browser/dom.ts | 61 ++++++++++++++++---
8+
src/vs/base/browser/domStylesheets.ts | 21 +++++--
9+
src/vs/base/browser/keyboardEvent.ts | 12 +++-
1010
.../browser/ui/contextview/contextview.ts | 2 +-
11-
src/vs/base/browser/ui/dialog/dialog.ts | 6 ++--
12-
src/vs/base/browser/ui/dnd/dnd.ts | 4 +--
11+
src/vs/base/browser/ui/dialog/dialog.ts | 6 +-
12+
src/vs/base/browser/ui/dnd/dnd.ts | 4 +-
1313
src/vs/base/browser/ui/findinput/findInput.ts | 3 +-
1414
.../base/browser/ui/findinput/replaceInput.ts | 3 +-
1515
src/vs/base/browser/ui/inputbox/inputBox.ts | 2 +-
1616
src/vs/base/browser/ui/sash/sash.ts | 2 +-
17-
src/vs/base/browser/ui/splitview/paneview.ts | 6 ++--
18-
src/vs/base/browser/ui/splitview/splitview.ts | 6 ++--
19-
.../native/screenReaderContentRich.ts | 6 ++--
20-
.../native/screenReaderContentSimple.ts | 6 ++--
17+
src/vs/base/browser/ui/splitview/paneview.ts | 6 +-
18+
src/vs/base/browser/ui/splitview/splitview.ts | 6 +-
19+
.../native/screenReaderContentRich.ts | 6 +-
20+
.../native/screenReaderContentSimple.ts | 6 +-
2121
.../editor/browser/controller/mouseHandler.ts | 2 +-
2222
.../editor/browser/controller/mouseTarget.ts | 2 +-
2323
src/vs/editor/browser/view/viewPart.ts | 3 +-
2424
.../contentWidgets/contentWidgets.ts | 2 +-
2525
.../hover/browser/contentHoverController.ts | 3 +-
2626
.../hover/browser/contentHoverWidget.ts | 2 +-
2727
.../actionWidget/browser/actionList.ts | 2 +-
28-
.../clipboard/browser/clipboardService.ts | 4 +--
29-
.../contextkey/browser/contextKeyService.ts | 15 ++++++----
28+
.../clipboard/browser/clipboardService.ts | 4 +-
29+
.../contextkey/browser/contextKeyService.ts | 26 ++++----
3030
src/vs/platform/hover/browser/hoverWidget.ts | 2 +-
31-
.../browser/actions/developerActions.ts | 4 +--
32-
src/vs/workbench/browser/layout.ts | 3 ++
33-
.../browser/parts/editor/editorGroupView.ts | 4 +--
34-
src/vs/workbench/browser/workbench.ts | 6 ++--
31+
.../browser/actions/developerActions.ts | 4 +-
32+
src/vs/workbench/browser/layout.ts | 3 +
33+
.../browser/parts/editor/editorGroupView.ts | 4 +-
34+
src/vs/workbench/browser/workbench.ts | 6 +-
3535
.../contrib/chat/browser/chatInputPart.ts | 2 +-
3636
.../chatSessions/view/sessionsTreeRenderer.ts | 3 +-
37-
.../files/browser/views/explorerViewer.ts | 4 ++-
38-
.../notebook/browser/notebookEditorWidget.ts | 6 ++--
39-
.../browser/view/cellParts/cellStatusPart.ts | 5 ++--
40-
.../browser/view/cellParts/codeCell.ts | 6 ++--
41-
.../browser/view/cellParts/markupCell.ts | 6 ++--
42-
.../notebook/browser/view/notebookCellList.ts | 5 ++--
37+
.../files/browser/views/explorerViewer.ts | 4 +-
38+
.../notebook/browser/notebookEditorWidget.ts | 6 +-
39+
.../browser/view/cellParts/cellStatusPart.ts | 5 +-
40+
.../browser/view/cellParts/codeCell.ts | 6 +-
41+
.../browser/view/cellParts/markupCell.ts | 6 +-
42+
.../notebook/browser/view/notebookCellList.ts | 5 +-
4343
.../view/renderers/backLayerWebView.ts | 3 +-
4444
.../browser/preferences.contribution.ts | 3 +-
45-
.../preferences/browser/settingsEditor2.ts | 6 ++--
45+
.../preferences/browser/settingsEditor2.ts | 6 +-
4646
.../terminal/browser/terminalTabbedView.ts | 2 +-
4747
.../contrib/terminal/browser/terminalView.ts | 2 +-
48-
.../contrib/webview/browser/webviewElement.ts | 12 +++++---
49-
.../browser/gettingStarted.ts | 4 +--
50-
.../browser/walkThroughPart.ts | 6 ++--
51-
.../suggest/browser/simpleSuggestWidget.ts | 4 +--
48+
.../contrib/webview/browser/webviewElement.ts | 12 ++--
49+
.../browser/gettingStarted.ts | 4 +-
50+
.../browser/walkThroughPart.ts | 6 +-
51+
.../suggest/browser/simpleSuggestWidget.ts | 4 +-
5252
.../themes/browser/workbenchThemeService.ts | 2 +-
53-
46 files changed, 148 insertions(+), 94 deletions(-)
53+
46 files changed, 186 insertions(+), 100 deletions(-)
5454

5555
diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
56-
index be401204e06..f181ffdea9f 100644
56+
index be401204e06..b110cb2b742 100644
5757
--- a/src/vs/base/browser/dom.ts
5858
+++ b/src/vs/base/browser/dom.ts
59-
@@ -619,8 +619,7 @@ export function getTopLeftOffset(element: HTMLElement): IDomPosition {
59+
@@ -165,6 +165,39 @@ export function addDisposableListener(node: EventTarget, type: string, handler:
60+
return new DomListener(node, type, handler, useCaptureOrOptions);
61+
}
62+
63+
+export interface IActiveElementTracker extends Disposable {
64+
+ readonly onDidChangeActiveElement: event.Event<Element | null>;
65+
+ activeElement: Element | null;
66+
+}
67+
+
68+
+class ActiveElementTracker extends Disposable implements IActiveElementTracker {
69+
+ activeElement: Element | null = null;
70+
+ private readonly _onDidChangeActiveElement = this._register(new event.Emitter<Element | null>());
71+
+ get onDidChangeActiveElement() { return this._onDidChangeActiveElement.event; }
72+
+
73+
+ constructor(private window: CodeWindow) {
74+
+ super();
75+
+ this._register(addDisposableListener(this.window, EventType.FOCUS_IN, this._onFocusIn));
76+
+ }
77+
+
78+
+ private _onFocusIn = (e: FocusEvent) => {
79+
+ this.activeElement = getActiveElement(this.window.document);
80+
+ this._onDidChangeActiveElement.fire(this.activeElement);
81+
+
82+
+ if (e.target instanceof Element && e.target.shadowRoot) {
83+
+ const disposableStore = new DisposableStore();
84+
+ disposableStore.add(addDisposableListener(e.target.shadowRoot, EventType.FOCUS_IN, this._onFocusIn));
85+
+ disposableStore.add(addDisposableListener(e.target, EventType.FOCUS_OUT, () => {
86+
+ disposableStore.dispose();
87+
+ }));
88+
+ }
89+
+ };
90+
+}
91+
+
92+
+export function trackActiveElement(window: CodeWindow): IActiveElementTracker {
93+
+ return new ActiveElementTracker(window);
94+
+}
95+
+
96+
export interface IAddStandardDisposableListenerSignature {
97+
(node: HTMLElement | Element | Document, type: 'click', handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable;
98+
(node: HTMLElement | Element | Document, type: 'mousedown', handler: (event: IMouseEvent) => void, useCapture?: boolean): IDisposable;
99+
@@ -619,8 +652,7 @@ export function getTopLeftOffset(element: HTMLElement): IDomPosition {
60100

61101
while (
62102
(element = <HTMLElement>element.parentNode) !== null
@@ -66,7 +106,7 @@ index be401204e06..f181ffdea9f 100644
66106
) {
67107
top -= element.scrollTop;
68108
const c = isShadowRoot(element) ? null : getComputedStyle(element);
69-
@@ -722,7 +721,7 @@ export function getDomNodeZoomLevel(domNode: HTMLElement): number {
109+
@@ -722,7 +754,7 @@ export function getDomNodeZoomLevel(domNode: HTMLElement): number {
70110
}
71111

72112
testElement = testElement.parentElement;
@@ -75,7 +115,7 @@ index be401204e06..f181ffdea9f 100644
75115

76116
return zoom;
77117
}
78-
@@ -800,7 +799,7 @@ function getParentFlowToElement(node: HTMLElement): HTMLElement | null {
118+
@@ -800,7 +832,7 @@ function getParentFlowToElement(node: HTMLElement): HTMLElement | null {
79119
const flowToParentId = node.dataset[parentFlowToDataKey];
80120
if (typeof flowToParentId === 'string') {
81121
// eslint-disable-next-line no-restricted-syntax
@@ -84,7 +124,7 @@ index be401204e06..f181ffdea9f 100644
84124
}
85125
return null;
86126
}
87-
@@ -883,8 +882,8 @@ export function getShadowRoot(domNode: Node): ShadowRoot | null {
127+
@@ -883,8 +915,8 @@ export function getShadowRoot(domNode: Node): ShadowRoot | null {
88128
* based on document focus. Falls back to the main
89129
* window if no window has focus.
90130
*/
@@ -95,7 +135,7 @@ index be401204e06..f181ffdea9f 100644
95135

96136
while (result?.shadowRoot) {
97137
result = result.shadowRoot.activeElement;
98-
@@ -893,6 +892,14 @@ export function getActiveElement(): Element | null {
138+
@@ -893,6 +925,14 @@ export function getActiveElement(): Element | null {
99139
return result;
100140
}
101141

@@ -110,7 +150,7 @@ index be401204e06..f181ffdea9f 100644
110150
/**
111151
* Returns true if the focused window active element matches
112152
* the provided element. Falls back to the main window if no
113-
@@ -1044,6 +1051,11 @@ export function isHTMLDivElement(e: unknown): e is HTMLDivElement {
153+
@@ -1044,6 +1084,11 @@ export function isHTMLDivElement(e: unknown): e is HTMLDivElement {
114154
return e instanceof HTMLDivElement || e instanceof getWindow(e as Node).HTMLDivElement;
115155
}
116156

@@ -122,7 +162,7 @@ index be401204e06..f181ffdea9f 100644
122162
export function isSVGElement(e: unknown): e is SVGElement {
123163
// eslint-disable-next-line no-restricted-syntax
124164
return e instanceof SVGElement || e instanceof getWindow(e as Node).SVGElement;
125-
@@ -1189,7 +1201,7 @@ class FocusTracker extends Disposable implements IFocusTracker {
165+
@@ -1189,7 +1234,7 @@ class FocusTracker extends Disposable implements IFocusTracker {
126166
private static hasFocusWithin(element: HTMLElement | Window): boolean {
127167
if (isHTMLElement(element)) {
128168
const shadowRoot = getShadowRoot(element);
@@ -131,7 +171,7 @@ index be401204e06..f181ffdea9f 100644
131171
return isAncestor(activeElement, element);
132172
} else {
133173
const window = element;
134-
@@ -1409,7 +1421,7 @@ export function removeTabIndexAndUpdateFocus(node: HTMLElement): void {
174+
@@ -1409,7 +1454,7 @@ export function removeTabIndexAndUpdateFocus(node: HTMLElement): void {
135175
// standard DOM behavior is to move focus to the <body> element. We
136176
// typically never want that, rather put focus to the closest element
137177
// in the hierarchy of the parent DOM nodes.
@@ -612,57 +652,67 @@ index 6e0a6e018d0..358aa682cda 100644
612652
const textArea: HTMLTextAreaElement = activeDocument.body.appendChild($('textarea', { 'aria-hidden': true }));
613653
textArea.style.height = '1px';
614654
diff --git a/src/vs/platform/contextkey/browser/contextKeyService.ts b/src/vs/platform/contextkey/browser/contextKeyService.ts
615-
index 7f749b68489..53629be4418 100644
655+
index 7f749b68489..93362cb86a6 100644
616656
--- a/src/vs/platform/contextkey/browser/contextKeyService.ts
617657
+++ b/src/vs/platform/contextkey/browser/contextKeyService.ts
618-
@@ -18,7 +18,8 @@ import { ContextKeyExpression, ContextKeyInfo, ContextKeyValue, IContext, IConte
658+
@@ -3,6 +3,8 @@
659+
* Licensed under the MIT License. See License.txt in the project root for license information.
660+
*--------------------------------------------------------------------------------------------*/
661+
662+
+import { getActiveDocument, getActiveElement, isEditableElement, onDidRegisterWindow, trackActiveElement, trackFocus } from '../../../base/browser/dom.js';
663+
+import { mainWindow } from '../../../base/browser/window.js';
664+
import { Emitter, Event, PauseableEmitter } from '../../../base/common/event.js';
665+
import { Iterable } from '../../../base/common/iterator.js';
666+
import { Disposable, DisposableStore, IDisposable, MutableDisposable } from '../../../base/common/lifecycle.js';
667+
@@ -14,11 +16,9 @@ import { URI } from '../../../base/common/uri.js';
668+
import { localize } from '../../../nls.js';
669+
import { CommandsRegistry } from '../../commands/common/commands.js';
670+
import { ConfigurationTarget, IConfigurationService } from '../../configuration/common/configuration.js';
671+
-import { ContextKeyExpression, ContextKeyInfo, ContextKeyValue, IContext, IContextKey, IContextKeyChangeEvent, IContextKeyService, IContextKeyServiceTarget, IReadableSet, IScopedContextKeyService, RawContextKey } from '../common/contextkey.js';
619672
import { ServicesAccessor } from '../../instantiation/common/instantiation.js';
673+
+import { ContextKeyExpression, ContextKeyInfo, ContextKeyValue, IContext, IContextKey, IContextKeyChangeEvent, IContextKeyService, IContextKeyServiceTarget, IReadableSet, IScopedContextKeyService, RawContextKey } from '../common/contextkey.js';
620674
import { InputFocusedContext } from '../common/contextkeys.js';
621-
import { mainWindow } from '../../../base/browser/window.js';
675+
-import { mainWindow } from '../../../base/browser/window.js';
622676
-import { addDisposableListener, EventType, getActiveWindow, isEditableElement, onDidRegisterWindow, trackFocus } from '../../../base/browser/dom.js';
623-
+import { addDisposableListener, EventType, getActiveDocument, getActiveElement, isEditableElement, onDidRegisterWindow, trackFocus } from '../../../base/browser/dom.js';
624-
+import { ILayoutService } from '../../layout/browser/layoutService.js';
625677

626678
const KEYBINDING_CONTEXT_ATTR = 'data-keybinding-context';
627679

628-
@@ -383,7 +384,7 @@ export class ContextKeyService extends AbstractContextKeyService implements ICon
629-
630-
private inputFocusedContext: IContextKey<boolean>;
631-
632-
- constructor(@IConfigurationService configurationService: IConfigurationService) {
633-
+ constructor(@IConfigurationService configurationService: IConfigurationService, @ILayoutService layoutService: ILayoutService) {
634-
super(0);
635-
this._lastContextId = 0;
636-
this.inputFocusedContext = InputFocusedContext.bindTo(this);
637-
@@ -404,7 +405,7 @@ export class ContextKeyService extends AbstractContextKeyService implements ICon
680+
@@ -404,24 +404,26 @@ export class ContextKeyService extends AbstractContextKeyService implements ICon
638681

639682
this._register(Event.runAndSubscribe(onDidRegisterWindow, ({ window, disposables }) => {
640683
const onFocusDisposables = disposables.add(new MutableDisposable<DisposableStore>());
641684
- disposables.add(addDisposableListener(window, EventType.FOCUS_IN, () => {
642-
+ disposables.add(addDisposableListener(layoutService.getContainer(window), EventType.FOCUS_IN, () => {
685+
+
686+
+ const activeElementTracker = disposables.add(trackActiveElement(window));
687+
+ activeElementTracker.onDidChangeActiveElement((activeElement) => {
643688
onFocusDisposables.value = new DisposableStore();
644-
this.updateInputContextKeys(window.document, onFocusDisposables.value);
645-
}, true));
646-
@@ -414,14 +415,16 @@ export class ContextKeyService extends AbstractContextKeyService implements ICon
647-
private updateInputContextKeys(ownerDocument: Document, disposables: DisposableStore): void {
689+
- this.updateInputContextKeys(window.document, onFocusDisposables.value);
690+
- }, true));
691+
+ this.updateInputContextKeys(window.document, activeElement, onFocusDisposables.value);
692+
+ });
693+
}, { window: mainWindow, disposables: this._store }));
694+
}
695+
696+
- private updateInputContextKeys(ownerDocument: Document, disposables: DisposableStore): void {
697+
+ private updateInputContextKeys(ownerDocument: Document, activeElement: Element | null, disposables: DisposableStore): void {
648698

649-
function activeElementIsInput(): boolean {
699+
- function activeElementIsInput(): boolean {
650700
- return !!ownerDocument.activeElement && isEditableElement(ownerDocument.activeElement);
651-
+ const activeElement = getActiveElement(ownerDocument);
701+
+ function activeElementIsInput(activeElement: Element | null = getActiveElement(ownerDocument)): boolean {
652702
+ return !!activeElement && isEditableElement(activeElement);
653703
}
654704

655-
const isInputFocused = activeElementIsInput();
705+
- const isInputFocused = activeElementIsInput();
706+
+ const isInputFocused = activeElementIsInput(activeElement);
656707
this.inputFocusedContext.set(isInputFocused);
657708

658709
if (isInputFocused) {
659710
- const tracker = disposables.add(trackFocus(ownerDocument.activeElement as HTMLElement));
660-
+ const activeElement = getActiveElement(ownerDocument);
661711
+ const tracker = disposables.add(trackFocus(activeElement as HTMLElement));
662712
Event.once(tracker.onDidBlur)(() => {
663713

664714
// Ensure we are only updating the context key if we are
665-
@@ -432,7 +435,7 @@ export class ContextKeyService extends AbstractContextKeyService implements ICon
715+
@@ -432,7 +434,7 @@ export class ContextKeyService extends AbstractContextKeyService implements ICon
666716
// blur events from the focus tracker are emitted with a
667717
// timeout of 0.
668718

vscode-patches/0067-feat-prevent-IDE-from-entering-fullscreen-if-not-occ.patch

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ Subject: [PATCH] feat: prevent IDE from entering fullscreen if not occupying
1111
3 files changed, 11 insertions(+), 7 deletions(-)
1212

1313
diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
14-
index f181ffdea9f..8be3c97a212 100644
14+
index b110cb2b742..278424505eb 100644
1515
--- a/src/vs/base/browser/dom.ts
1616
+++ b/src/vs/base/browser/dom.ts
17-
@@ -1666,11 +1666,13 @@ export interface IDetectedFullscreen {
17+
@@ -1699,11 +1699,13 @@ export interface IDetectedFullscreen {
1818
guess: boolean;
1919
}
2020

@@ -31,7 +31,7 @@ index f181ffdea9f..8be3c97a212 100644
3131
return { mode: DetectedFullscreenMode.DOCUMENT, guess: false };
3232
}
3333

34-
@@ -1679,7 +1681,9 @@ export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | nu
34+
@@ -1712,7 +1714,9 @@ export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | nu
3535
// height and comparing that to window height, we can guess
3636
// it though.
3737

@@ -42,7 +42,7 @@ index f181ffdea9f..8be3c97a212 100644
4242
// if the height of the window matches the screen height, we can
4343
// safely assume that the browser is fullscreen because no browser
4444
// chrome is taking height away (e.g. like toolbars).
45-
@@ -1688,7 +1692,7 @@ export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | nu
45+
@@ -1721,7 +1725,7 @@ export function detectFullscreen(targetWindow: Window): IDetectedFullscreen | nu
4646

4747
if (platform.isMacintosh || platform.isLinux) {
4848
// macOS and Linux do not properly report `innerHeight`, only Windows does

vscode-patches/0068-feat-support-loading-VSCode-in-an-iframe.patch

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@ Subject: [PATCH] feat: support loading VSCode in an iframe
66
---
77
src/vs/base/browser/dom.ts | 39 +++++++------------
88
src/vs/base/browser/domStylesheets.ts | 4 +-
9-
src/vs/base/browser/window.ts | 7 +++-
9+
src/vs/base/browser/window.ts | 6 ++-
1010
src/vs/workbench/browser/window.ts | 25 ++++++++----
1111
.../performance/browser/perfviewEditor.ts | 3 +-
1212
.../performance/browser/startupTimings.ts | 3 +-
1313
.../browser/webWorkerExtensionHost.ts | 6 +--
1414
.../lifecycle/browser/lifecycleService.ts | 2 +-
15-
8 files changed, 46 insertions(+), 43 deletions(-)
15+
8 files changed, 45 insertions(+), 43 deletions(-)
1616

1717
diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
18-
index 8be3c97a212..1f8cb13a03d 100644
18+
index 278424505eb..f3bb5a8352b 100644
1919
--- a/src/vs/base/browser/dom.ts
2020
+++ b/src/vs/base/browser/dom.ts
21-
@@ -1017,68 +1017,55 @@ function createHeadElement<K extends keyof HTMLElementTagNameMap>(tagName: K, co
21+
@@ -1050,68 +1050,55 @@ function createHeadElement<K extends keyof HTMLElementTagNameMap>(tagName: K, co
2222
}
2323

2424
export function isHTMLElement(e: unknown): e is HTMLElement {
@@ -123,10 +123,10 @@ index 0782c211144..61e4c36505d 100644
123123
}
124124
}
125125
diff --git a/src/vs/base/browser/window.ts b/src/vs/base/browser/window.ts
126-
index ab920e18349..c4a02c5ca47 100644
126+
index ab920e18349..ab318ad411d 100644
127127
--- a/src/vs/base/browser/window.ts
128128
+++ b/src/vs/base/browser/window.ts
129-
@@ -17,8 +17,13 @@ export function ensureCodeWindow(targetWindow: Window, fallbackWindowId: number)
129+
@@ -17,8 +17,12 @@ export function ensureCodeWindow(targetWindow: Window, fallbackWindowId: number)
130130
}
131131
}
132132

vscode-patches/0069-feat-mark-elements-created-outside-of-the-VSCode-con.patch

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ Subject: [PATCH] feat: mark elements created outside of the VSCode container
99
2 files changed, 2 insertions(+)
1010

1111
diff --git a/src/vs/base/browser/dom.ts b/src/vs/base/browser/dom.ts
12-
index 1f8cb13a03d..b5a908504f7 100644
12+
index f3bb5a8352b..0a22d593f8c 100644
1313
--- a/src/vs/base/browser/dom.ts
1414
+++ b/src/vs/base/browser/dom.ts
15-
@@ -1012,6 +1012,7 @@ export function createLinkElement(container: HTMLElement = mainWindow.document.h
15+
@@ -1045,6 +1045,7 @@ export function createLinkElement(container: HTMLElement = mainWindow.document.h
1616

1717
function createHeadElement<K extends keyof HTMLElementTagNameMap>(tagName: K, container: HTMLElement = mainWindow.document.head): HTMLElementTagNameMap[K] {
1818
const element = document.createElement(tagName);

0 commit comments

Comments
 (0)