@xterm/xterm 5.4.0-beta.1

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 (108) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +235 -0
  3. package/css/xterm.css +209 -0
  4. package/lib/xterm.js +2 -0
  5. package/lib/xterm.js.map +1 -0
  6. package/package.json +101 -0
  7. package/src/browser/AccessibilityManager.ts +278 -0
  8. package/src/browser/Clipboard.ts +93 -0
  9. package/src/browser/ColorContrastCache.ts +34 -0
  10. package/src/browser/Lifecycle.ts +33 -0
  11. package/src/browser/Linkifier2.ts +416 -0
  12. package/src/browser/LocalizableStrings.ts +12 -0
  13. package/src/browser/OscLinkProvider.ts +128 -0
  14. package/src/browser/RenderDebouncer.ts +83 -0
  15. package/src/browser/Terminal.ts +1317 -0
  16. package/src/browser/TimeBasedDebouncer.ts +86 -0
  17. package/src/browser/Types.d.ts +181 -0
  18. package/src/browser/Viewport.ts +401 -0
  19. package/src/browser/decorations/BufferDecorationRenderer.ts +134 -0
  20. package/src/browser/decorations/ColorZoneStore.ts +117 -0
  21. package/src/browser/decorations/OverviewRulerRenderer.ts +218 -0
  22. package/src/browser/input/CompositionHelper.ts +246 -0
  23. package/src/browser/input/Mouse.ts +54 -0
  24. package/src/browser/input/MoveToCell.ts +249 -0
  25. package/src/browser/public/Terminal.ts +260 -0
  26. package/src/browser/renderer/dom/DomRenderer.ts +509 -0
  27. package/src/browser/renderer/dom/DomRendererRowFactory.ts +526 -0
  28. package/src/browser/renderer/dom/WidthCache.ts +160 -0
  29. package/src/browser/renderer/shared/CellColorResolver.ts +137 -0
  30. package/src/browser/renderer/shared/CharAtlasCache.ts +96 -0
  31. package/src/browser/renderer/shared/CharAtlasUtils.ts +75 -0
  32. package/src/browser/renderer/shared/Constants.ts +14 -0
  33. package/src/browser/renderer/shared/CursorBlinkStateManager.ts +146 -0
  34. package/src/browser/renderer/shared/CustomGlyphs.ts +687 -0
  35. package/src/browser/renderer/shared/DevicePixelObserver.ts +41 -0
  36. package/src/browser/renderer/shared/README.md +1 -0
  37. package/src/browser/renderer/shared/RendererUtils.ts +58 -0
  38. package/src/browser/renderer/shared/SelectionRenderModel.ts +91 -0
  39. package/src/browser/renderer/shared/TextureAtlas.ts +1082 -0
  40. package/src/browser/renderer/shared/Types.d.ts +173 -0
  41. package/src/browser/selection/SelectionModel.ts +144 -0
  42. package/src/browser/selection/Types.d.ts +15 -0
  43. package/src/browser/services/CharSizeService.ts +102 -0
  44. package/src/browser/services/CharacterJoinerService.ts +339 -0
  45. package/src/browser/services/CoreBrowserService.ts +137 -0
  46. package/src/browser/services/MouseService.ts +46 -0
  47. package/src/browser/services/RenderService.ts +279 -0
  48. package/src/browser/services/SelectionService.ts +1031 -0
  49. package/src/browser/services/Services.ts +147 -0
  50. package/src/browser/services/ThemeService.ts +237 -0
  51. package/src/common/CircularList.ts +241 -0
  52. package/src/common/Clone.ts +23 -0
  53. package/src/common/Color.ts +357 -0
  54. package/src/common/CoreTerminal.ts +284 -0
  55. package/src/common/EventEmitter.ts +78 -0
  56. package/src/common/InputHandler.ts +3461 -0
  57. package/src/common/Lifecycle.ts +108 -0
  58. package/src/common/MultiKeyMap.ts +42 -0
  59. package/src/common/Platform.ts +44 -0
  60. package/src/common/SortedList.ts +118 -0
  61. package/src/common/TaskQueue.ts +166 -0
  62. package/src/common/TypedArrayUtils.ts +17 -0
  63. package/src/common/Types.d.ts +553 -0
  64. package/src/common/WindowsMode.ts +27 -0
  65. package/src/common/buffer/AttributeData.ts +196 -0
  66. package/src/common/buffer/Buffer.ts +654 -0
  67. package/src/common/buffer/BufferLine.ts +524 -0
  68. package/src/common/buffer/BufferRange.ts +13 -0
  69. package/src/common/buffer/BufferReflow.ts +223 -0
  70. package/src/common/buffer/BufferSet.ts +134 -0
  71. package/src/common/buffer/CellData.ts +94 -0
  72. package/src/common/buffer/Constants.ts +149 -0
  73. package/src/common/buffer/Marker.ts +43 -0
  74. package/src/common/buffer/Types.d.ts +52 -0
  75. package/src/common/data/Charsets.ts +256 -0
  76. package/src/common/data/EscapeSequences.ts +153 -0
  77. package/src/common/input/Keyboard.ts +398 -0
  78. package/src/common/input/TextDecoder.ts +346 -0
  79. package/src/common/input/UnicodeV6.ts +145 -0
  80. package/src/common/input/WriteBuffer.ts +246 -0
  81. package/src/common/input/XParseColor.ts +80 -0
  82. package/src/common/parser/Constants.ts +58 -0
  83. package/src/common/parser/DcsParser.ts +192 -0
  84. package/src/common/parser/EscapeSequenceParser.ts +792 -0
  85. package/src/common/parser/OscParser.ts +238 -0
  86. package/src/common/parser/Params.ts +229 -0
  87. package/src/common/parser/Types.d.ts +275 -0
  88. package/src/common/public/AddonManager.ts +53 -0
  89. package/src/common/public/BufferApiView.ts +35 -0
  90. package/src/common/public/BufferLineApiView.ts +29 -0
  91. package/src/common/public/BufferNamespaceApi.ts +36 -0
  92. package/src/common/public/ParserApi.ts +37 -0
  93. package/src/common/public/UnicodeApi.ts +27 -0
  94. package/src/common/services/BufferService.ts +151 -0
  95. package/src/common/services/CharsetService.ts +34 -0
  96. package/src/common/services/CoreMouseService.ts +318 -0
  97. package/src/common/services/CoreService.ts +87 -0
  98. package/src/common/services/DecorationService.ts +140 -0
  99. package/src/common/services/InstantiationService.ts +85 -0
  100. package/src/common/services/LogService.ts +124 -0
  101. package/src/common/services/OptionsService.ts +202 -0
  102. package/src/common/services/OscLinkService.ts +115 -0
  103. package/src/common/services/ServiceRegistry.ts +49 -0
  104. package/src/common/services/Services.ts +373 -0
  105. package/src/common/services/UnicodeService.ts +111 -0
  106. package/src/headless/Terminal.ts +136 -0
  107. package/src/headless/public/Terminal.ts +195 -0
  108. package/typings/xterm.d.ts +1857 -0
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Copyright (c) 2018 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { IDisposable } from 'common/Types';
7
+
8
+ /**
9
+ * A base class that can be extended to provide convenience methods for managing the lifecycle of an
10
+ * object and its components.
11
+ */
12
+ export abstract class Disposable implements IDisposable {
13
+ protected _disposables: IDisposable[] = [];
14
+ protected _isDisposed: boolean = false;
15
+
16
+ /**
17
+ * Disposes the object, triggering the `dispose` method on all registered IDisposables.
18
+ */
19
+ public dispose(): void {
20
+ this._isDisposed = true;
21
+ for (const d of this._disposables) {
22
+ d.dispose();
23
+ }
24
+ this._disposables.length = 0;
25
+ }
26
+
27
+ /**
28
+ * Registers a disposable object.
29
+ * @param d The disposable to register.
30
+ * @returns The disposable.
31
+ */
32
+ public register<T extends IDisposable>(d: T): T {
33
+ this._disposables.push(d);
34
+ return d;
35
+ }
36
+
37
+ /**
38
+ * Unregisters a disposable object if it has been registered, if not do
39
+ * nothing.
40
+ * @param d The disposable to unregister.
41
+ */
42
+ public unregister<T extends IDisposable>(d: T): void {
43
+ const index = this._disposables.indexOf(d);
44
+ if (index !== -1) {
45
+ this._disposables.splice(index, 1);
46
+ }
47
+ }
48
+ }
49
+
50
+ export class MutableDisposable<T extends IDisposable> implements IDisposable {
51
+ private _value?: T;
52
+ private _isDisposed = false;
53
+
54
+ /**
55
+ * Gets the value if it exists.
56
+ */
57
+ public get value(): T | undefined {
58
+ return this._isDisposed ? undefined : this._value;
59
+ }
60
+
61
+ /**
62
+ * Sets the value, disposing of the old value if it exists.
63
+ */
64
+ public set value(value: T | undefined) {
65
+ if (this._isDisposed || value === this._value) {
66
+ return;
67
+ }
68
+ this._value?.dispose();
69
+ this._value = value;
70
+ }
71
+
72
+ /**
73
+ * Resets the stored value and disposes of the previously stored value.
74
+ */
75
+ public clear(): void {
76
+ this.value = undefined;
77
+ }
78
+
79
+ public dispose(): void {
80
+ this._isDisposed = true;
81
+ this._value?.dispose();
82
+ this._value = undefined;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Wrap a function in a disposable.
88
+ */
89
+ export function toDisposable(f: () => void): IDisposable {
90
+ return { dispose: f };
91
+ }
92
+
93
+ /**
94
+ * Dispose of all disposables in an array and set its length to 0.
95
+ */
96
+ export function disposeArray(disposables: IDisposable[]): void {
97
+ for (const d of disposables) {
98
+ d.dispose();
99
+ }
100
+ disposables.length = 0;
101
+ }
102
+
103
+ /**
104
+ * Creates a disposable that will dispose of an array of disposables when disposed.
105
+ */
106
+ export function getDisposeArrayDisposable(array: IDisposable[]): IDisposable {
107
+ return { dispose: () => disposeArray(array) };
108
+ }
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Copyright (c) 2022 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ export class TwoKeyMap<TFirst extends string | number, TSecond extends string | number, TValue> {
7
+ private _data: { [bg: string | number]: { [fg: string | number]: TValue | undefined } | undefined } = {};
8
+
9
+ public set(first: TFirst, second: TSecond, value: TValue): void {
10
+ if (!this._data[first]) {
11
+ this._data[first] = {};
12
+ }
13
+ this._data[first as string | number]![second] = value;
14
+ }
15
+
16
+ public get(first: TFirst, second: TSecond): TValue | undefined {
17
+ return this._data[first as string | number] ? this._data[first as string | number]![second] : undefined;
18
+ }
19
+
20
+ public clear(): void {
21
+ this._data = {};
22
+ }
23
+ }
24
+
25
+ export class FourKeyMap<TFirst extends string | number, TSecond extends string | number, TThird extends string | number, TFourth extends string | number, TValue> {
26
+ private _data: TwoKeyMap<TFirst, TSecond, TwoKeyMap<TThird, TFourth, TValue>> = new TwoKeyMap();
27
+
28
+ public set(first: TFirst, second: TSecond, third: TThird, fourth: TFourth, value: TValue): void {
29
+ if (!this._data.get(first, second)) {
30
+ this._data.set(first, second, new TwoKeyMap());
31
+ }
32
+ this._data.get(first, second)!.set(third, fourth, value);
33
+ }
34
+
35
+ public get(first: TFirst, second: TSecond, third: TThird, fourth: TFourth): TValue | undefined {
36
+ return this._data.get(first, second)?.get(third, fourth);
37
+ }
38
+
39
+ public clear(): void {
40
+ this._data.clear();
41
+ }
42
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Copyright (c) 2016 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ interface INavigator {
7
+ userAgent: string;
8
+ language: string;
9
+ platform: string;
10
+ }
11
+
12
+ // We're declaring a navigator global here as we expect it in all runtimes (node and browser), but
13
+ // we want this module to live in common.
14
+ declare const navigator: INavigator;
15
+ declare const process: unknown;
16
+
17
+ export const isNode = (typeof process !== 'undefined') ? true : false;
18
+ const userAgent = (isNode) ? 'node' : navigator.userAgent;
19
+ const platform = (isNode) ? 'node' : navigator.platform;
20
+
21
+ export const isFirefox = userAgent.includes('Firefox');
22
+ export const isLegacyEdge = userAgent.includes('Edge');
23
+ export const isSafari = /^((?!chrome|android).)*safari/i.test(userAgent);
24
+ export function getSafariVersion(): number {
25
+ if (!isSafari) {
26
+ return 0;
27
+ }
28
+ const majorVersion = userAgent.match(/Version\/(\d+)/);
29
+ if (majorVersion === null || majorVersion.length < 2) {
30
+ return 0;
31
+ }
32
+ return parseInt(majorVersion[1]);
33
+ }
34
+
35
+ // Find the users platform. We use this to interpret the meta key
36
+ // and ISO third level shifts.
37
+ // http://stackoverflow.com/q/19877924/577598
38
+ export const isMac = ['Macintosh', 'MacIntel', 'MacPPC', 'Mac68K'].includes(platform);
39
+ export const isIpad = platform === 'iPad';
40
+ export const isIphone = platform === 'iPhone';
41
+ export const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].includes(platform);
42
+ export const isLinux = platform.indexOf('Linux') >= 0;
43
+ // Note that when this is true, isLinux will also be true.
44
+ export const isChromeOS = /\bCrOS\b/.test(userAgent);
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Copyright (c) 2022 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ // Work variables to avoid garbage collection.
7
+ let i = 0;
8
+
9
+ /**
10
+ * A generic list that is maintained in sorted order and allows values with duplicate keys. This
11
+ * list is based on binary search and as such locating a key will take O(log n) amortized, this
12
+ * includes the by key iterator.
13
+ */
14
+ export class SortedList<T> {
15
+ private readonly _array: T[] = [];
16
+
17
+ constructor(
18
+ private readonly _getKey: (value: T) => number
19
+ ) {
20
+ }
21
+
22
+ public clear(): void {
23
+ this._array.length = 0;
24
+ }
25
+
26
+ public insert(value: T): void {
27
+ if (this._array.length === 0) {
28
+ this._array.push(value);
29
+ return;
30
+ }
31
+ i = this._search(this._getKey(value));
32
+ this._array.splice(i, 0, value);
33
+ }
34
+
35
+ public delete(value: T): boolean {
36
+ if (this._array.length === 0) {
37
+ return false;
38
+ }
39
+ const key = this._getKey(value);
40
+ if (key === undefined) {
41
+ return false;
42
+ }
43
+ i = this._search(key);
44
+ if (i === -1) {
45
+ return false;
46
+ }
47
+ if (this._getKey(this._array[i]) !== key) {
48
+ return false;
49
+ }
50
+ do {
51
+ if (this._array[i] === value) {
52
+ this._array.splice(i, 1);
53
+ return true;
54
+ }
55
+ } while (++i < this._array.length && this._getKey(this._array[i]) === key);
56
+ return false;
57
+ }
58
+
59
+ public *getKeyIterator(key: number): IterableIterator<T> {
60
+ if (this._array.length === 0) {
61
+ return;
62
+ }
63
+ i = this._search(key);
64
+ if (i < 0 || i >= this._array.length) {
65
+ return;
66
+ }
67
+ if (this._getKey(this._array[i]) !== key) {
68
+ return;
69
+ }
70
+ do {
71
+ yield this._array[i];
72
+ } while (++i < this._array.length && this._getKey(this._array[i]) === key);
73
+ }
74
+
75
+ public forEachByKey(key: number, callback: (value: T) => void): void {
76
+ if (this._array.length === 0) {
77
+ return;
78
+ }
79
+ i = this._search(key);
80
+ if (i < 0 || i >= this._array.length) {
81
+ return;
82
+ }
83
+ if (this._getKey(this._array[i]) !== key) {
84
+ return;
85
+ }
86
+ do {
87
+ callback(this._array[i]);
88
+ } while (++i < this._array.length && this._getKey(this._array[i]) === key);
89
+ }
90
+
91
+ public values(): IterableIterator<T> {
92
+ // Duplicate the array to avoid issues when _array changes while iterating
93
+ return [...this._array].values();
94
+ }
95
+
96
+ private _search(key: number): number {
97
+ let min = 0;
98
+ let max = this._array.length - 1;
99
+ while (max >= min) {
100
+ let mid = (min + max) >> 1;
101
+ const midKey = this._getKey(this._array[mid]);
102
+ if (midKey > key) {
103
+ max = mid - 1;
104
+ } else if (midKey < key) {
105
+ min = mid + 1;
106
+ } else {
107
+ // key in list, walk to lowest duplicate
108
+ while (mid > 0 && this._getKey(this._array[mid - 1]) === key) {
109
+ mid--;
110
+ }
111
+ return mid;
112
+ }
113
+ }
114
+ // key not in list
115
+ // still return closest min (also used as insert position)
116
+ return min;
117
+ }
118
+ }
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Copyright (c) 2022 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { isNode } from 'common/Platform';
7
+
8
+ interface ITaskQueue {
9
+ /**
10
+ * Adds a task to the queue which will run in a future idle callback.
11
+ * To avoid perceivable stalls on the mainthread, tasks with heavy workload
12
+ * should split their work into smaller pieces and return `true` to get
13
+ * called again until the work is done (on falsy return value).
14
+ */
15
+ enqueue(task: () => boolean | void): void;
16
+
17
+ /**
18
+ * Flushes the queue, running all remaining tasks synchronously.
19
+ */
20
+ flush(): void;
21
+
22
+ /**
23
+ * Clears any remaining tasks from the queue, these will not be run.
24
+ */
25
+ clear(): void;
26
+ }
27
+
28
+ interface ITaskDeadline {
29
+ timeRemaining(): number;
30
+ }
31
+ type CallbackWithDeadline = (deadline: ITaskDeadline) => void;
32
+
33
+ abstract class TaskQueue implements ITaskQueue {
34
+ private _tasks: (() => boolean | void)[] = [];
35
+ private _idleCallback?: number;
36
+ private _i = 0;
37
+
38
+ protected abstract _requestCallback(callback: CallbackWithDeadline): number;
39
+ protected abstract _cancelCallback(identifier: number): void;
40
+
41
+ public enqueue(task: () => boolean | void): void {
42
+ this._tasks.push(task);
43
+ this._start();
44
+ }
45
+
46
+ public flush(): void {
47
+ while (this._i < this._tasks.length) {
48
+ if (!this._tasks[this._i]()) {
49
+ this._i++;
50
+ }
51
+ }
52
+ this.clear();
53
+ }
54
+
55
+ public clear(): void {
56
+ if (this._idleCallback) {
57
+ this._cancelCallback(this._idleCallback);
58
+ this._idleCallback = undefined;
59
+ }
60
+ this._i = 0;
61
+ this._tasks.length = 0;
62
+ }
63
+
64
+ private _start(): void {
65
+ if (!this._idleCallback) {
66
+ this._idleCallback = this._requestCallback(this._process.bind(this));
67
+ }
68
+ }
69
+
70
+ private _process(deadline: ITaskDeadline): void {
71
+ this._idleCallback = undefined;
72
+ let taskDuration = 0;
73
+ let longestTask = 0;
74
+ let lastDeadlineRemaining = deadline.timeRemaining();
75
+ let deadlineRemaining = 0;
76
+ while (this._i < this._tasks.length) {
77
+ taskDuration = Date.now();
78
+ if (!this._tasks[this._i]()) {
79
+ this._i++;
80
+ }
81
+ // other than performance.now, Date.now might not be stable (changes on wall clock changes),
82
+ // this is not an issue here as a clock change during a short running task is very unlikely
83
+ // in case it still happened and leads to negative duration, simply assume 1 msec
84
+ taskDuration = Math.max(1, Date.now() - taskDuration);
85
+ longestTask = Math.max(taskDuration, longestTask);
86
+ // Guess the following task will take a similar time to the longest task in this batch, allow
87
+ // additional room to try avoid exceeding the deadline
88
+ deadlineRemaining = deadline.timeRemaining();
89
+ if (longestTask * 1.5 > deadlineRemaining) {
90
+ // Warn when the time exceeding the deadline is over 20ms, if this happens in practice the
91
+ // task should be split into sub-tasks to ensure the UI remains responsive.
92
+ if (lastDeadlineRemaining - taskDuration < -20) {
93
+ console.warn(`task queue exceeded allotted deadline by ${Math.abs(Math.round(lastDeadlineRemaining - taskDuration))}ms`);
94
+ }
95
+ this._start();
96
+ return;
97
+ }
98
+ lastDeadlineRemaining = deadlineRemaining;
99
+ }
100
+ this.clear();
101
+ }
102
+ }
103
+
104
+ /**
105
+ * A queue of that runs tasks over several tasks via setTimeout, trying to maintain above 60 frames
106
+ * per second. The tasks will run in the order they are enqueued, but they will run some time later,
107
+ * and care should be taken to ensure they're non-urgent and will not introduce race conditions.
108
+ */
109
+ export class PriorityTaskQueue extends TaskQueue {
110
+ protected _requestCallback(callback: CallbackWithDeadline): number {
111
+ return setTimeout(() => callback(this._createDeadline(16)));
112
+ }
113
+
114
+ protected _cancelCallback(identifier: number): void {
115
+ clearTimeout(identifier);
116
+ }
117
+
118
+ private _createDeadline(duration: number): ITaskDeadline {
119
+ const end = Date.now() + duration;
120
+ return {
121
+ timeRemaining: () => Math.max(0, end - Date.now())
122
+ };
123
+ }
124
+ }
125
+
126
+ class IdleTaskQueueInternal extends TaskQueue {
127
+ protected _requestCallback(callback: IdleRequestCallback): number {
128
+ return requestIdleCallback(callback);
129
+ }
130
+
131
+ protected _cancelCallback(identifier: number): void {
132
+ cancelIdleCallback(identifier);
133
+ }
134
+ }
135
+
136
+ /**
137
+ * A queue of that runs tasks over several idle callbacks, trying to respect the idle callback's
138
+ * deadline given by the environment. The tasks will run in the order they are enqueued, but they
139
+ * will run some time later, and care should be taken to ensure they're non-urgent and will not
140
+ * introduce race conditions.
141
+ *
142
+ * This reverts to a {@link PriorityTaskQueue} if the environment does not support idle callbacks.
143
+ */
144
+ // eslint-disable-next-line @typescript-eslint/naming-convention
145
+ export const IdleTaskQueue = (!isNode && 'requestIdleCallback' in window) ? IdleTaskQueueInternal : PriorityTaskQueue;
146
+
147
+ /**
148
+ * An object that tracks a single debounced task that will run on the next idle frame. When called
149
+ * multiple times, only the last set task will run.
150
+ */
151
+ export class DebouncedIdleTask {
152
+ private _queue: ITaskQueue;
153
+
154
+ constructor() {
155
+ this._queue = new IdleTaskQueue();
156
+ }
157
+
158
+ public set(task: () => boolean | void): void {
159
+ this._queue.clear();
160
+ this._queue.enqueue(task);
161
+ }
162
+
163
+ public flush(): void {
164
+ this._queue.flush();
165
+ }
166
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Copyright (c) 2018 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ export type TypedArray = Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Int8Array | Int16Array | Int32Array | Float32Array | Float64Array;
7
+
8
+ /**
9
+ * Concat two typed arrays `a` and `b`.
10
+ * Returns a new typed array.
11
+ */
12
+ export function concat<T extends TypedArray>(a: T, b: T): T {
13
+ const result = new (a.constructor as any)(a.length + b.length);
14
+ result.set(a);
15
+ result.set(b, a.length);
16
+ return result;
17
+ }