@xterm/xterm 5.6.0-beta.6 → 5.6.0-beta.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +7 -3
  2. package/css/xterm.css +71 -4
  3. package/lib/xterm.js +1 -1
  4. package/lib/xterm.js.map +1 -1
  5. package/lib/xterm.mjs +53 -0
  6. package/lib/xterm.mjs.map +7 -0
  7. package/package.json +43 -33
  8. package/src/browser/AccessibilityManager.ts +53 -25
  9. package/src/browser/{Terminal.ts → CoreBrowserTerminal.ts} +132 -144
  10. package/src/browser/Linkifier.ts +15 -13
  11. package/src/browser/LocalizableStrings.ts +15 -4
  12. package/src/browser/{Types.d.ts → Types.ts} +67 -15
  13. package/src/browser/Viewport.ts +142 -370
  14. package/src/browser/decorations/BufferDecorationRenderer.ts +14 -9
  15. package/src/browser/decorations/OverviewRulerRenderer.ts +40 -44
  16. package/src/browser/public/Terminal.ts +25 -19
  17. package/src/browser/renderer/dom/DomRenderer.ts +14 -16
  18. package/src/browser/renderer/shared/CharAtlasUtils.ts +4 -0
  19. package/src/browser/renderer/shared/CustomGlyphs.ts +6 -0
  20. package/src/browser/renderer/shared/DevicePixelObserver.ts +1 -2
  21. package/src/browser/renderer/shared/TextureAtlas.ts +3 -3
  22. package/src/browser/renderer/shared/{Types.d.ts → Types.ts} +4 -4
  23. package/src/browser/services/CharSizeService.ts +6 -6
  24. package/src/browser/services/CoreBrowserService.ts +15 -15
  25. package/src/browser/services/LinkProviderService.ts +2 -2
  26. package/src/browser/services/RenderService.ts +20 -20
  27. package/src/browser/services/SelectionService.ts +8 -8
  28. package/src/browser/services/Services.ts +13 -13
  29. package/src/browser/services/ThemeService.ts +17 -56
  30. package/src/browser/shared/Constants.ts +8 -0
  31. package/src/common/CircularList.ts +5 -5
  32. package/src/common/CoreTerminal.ts +35 -41
  33. package/src/common/InputHandler.ts +34 -28
  34. package/src/common/{Types.d.ts → Types.ts} +11 -17
  35. package/src/common/buffer/Buffer.ts +5 -1
  36. package/src/common/buffer/BufferSet.ts +5 -5
  37. package/src/common/buffer/Marker.ts +4 -4
  38. package/src/common/buffer/{Types.d.ts → Types.ts} +2 -2
  39. package/src/common/input/WriteBuffer.ts +3 -3
  40. package/src/common/parser/EscapeSequenceParser.ts +4 -4
  41. package/src/common/public/BufferNamespaceApi.ts +3 -3
  42. package/src/common/services/BufferService.ts +7 -7
  43. package/src/common/services/CoreMouseService.ts +5 -3
  44. package/src/common/services/CoreService.ts +6 -6
  45. package/src/common/services/DecorationService.ts +8 -9
  46. package/src/common/services/LogService.ts +2 -2
  47. package/src/common/services/OptionsService.ts +5 -5
  48. package/src/common/services/Services.ts +24 -17
  49. package/src/common/services/UnicodeService.ts +2 -2
  50. package/src/vs/base/browser/browser.ts +141 -0
  51. package/src/vs/base/browser/canIUse.ts +49 -0
  52. package/src/vs/base/browser/dom.ts +2369 -0
  53. package/src/vs/base/browser/fastDomNode.ts +316 -0
  54. package/src/vs/base/browser/globalPointerMoveMonitor.ts +112 -0
  55. package/src/vs/base/browser/iframe.ts +135 -0
  56. package/src/vs/base/browser/keyboardEvent.ts +213 -0
  57. package/src/vs/base/browser/mouseEvent.ts +229 -0
  58. package/src/vs/base/browser/touch.ts +372 -0
  59. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +303 -0
  60. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +114 -0
  61. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +720 -0
  62. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +165 -0
  63. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +114 -0
  64. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +243 -0
  65. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +118 -0
  66. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +116 -0
  67. package/src/vs/base/browser/ui/widget.ts +57 -0
  68. package/src/vs/base/browser/window.ts +14 -0
  69. package/src/vs/base/common/arrays.ts +887 -0
  70. package/src/vs/base/common/arraysFind.ts +202 -0
  71. package/src/vs/base/common/assert.ts +71 -0
  72. package/src/vs/base/common/async.ts +1992 -0
  73. package/src/vs/base/common/cancellation.ts +148 -0
  74. package/src/vs/base/common/charCode.ts +450 -0
  75. package/src/vs/base/common/collections.ts +140 -0
  76. package/src/vs/base/common/decorators.ts +130 -0
  77. package/src/vs/base/common/equals.ts +146 -0
  78. package/src/vs/base/common/errors.ts +303 -0
  79. package/src/vs/base/common/event.ts +1778 -0
  80. package/src/vs/base/common/functional.ts +32 -0
  81. package/src/vs/base/common/hash.ts +316 -0
  82. package/src/vs/base/common/iterator.ts +159 -0
  83. package/src/vs/base/common/keyCodes.ts +526 -0
  84. package/src/vs/base/common/keybindings.ts +284 -0
  85. package/src/vs/base/common/lazy.ts +47 -0
  86. package/src/vs/base/common/lifecycle.ts +801 -0
  87. package/src/vs/base/common/linkedList.ts +142 -0
  88. package/src/vs/base/common/map.ts +202 -0
  89. package/src/vs/base/common/numbers.ts +98 -0
  90. package/src/vs/base/common/observable.ts +76 -0
  91. package/src/vs/base/common/observableInternal/api.ts +31 -0
  92. package/src/vs/base/common/observableInternal/autorun.ts +281 -0
  93. package/src/vs/base/common/observableInternal/base.ts +489 -0
  94. package/src/vs/base/common/observableInternal/debugName.ts +145 -0
  95. package/src/vs/base/common/observableInternal/derived.ts +428 -0
  96. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +146 -0
  97. package/src/vs/base/common/observableInternal/logging.ts +328 -0
  98. package/src/vs/base/common/observableInternal/promise.ts +209 -0
  99. package/src/vs/base/common/observableInternal/utils.ts +610 -0
  100. package/src/vs/base/common/platform.ts +281 -0
  101. package/src/vs/base/common/scrollable.ts +522 -0
  102. package/src/vs/base/common/sequence.ts +34 -0
  103. package/src/vs/base/common/stopwatch.ts +43 -0
  104. package/src/vs/base/common/strings.ts +557 -0
  105. package/src/vs/base/common/symbols.ts +9 -0
  106. package/src/vs/base/common/uint.ts +59 -0
  107. package/src/vs/patches/nls.ts +90 -0
  108. package/src/vs/typings/base-common.d.ts +20 -0
  109. package/src/vs/typings/require.d.ts +42 -0
  110. package/src/vs/typings/thenable.d.ts +12 -0
  111. package/src/vs/typings/vscode-globals-nls.d.ts +36 -0
  112. package/src/vs/typings/vscode-globals-product.d.ts +33 -0
  113. package/typings/xterm.d.ts +59 -15
  114. package/src/browser/Lifecycle.ts +0 -33
  115. package/src/common/EventEmitter.ts +0 -78
  116. package/src/common/Lifecycle.ts +0 -108
  117. /package/src/browser/selection/{Types.d.ts → Types.ts} +0 -0
  118. /package/src/common/parser/{Types.d.ts → Types.ts} +0 -0
@@ -0,0 +1,316 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+
6
+ export class FastDomNode<T extends HTMLElement> {
7
+
8
+ private _maxWidth: string = '';
9
+ private _width: string = '';
10
+ private _height: string = '';
11
+ private _top: string = '';
12
+ private _left: string = '';
13
+ private _bottom: string = '';
14
+ private _right: string = '';
15
+ private _paddingTop: string = '';
16
+ private _paddingLeft: string = '';
17
+ private _paddingBottom: string = '';
18
+ private _paddingRight: string = '';
19
+ private _fontFamily: string = '';
20
+ private _fontWeight: string = '';
21
+ private _fontSize: string = '';
22
+ private _fontStyle: string = '';
23
+ private _fontFeatureSettings: string = '';
24
+ private _fontVariationSettings: string = '';
25
+ private _textDecoration: string = '';
26
+ private _lineHeight: string = '';
27
+ private _letterSpacing: string = '';
28
+ private _className: string = '';
29
+ private _display: string = '';
30
+ private _position: string = '';
31
+ private _visibility: string = '';
32
+ private _color: string = '';
33
+ private _backgroundColor: string = '';
34
+ private _layerHint: boolean = false;
35
+ private _contain: 'none' | 'strict' | 'content' | 'size' | 'layout' | 'style' | 'paint' = 'none';
36
+ private _boxShadow: string = '';
37
+
38
+ constructor(
39
+ public readonly domNode: T
40
+ ) { }
41
+
42
+ public setMaxWidth(_maxWidth: number | string): void {
43
+ const maxWidth = numberAsPixels(_maxWidth);
44
+ if (this._maxWidth === maxWidth) {
45
+ return;
46
+ }
47
+ this._maxWidth = maxWidth;
48
+ this.domNode.style.maxWidth = this._maxWidth;
49
+ }
50
+
51
+ public setWidth(_width: number | string): void {
52
+ const width = numberAsPixels(_width);
53
+ if (this._width === width) {
54
+ return;
55
+ }
56
+ this._width = width;
57
+ this.domNode.style.width = this._width;
58
+ }
59
+
60
+ public setHeight(_height: number | string): void {
61
+ const height = numberAsPixels(_height);
62
+ if (this._height === height) {
63
+ return;
64
+ }
65
+ this._height = height;
66
+ this.domNode.style.height = this._height;
67
+ }
68
+
69
+ public setTop(_top: number | string): void {
70
+ const top = numberAsPixels(_top);
71
+ if (this._top === top) {
72
+ return;
73
+ }
74
+ this._top = top;
75
+ this.domNode.style.top = this._top;
76
+ }
77
+
78
+ public setLeft(_left: number | string): void {
79
+ const left = numberAsPixels(_left);
80
+ if (this._left === left) {
81
+ return;
82
+ }
83
+ this._left = left;
84
+ this.domNode.style.left = this._left;
85
+ }
86
+
87
+ public setBottom(_bottom: number | string): void {
88
+ const bottom = numberAsPixels(_bottom);
89
+ if (this._bottom === bottom) {
90
+ return;
91
+ }
92
+ this._bottom = bottom;
93
+ this.domNode.style.bottom = this._bottom;
94
+ }
95
+
96
+ public setRight(_right: number | string): void {
97
+ const right = numberAsPixels(_right);
98
+ if (this._right === right) {
99
+ return;
100
+ }
101
+ this._right = right;
102
+ this.domNode.style.right = this._right;
103
+ }
104
+
105
+ public setPaddingTop(_paddingTop: number | string): void {
106
+ const paddingTop = numberAsPixels(_paddingTop);
107
+ if (this._paddingTop === paddingTop) {
108
+ return;
109
+ }
110
+ this._paddingTop = paddingTop;
111
+ this.domNode.style.paddingTop = this._paddingTop;
112
+ }
113
+
114
+ public setPaddingLeft(_paddingLeft: number | string): void {
115
+ const paddingLeft = numberAsPixels(_paddingLeft);
116
+ if (this._paddingLeft === paddingLeft) {
117
+ return;
118
+ }
119
+ this._paddingLeft = paddingLeft;
120
+ this.domNode.style.paddingLeft = this._paddingLeft;
121
+ }
122
+
123
+ public setPaddingBottom(_paddingBottom: number | string): void {
124
+ const paddingBottom = numberAsPixels(_paddingBottom);
125
+ if (this._paddingBottom === paddingBottom) {
126
+ return;
127
+ }
128
+ this._paddingBottom = paddingBottom;
129
+ this.domNode.style.paddingBottom = this._paddingBottom;
130
+ }
131
+
132
+ public setPaddingRight(_paddingRight: number | string): void {
133
+ const paddingRight = numberAsPixels(_paddingRight);
134
+ if (this._paddingRight === paddingRight) {
135
+ return;
136
+ }
137
+ this._paddingRight = paddingRight;
138
+ this.domNode.style.paddingRight = this._paddingRight;
139
+ }
140
+
141
+ public setFontFamily(fontFamily: string): void {
142
+ if (this._fontFamily === fontFamily) {
143
+ return;
144
+ }
145
+ this._fontFamily = fontFamily;
146
+ this.domNode.style.fontFamily = this._fontFamily;
147
+ }
148
+
149
+ public setFontWeight(fontWeight: string): void {
150
+ if (this._fontWeight === fontWeight) {
151
+ return;
152
+ }
153
+ this._fontWeight = fontWeight;
154
+ this.domNode.style.fontWeight = this._fontWeight;
155
+ }
156
+
157
+ public setFontSize(_fontSize: number | string): void {
158
+ const fontSize = numberAsPixels(_fontSize);
159
+ if (this._fontSize === fontSize) {
160
+ return;
161
+ }
162
+ this._fontSize = fontSize;
163
+ this.domNode.style.fontSize = this._fontSize;
164
+ }
165
+
166
+ public setFontStyle(fontStyle: string): void {
167
+ if (this._fontStyle === fontStyle) {
168
+ return;
169
+ }
170
+ this._fontStyle = fontStyle;
171
+ this.domNode.style.fontStyle = this._fontStyle;
172
+ }
173
+
174
+ public setFontFeatureSettings(fontFeatureSettings: string): void {
175
+ if (this._fontFeatureSettings === fontFeatureSettings) {
176
+ return;
177
+ }
178
+ this._fontFeatureSettings = fontFeatureSettings;
179
+ this.domNode.style.fontFeatureSettings = this._fontFeatureSettings;
180
+ }
181
+
182
+ public setFontVariationSettings(fontVariationSettings: string): void {
183
+ if (this._fontVariationSettings === fontVariationSettings) {
184
+ return;
185
+ }
186
+ this._fontVariationSettings = fontVariationSettings;
187
+ this.domNode.style.fontVariationSettings = this._fontVariationSettings;
188
+ }
189
+
190
+ public setTextDecoration(textDecoration: string): void {
191
+ if (this._textDecoration === textDecoration) {
192
+ return;
193
+ }
194
+ this._textDecoration = textDecoration;
195
+ this.domNode.style.textDecoration = this._textDecoration;
196
+ }
197
+
198
+ public setLineHeight(_lineHeight: number | string): void {
199
+ const lineHeight = numberAsPixels(_lineHeight);
200
+ if (this._lineHeight === lineHeight) {
201
+ return;
202
+ }
203
+ this._lineHeight = lineHeight;
204
+ this.domNode.style.lineHeight = this._lineHeight;
205
+ }
206
+
207
+ public setLetterSpacing(_letterSpacing: number | string): void {
208
+ const letterSpacing = numberAsPixels(_letterSpacing);
209
+ if (this._letterSpacing === letterSpacing) {
210
+ return;
211
+ }
212
+ this._letterSpacing = letterSpacing;
213
+ this.domNode.style.letterSpacing = this._letterSpacing;
214
+ }
215
+
216
+ public setClassName(className: string): void {
217
+ if (this._className === className) {
218
+ return;
219
+ }
220
+ this._className = className;
221
+ this.domNode.className = this._className;
222
+ }
223
+
224
+ public toggleClassName(className: string, shouldHaveIt?: boolean): void {
225
+ this.domNode.classList.toggle(className, shouldHaveIt);
226
+ this._className = this.domNode.className;
227
+ }
228
+
229
+ public setDisplay(display: string): void {
230
+ if (this._display === display) {
231
+ return;
232
+ }
233
+ this._display = display;
234
+ this.domNode.style.display = this._display;
235
+ }
236
+
237
+ public setPosition(position: string): void {
238
+ if (this._position === position) {
239
+ return;
240
+ }
241
+ this._position = position;
242
+ this.domNode.style.position = this._position;
243
+ }
244
+
245
+ public setVisibility(visibility: string): void {
246
+ if (this._visibility === visibility) {
247
+ return;
248
+ }
249
+ this._visibility = visibility;
250
+ this.domNode.style.visibility = this._visibility;
251
+ }
252
+
253
+ public setColor(color: string): void {
254
+ if (this._color === color) {
255
+ return;
256
+ }
257
+ this._color = color;
258
+ this.domNode.style.color = this._color;
259
+ }
260
+
261
+ public setBackgroundColor(backgroundColor: string): void {
262
+ if (this._backgroundColor === backgroundColor) {
263
+ return;
264
+ }
265
+ this._backgroundColor = backgroundColor;
266
+ this.domNode.style.backgroundColor = this._backgroundColor;
267
+ }
268
+
269
+ public setLayerHinting(layerHint: boolean): void {
270
+ if (this._layerHint === layerHint) {
271
+ return;
272
+ }
273
+ this._layerHint = layerHint;
274
+ this.domNode.style.transform = this._layerHint ? 'translate3d(0px, 0px, 0px)' : '';
275
+ }
276
+
277
+ public setBoxShadow(boxShadow: string): void {
278
+ if (this._boxShadow === boxShadow) {
279
+ return;
280
+ }
281
+ this._boxShadow = boxShadow;
282
+ this.domNode.style.boxShadow = boxShadow;
283
+ }
284
+
285
+ public setContain(contain: 'none' | 'strict' | 'content' | 'size' | 'layout' | 'style' | 'paint'): void {
286
+ if (this._contain === contain) {
287
+ return;
288
+ }
289
+ this._contain = contain;
290
+ (<any>this.domNode.style).contain = this._contain;
291
+ }
292
+
293
+ public setAttribute(name: string, value: string): void {
294
+ this.domNode.setAttribute(name, value);
295
+ }
296
+
297
+ public removeAttribute(name: string): void {
298
+ this.domNode.removeAttribute(name);
299
+ }
300
+
301
+ public appendChild(child: FastDomNode<T>): void {
302
+ this.domNode.appendChild(child.domNode);
303
+ }
304
+
305
+ public removeChild(child: FastDomNode<T>): void {
306
+ this.domNode.removeChild(child.domNode);
307
+ }
308
+ }
309
+
310
+ function numberAsPixels(value: number | string): string {
311
+ return (typeof value === 'number' ? `${value}px` : value);
312
+ }
313
+
314
+ export function createFastDomNode<T extends HTMLElement>(domNode: T): FastDomNode<T> {
315
+ return new FastDomNode(domNode);
316
+ }
@@ -0,0 +1,112 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+
6
+ import * as dom from 'vs/base/browser/dom';
7
+ import { DisposableStore, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
8
+
9
+ export interface IPointerMoveCallback {
10
+ (event: PointerEvent): void;
11
+ }
12
+
13
+ export interface IOnStopCallback {
14
+ (browserEvent?: PointerEvent | KeyboardEvent): void;
15
+ }
16
+
17
+ export class GlobalPointerMoveMonitor implements IDisposable {
18
+
19
+ private readonly _hooks = new DisposableStore();
20
+ private _pointerMoveCallback: IPointerMoveCallback | null = null;
21
+ private _onStopCallback: IOnStopCallback | null = null;
22
+
23
+ public dispose(): void {
24
+ this.stopMonitoring(false);
25
+ this._hooks.dispose();
26
+ }
27
+
28
+ public stopMonitoring(invokeStopCallback: boolean, browserEvent?: PointerEvent | KeyboardEvent): void {
29
+ if (!this.isMonitoring()) {
30
+ // Not monitoring
31
+ return;
32
+ }
33
+
34
+ // Unhook
35
+ this._hooks.clear();
36
+ this._pointerMoveCallback = null;
37
+ const onStopCallback = this._onStopCallback;
38
+ this._onStopCallback = null;
39
+
40
+ if (invokeStopCallback && onStopCallback) {
41
+ onStopCallback(browserEvent);
42
+ }
43
+ }
44
+
45
+ public isMonitoring(): boolean {
46
+ return !!this._pointerMoveCallback;
47
+ }
48
+
49
+ public startMonitoring(
50
+ initialElement: Element,
51
+ pointerId: number,
52
+ initialButtons: number,
53
+ pointerMoveCallback: IPointerMoveCallback,
54
+ onStopCallback: IOnStopCallback
55
+ ): void {
56
+ if (this.isMonitoring()) {
57
+ this.stopMonitoring(false);
58
+ }
59
+ this._pointerMoveCallback = pointerMoveCallback;
60
+ this._onStopCallback = onStopCallback;
61
+
62
+ let eventSource: Element | Window = initialElement;
63
+
64
+ try {
65
+ initialElement.setPointerCapture(pointerId);
66
+ this._hooks.add(toDisposable(() => {
67
+ try {
68
+ initialElement.releasePointerCapture(pointerId);
69
+ } catch (err) {
70
+ // See https://github.com/microsoft/vscode/issues/161731
71
+ //
72
+ // `releasePointerCapture` sometimes fails when being invoked with the exception:
73
+ // DOMException: Failed to execute 'releasePointerCapture' on 'Element':
74
+ // No active pointer with the given id is found.
75
+ //
76
+ // There's no need to do anything in case of failure
77
+ }
78
+ }));
79
+ } catch (err) {
80
+ // See https://github.com/microsoft/vscode/issues/144584
81
+ // See https://github.com/microsoft/vscode/issues/146947
82
+ // `setPointerCapture` sometimes fails when being invoked
83
+ // from a `mousedown` listener on macOS and Windows
84
+ // and it always fails on Linux with the exception:
85
+ // DOMException: Failed to execute 'setPointerCapture' on 'Element':
86
+ // No active pointer with the given id is found.
87
+ // In case of failure, we bind the listeners on the window
88
+ eventSource = dom.getWindow(initialElement);
89
+ }
90
+
91
+ this._hooks.add(dom.addDisposableListener(
92
+ eventSource,
93
+ dom.EventType.POINTER_MOVE,
94
+ (e) => {
95
+ if (e.buttons !== initialButtons) {
96
+ // Buttons state has changed in the meantime
97
+ this.stopMonitoring(true);
98
+ return;
99
+ }
100
+
101
+ e.preventDefault();
102
+ this._pointerMoveCallback!(e);
103
+ }
104
+ ));
105
+
106
+ this._hooks.add(dom.addDisposableListener(
107
+ eventSource,
108
+ dom.EventType.POINTER_UP,
109
+ (e: PointerEvent) => this.stopMonitoring(true)
110
+ ));
111
+ }
112
+ }
@@ -0,0 +1,135 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License. See License.txt in the project root for license information.
4
+ *--------------------------------------------------------------------------------------------*/
5
+
6
+ /**
7
+ * Represents a window in a possible chain of iframes
8
+ */
9
+ interface IWindowChainElement {
10
+ /**
11
+ * The window object for it
12
+ */
13
+ readonly window: WeakRef<Window>;
14
+ /**
15
+ * The iframe element inside the window.parent corresponding to window
16
+ */
17
+ readonly iframeElement: Element | null;
18
+ }
19
+
20
+ const sameOriginWindowChainCache = new WeakMap<Window, IWindowChainElement[] | null>();
21
+
22
+ function getParentWindowIfSameOrigin(w: Window): Window | null {
23
+ if (!w.parent || w.parent === w) {
24
+ return null;
25
+ }
26
+
27
+ // Cannot really tell if we have access to the parent window unless we try to access something in it
28
+ try {
29
+ const location = w.location;
30
+ const parentLocation = w.parent.location;
31
+ if (location.origin !== 'null' && parentLocation.origin !== 'null' && location.origin !== parentLocation.origin) {
32
+ return null;
33
+ }
34
+ } catch (e) {
35
+ return null;
36
+ }
37
+
38
+ return w.parent;
39
+ }
40
+
41
+ export class IframeUtils {
42
+
43
+ /**
44
+ * Returns a chain of embedded windows with the same origin (which can be accessed programmatically).
45
+ * Having a chain of length 1 might mean that the current execution environment is running outside of an iframe or inside an iframe embedded in a window with a different origin.
46
+ */
47
+ private static getSameOriginWindowChain(targetWindow: Window): IWindowChainElement[] {
48
+ let windowChainCache = sameOriginWindowChainCache.get(targetWindow);
49
+ if (!windowChainCache) {
50
+ windowChainCache = [];
51
+ sameOriginWindowChainCache.set(targetWindow, windowChainCache);
52
+ let w: Window | null = targetWindow;
53
+ let parent: Window | null;
54
+ do {
55
+ parent = getParentWindowIfSameOrigin(w);
56
+ if (parent) {
57
+ windowChainCache.push({
58
+ window: new WeakRef(w),
59
+ iframeElement: w.frameElement || null
60
+ });
61
+ } else {
62
+ windowChainCache.push({
63
+ window: new WeakRef(w),
64
+ iframeElement: null
65
+ });
66
+ }
67
+ w = parent;
68
+ } while (w);
69
+ }
70
+ return windowChainCache.slice(0);
71
+ }
72
+
73
+ /**
74
+ * Returns the position of `childWindow` relative to `ancestorWindow`
75
+ */
76
+ public static getPositionOfChildWindowRelativeToAncestorWindow(childWindow: Window, ancestorWindow: Window | null) {
77
+
78
+ if (!ancestorWindow || childWindow === ancestorWindow) {
79
+ return {
80
+ top: 0,
81
+ left: 0
82
+ };
83
+ }
84
+
85
+ let top = 0, left = 0;
86
+
87
+ const windowChain = this.getSameOriginWindowChain(childWindow);
88
+
89
+ for (const windowChainEl of windowChain) {
90
+ const windowInChain = windowChainEl.window.deref();
91
+ top += windowInChain?.scrollY ?? 0;
92
+ left += windowInChain?.scrollX ?? 0;
93
+
94
+ if (windowInChain === ancestorWindow) {
95
+ break;
96
+ }
97
+
98
+ if (!windowChainEl.iframeElement) {
99
+ break;
100
+ }
101
+
102
+ const boundingRect = windowChainEl.iframeElement.getBoundingClientRect();
103
+ top += boundingRect.top;
104
+ left += boundingRect.left;
105
+ }
106
+
107
+ return {
108
+ top: top,
109
+ left: left
110
+ };
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Returns a sha-256 composed of `parentOrigin` and `salt` converted to base 32
116
+ */
117
+ export async function parentOriginHash(parentOrigin: string, salt: string): Promise<string> {
118
+ // This same code is also inlined at `src/vs/workbench/services/extensions/worker/webWorkerExtensionHostIframe.html`
119
+ if (!crypto.subtle) {
120
+ throw new Error(`'crypto.subtle' is not available so webviews will not work. This is likely because the editor is not running in a secure context (https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts).`);
121
+ }
122
+
123
+ const strData = JSON.stringify({ parentOrigin, salt });
124
+ const encoder = new TextEncoder();
125
+ const arrData = encoder.encode(strData);
126
+ const hash = await crypto.subtle.digest('sha-256', arrData);
127
+ return sha256AsBase32(hash);
128
+ }
129
+
130
+ function sha256AsBase32(bytes: ArrayBuffer): string {
131
+ const array = Array.from(new Uint8Array(bytes));
132
+ const hexArray = array.map(b => b.toString(16).padStart(2, '0')).join('');
133
+ // sha256 has 256 bits, so we need at most ceil(lg(2^256-1)/lg(32)) = 52 chars to represent it in base 32
134
+ return BigInt(`0x${hexArray}`).toString(32).padStart(52, '0');
135
+ }