@discordjs/voice 0.11.0-dev.1654819794-2791c86 → 0.11.0-dev.1654949069-96053ba

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.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { TypedEmitter } from 'tiny-typed-emitter';
1
+ import EventEmitter, { EventEmitter as EventEmitter$1 } from 'node:events';
2
2
  import { Readable, ReadableOptions } from 'node:stream';
3
3
  import prism from 'prism-media';
4
4
  import WebSocket, { MessageEvent } from 'ws';
@@ -209,29 +209,6 @@ declare class AudioPlayerError extends Error {
209
209
  constructor(error: Error, resource: AudioResource);
210
210
  }
211
211
 
212
- /**
213
- * Represents a subscription of a voice connection to an audio player, allowing
214
- * the audio player to play audio on the voice connection.
215
- */
216
- declare class PlayerSubscription {
217
- /**
218
- * The voice connection of this subscription.
219
- */
220
- readonly connection: VoiceConnection;
221
- /**
222
- * The audio player of this subscription.
223
- */
224
- readonly player: AudioPlayer;
225
- constructor(connection: VoiceConnection, player: AudioPlayer);
226
- /**
227
- * Unsubscribes the connection from the audio player, meaning that the
228
- * audio player cannot stream audio to it until a new subscription is made.
229
- */
230
- unsubscribe(): void;
231
- }
232
-
233
- declare type Awaited<T> = T | Promise<T>;
234
-
235
212
  /**
236
213
  * Describes the behavior of the player when an audio packet is played but there are no available
237
214
  * voice connections to play to.
@@ -349,17 +326,14 @@ interface AudioPlayerPausedState {
349
326
  * The various states that the player can be in.
350
327
  */
351
328
  declare type AudioPlayerState = AudioPlayerIdleState | AudioPlayerBufferingState | AudioPlayerPlayingState | AudioPlayerPausedState;
352
- declare type AudioPlayerEvents = {
353
- error: (error: AudioPlayerError) => Awaited<void>;
354
- debug: (message: string) => Awaited<void>;
355
- stateChange: (oldState: AudioPlayerState, newState: AudioPlayerState) => Awaited<void>;
356
- subscribe: (subscription: PlayerSubscription) => Awaited<void>;
357
- unsubscribe: (subscription: PlayerSubscription) => Awaited<void>;
358
- } & {
359
- [status in AudioPlayerStatus]: (oldState: AudioPlayerState, newState: AudioPlayerState & {
360
- status: status;
361
- }) => Awaited<void>;
362
- };
329
+ interface AudioPlayer extends EventEmitter {
330
+ /**
331
+ * Emitted when there is an error emitted from the audio resource played by the audio player
332
+ *
333
+ * @event
334
+ */
335
+ on: (event: 'error', listener: (error: AudioPlayerError) => void) => this;
336
+ }
363
337
  /**
364
338
  * Used to play audio resources (i.e. tracks, streams) to voice connections.
365
339
  *
@@ -370,7 +344,7 @@ declare type AudioPlayerEvents = {
370
344
  * The AudioPlayer drives the timing of playback, and therefore is unaffected by voice connections
371
345
  * becoming unavailable. Its behavior in these scenarios can be configured.
372
346
  */
373
- declare class AudioPlayer extends TypedEmitter<AudioPlayerEvents> {
347
+ declare class AudioPlayer extends EventEmitter {
374
348
  /**
375
349
  * The state that the AudioPlayer is in.
376
350
  */
@@ -502,6 +476,27 @@ declare class AudioPlayer extends TypedEmitter<AudioPlayerEvents> {
502
476
  */
503
477
  declare function createAudioPlayer(options?: CreateAudioPlayerOptions): AudioPlayer;
504
478
 
479
+ /**
480
+ * Represents a subscription of a voice connection to an audio player, allowing
481
+ * the audio player to play audio on the voice connection.
482
+ */
483
+ declare class PlayerSubscription {
484
+ /**
485
+ * The voice connection of this subscription.
486
+ */
487
+ readonly connection: VoiceConnection;
488
+ /**
489
+ * The audio player of this subscription.
490
+ */
491
+ readonly player: AudioPlayer;
492
+ constructor(connection: VoiceConnection, player: AudioPlayer);
493
+ /**
494
+ * Unsubscribes the connection from the audio player, meaning that the
495
+ * audio player cannot stream audio to it until a new subscription is made.
496
+ */
497
+ unsubscribe(): void;
498
+ }
499
+
505
500
  interface JoinConfig {
506
501
  guildId: string;
507
502
  channelId: string | null;
@@ -550,16 +545,10 @@ interface SocketConfig {
550
545
  ip: string;
551
546
  port: number;
552
547
  }
553
- interface VoiceUDPSocketEvents {
554
- error: (error: Error) => Awaited<void>;
555
- close: () => Awaited<void>;
556
- debug: (message: string) => Awaited<void>;
557
- message: (message: Buffer) => Awaited<void>;
558
- }
559
548
  /**
560
549
  * Manages the UDP networking for a voice connection.
561
550
  */
562
- declare class VoiceUDPSocket extends TypedEmitter<VoiceUDPSocketEvents> {
551
+ declare class VoiceUDPSocket extends EventEmitter$1 {
563
552
  /**
564
553
  * The underlying network Socket for the VoiceUDPSocket.
565
554
  */
@@ -626,24 +615,28 @@ declare class VoiceUDPSocket extends TypedEmitter<VoiceUDPSocketEvents> {
626
615
  performIPDiscovery(ssrc: number): Promise<SocketConfig>;
627
616
  }
628
617
 
629
- /**
630
- * Debug event for VoiceWebSocket.
631
- *
632
- * @event VoiceWebSocket#debug
633
- * @type {string}
634
- */
635
- interface VoiceWebSocketEvents {
636
- error: (error: Error) => Awaited<void>;
637
- open: (event: WebSocket.Event) => Awaited<void>;
638
- close: (event: WebSocket.CloseEvent) => Awaited<void>;
639
- debug: (message: string) => Awaited<void>;
640
- packet: (packet: any) => Awaited<void>;
618
+ interface VoiceWebSocket extends EventEmitter$1 {
619
+ on(event: 'error', listener: (error: Error) => void): this;
620
+ on(event: 'open', listener: (event: WebSocket.Event) => void): this;
621
+ on(event: 'close', listener: (event: WebSocket.CloseEvent) => void): this;
622
+ /**
623
+ * Debug event for VoiceWebSocket.
624
+ *
625
+ * @event
626
+ */
627
+ on(event: 'debug', listener: (message: string) => void): this;
628
+ /**
629
+ * Packet event.
630
+ *
631
+ * @event
632
+ */
633
+ on(event: 'packet', listener: (packet: any) => void): this;
641
634
  }
642
635
  /**
643
636
  * An extension of the WebSocket class to provide helper functionality when interacting
644
637
  * with the Discord Voice gateway.
645
638
  */
646
- declare class VoiceWebSocket extends TypedEmitter<VoiceWebSocketEvents> {
639
+ declare class VoiceWebSocket extends EventEmitter$1 {
647
640
  /**
648
641
  * The current heartbeat interval, if any.
649
642
  */
@@ -823,16 +816,21 @@ interface ConnectionData {
823
816
  nonceBuffer: Buffer;
824
817
  speaking: boolean;
825
818
  }
826
- interface NetworkingEvents {
827
- debug: (message: string) => Awaited<void>;
828
- error: (error: Error) => Awaited<void>;
829
- stateChange: (oldState: NetworkingState, newState: NetworkingState) => Awaited<void>;
830
- close: (code: number) => Awaited<void>;
819
+ interface Networking extends EventEmitter$1 {
820
+ /**
821
+ * Debug event for Networking.
822
+ *
823
+ * @event
824
+ */
825
+ on(event: 'debug', listener: (message: string) => void): this;
826
+ on(event: 'error', listener: (error: Error) => void): this;
827
+ on(event: 'stateChange', listener: (oldState: NetworkingState, newState: NetworkingState) => void): this;
828
+ on(event: 'close', listener: (code: number) => void): this;
831
829
  }
832
830
  /**
833
831
  * Manages the networking required to maintain a voice connection and dispatch audio packets
834
832
  */
835
- declare class Networking extends TypedEmitter<NetworkingEvents> {
833
+ declare class Networking extends EventEmitter$1 {
836
834
  private _state;
837
835
  /**
838
836
  * The debug logger function, if debugging is enabled.
@@ -1011,18 +1009,10 @@ interface VoiceUserData {
1011
1009
  */
1012
1010
  userId: string;
1013
1011
  }
1014
- /**
1015
- * The events that an SSRCMap may emit.
1016
- */
1017
- interface SSRCMapEvents {
1018
- create: (newData: VoiceUserData) => Awaited<void>;
1019
- update: (oldData: VoiceUserData | undefined, newData: VoiceUserData) => Awaited<void>;
1020
- delete: (deletedData: VoiceUserData) => Awaited<void>;
1021
- }
1022
1012
  /**
1023
1013
  * Maps audio SSRCs to data of users in voice connections.
1024
1014
  */
1025
- declare class SSRCMap extends TypedEmitter<SSRCMapEvents> {
1015
+ declare class SSRCMap extends EventEmitter$1 {
1026
1016
  /**
1027
1017
  * The underlying map.
1028
1018
  */
@@ -1050,23 +1040,10 @@ declare class SSRCMap extends TypedEmitter<SSRCMapEvents> {
1050
1040
  delete(target: number | string): VoiceUserData | undefined;
1051
1041
  }
1052
1042
 
1053
- /**
1054
- * The events that a SpeakingMap can emit.
1055
- */
1056
- interface SpeakingMapEvents {
1057
- /**
1058
- * Emitted when a user starts speaking.
1059
- */
1060
- start: (userId: string) => Awaited<void>;
1061
- /**
1062
- * Emitted when a user stops speaking.
1063
- */
1064
- end: (userId: string) => Awaited<void>;
1065
- }
1066
1043
  /**
1067
1044
  * Tracks the speaking states of users in a voice channel.
1068
1045
  */
1069
- declare class SpeakingMap extends TypedEmitter<SpeakingMapEvents> {
1046
+ declare class SpeakingMap extends EventEmitter$1 {
1070
1047
  /**
1071
1048
  * The delay after a packet is received from a user until they're marked as not speaking anymore.
1072
1049
  */
@@ -1150,7 +1127,7 @@ declare class VoiceReceiver {
1150
1127
  }
1151
1128
 
1152
1129
  /**
1153
- * Methods that are provided by the @discordjs/voice library to implementations of
1130
+ * Methods that are provided by the \@discordjs/voice library to implementations of
1154
1131
  * Discord gateway DiscordGatewayAdapters.
1155
1132
  */
1156
1133
  interface DiscordGatewayAdapterLibraryMethods {
@@ -1184,7 +1161,7 @@ interface DiscordGatewayAdapterImplementerMethods {
1184
1161
  */
1185
1162
  sendPayload: (payload: any) => boolean;
1186
1163
  /**
1187
- * This will be called by @discordjs/voice when the adapter can safely be destroyed as it will no
1164
+ * This will be called by \@discordjs/voice when the adapter can safely be destroyed as it will no
1188
1165
  * longer be used.
1189
1166
  */
1190
1167
  destroy: () => void;
@@ -1316,19 +1293,10 @@ interface VoiceConnectionDestroyedState {
1316
1293
  * The various states that a voice connection can be in.
1317
1294
  */
1318
1295
  declare type VoiceConnectionState = VoiceConnectionSignallingState | VoiceConnectionDisconnectedState | VoiceConnectionConnectingState | VoiceConnectionReadyState | VoiceConnectionDestroyedState;
1319
- declare type VoiceConnectionEvents = {
1320
- error: (error: Error) => Awaited<void>;
1321
- debug: (message: string) => Awaited<void>;
1322
- stateChange: (oldState: VoiceConnectionState, newState: VoiceConnectionState) => Awaited<void>;
1323
- } & {
1324
- [status in VoiceConnectionStatus]: (oldState: VoiceConnectionState, newState: VoiceConnectionState & {
1325
- status: status;
1326
- }) => Awaited<void>;
1327
- };
1328
1296
  /**
1329
1297
  * A connection to the voice server of a Guild, can be used to play audio in voice channels.
1330
1298
  */
1331
- declare class VoiceConnection extends TypedEmitter<VoiceConnectionEvents> {
1299
+ declare class VoiceConnection extends EventEmitter$1 {
1332
1300
  /**
1333
1301
  * The number of consecutive rejoin attempts. Initially 0, and increments for each rejoin.
1334
1302
  * When a connection is successfully established, it resets to 0.
@@ -1614,4 +1582,4 @@ interface ProbeInfo {
1614
1582
  */
1615
1583
  declare function demuxProbe(stream: Readable, probeSize?: number, validator?: typeof validateDiscordOpusHead): Promise<ProbeInfo>;
1616
1584
 
1617
- export { AudioPlayer, AudioPlayerBufferingState, AudioPlayerError, AudioPlayerEvents, AudioPlayerIdleState, AudioPlayerPausedState, AudioPlayerPlayingState, AudioPlayerState, AudioPlayerStatus, AudioReceiveStream, AudioReceiveStreamOptions, AudioResource, CreateAudioPlayerOptions, CreateAudioResourceOptions, CreateVoiceConnectionOptions, DiscordGatewayAdapterCreator, DiscordGatewayAdapterImplementerMethods, DiscordGatewayAdapterLibraryMethods, EndBehavior, EndBehaviorType, JoinConfig, JoinVoiceChannelOptions, NoSubscriberBehavior, PlayerSubscription, ProbeInfo, SSRCMap, SSRCMapEvents, SpeakingMap, SpeakingMapEvents, StreamType, VoiceConnection, VoiceConnectionConnectingState, VoiceConnectionDestroyedState, VoiceConnectionDisconnectReason, VoiceConnectionDisconnectedBaseState, VoiceConnectionDisconnectedOtherState, VoiceConnectionDisconnectedState, VoiceConnectionDisconnectedWebSocketState, VoiceConnectionEvents, VoiceConnectionReadyState, VoiceConnectionSignallingState, VoiceConnectionState, VoiceConnectionStatus, VoiceReceiver, VoiceUserData, createAudioPlayer, createAudioResource, createDefaultAudioReceiveStreamOptions, demuxProbe, entersState, generateDependencyReport, getGroups, getVoiceConnection, getVoiceConnections, joinVoiceChannel, validateDiscordOpusHead };
1585
+ export { AudioPlayer, AudioPlayerBufferingState, AudioPlayerError, AudioPlayerIdleState, AudioPlayerPausedState, AudioPlayerPlayingState, AudioPlayerState, AudioPlayerStatus, AudioReceiveStream, AudioReceiveStreamOptions, AudioResource, CreateAudioPlayerOptions, CreateAudioResourceOptions, CreateVoiceConnectionOptions, DiscordGatewayAdapterCreator, DiscordGatewayAdapterImplementerMethods, DiscordGatewayAdapterLibraryMethods, EndBehavior, EndBehaviorType, JoinConfig, JoinVoiceChannelOptions, NoSubscriberBehavior, PlayerSubscription, ProbeInfo, SSRCMap, SpeakingMap, StreamType, VoiceConnection, VoiceConnectionConnectingState, VoiceConnectionDestroyedState, VoiceConnectionDisconnectReason, VoiceConnectionDisconnectedBaseState, VoiceConnectionDisconnectedOtherState, VoiceConnectionDisconnectedState, VoiceConnectionDisconnectedWebSocketState, VoiceConnectionReadyState, VoiceConnectionSignallingState, VoiceConnectionState, VoiceConnectionStatus, VoiceReceiver, VoiceUserData, createAudioPlayer, createAudioResource, createDefaultAudioReceiveStreamOptions, demuxProbe, entersState, generateDependencyReport, getGroups, getVoiceConnection, getVoiceConnections, joinVoiceChannel, validateDiscordOpusHead };
package/dist/index.js CHANGED
@@ -86,11 +86,10 @@ var require_package = __commonJS({
86
86
  homepage: "https://discord.js.org",
87
87
  dependencies: {
88
88
  "@types/ws": "^8.5.3",
89
- "discord-api-types": "^0.33.4",
89
+ "discord-api-types": "^0.33.5",
90
90
  "prism-media": "^1.3.2",
91
- "tiny-typed-emitter": "^2.1.0",
92
91
  tslib: "^2.4.0",
93
- ws: "^8.7.0"
92
+ ws: "^8.8.0"
94
93
  },
95
94
  devDependencies: {
96
95
  "@babel/core": "^7.18.2",
@@ -100,7 +99,7 @@ var require_package = __commonJS({
100
99
  "@discordjs/scripts": "workspace:^",
101
100
  "@favware/cliff-jumper": "^1.8.3",
102
101
  "@types/jest": "^28.1.1",
103
- "@types/node": "^16.11.38",
102
+ "@types/node": "^16.11.39",
104
103
  "@typescript-eslint/eslint-plugin": "^5.27.1",
105
104
  "@typescript-eslint/parser": "^5.27.1",
106
105
  eslint: "^8.17.0",
@@ -108,9 +107,9 @@ var require_package = __commonJS({
108
107
  "eslint-config-prettier": "^8.5.0",
109
108
  "eslint-import-resolver-typescript": "^2.7.1",
110
109
  "eslint-plugin-import": "^2.26.0",
111
- jest: "^28.1.0",
110
+ jest: "^28.1.1",
112
111
  "jest-websocket-mock": "^2.3.0",
113
- "mock-socket": "^9.1.4",
112
+ "mock-socket": "^9.1.5",
114
113
  prettier: "^2.6.2",
115
114
  tsup: "^6.1.0",
116
115
  tweetnacl: "^1.0.3",
@@ -159,7 +158,7 @@ __export(src_exports, {
159
158
  module.exports = __toCommonJS(src_exports);
160
159
 
161
160
  // src/VoiceConnection.ts
162
- var import_tiny_typed_emitter7 = require("tiny-typed-emitter");
161
+ var import_node_events7 = require("events");
163
162
 
164
163
  // src/DataStore.ts
165
164
  var import_v10 = require("discord-api-types/v10");
@@ -260,13 +259,13 @@ function deleteAudioPlayer(player) {
260
259
  __name(deleteAudioPlayer, "deleteAudioPlayer");
261
260
 
262
261
  // src/networking/Networking.ts
262
+ var import_node_events3 = require("events");
263
263
  var import_v42 = require("discord-api-types/voice/v4");
264
- var import_tiny_typed_emitter3 = require("tiny-typed-emitter");
265
264
 
266
265
  // src/networking/VoiceUDPSocket.ts
267
266
  var import_node_dgram = require("dgram");
267
+ var import_node_events = require("events");
268
268
  var import_node_net = require("net");
269
- var import_tiny_typed_emitter = require("tiny-typed-emitter");
270
269
  function parseLocalPacket(message) {
271
270
  const packet = Buffer.from(message);
272
271
  const ip = packet.slice(8, packet.indexOf(0, 8)).toString("utf-8");
@@ -280,7 +279,7 @@ __name(parseLocalPacket, "parseLocalPacket");
280
279
  var KEEP_ALIVE_INTERVAL = 5e3;
281
280
  var KEEP_ALIVE_LIMIT = 12;
282
281
  var MAX_COUNTER_VALUE = 2 ** 32 - 1;
283
- var VoiceUDPSocket = class extends import_tiny_typed_emitter.TypedEmitter {
282
+ var VoiceUDPSocket = class extends import_node_events.EventEmitter {
284
283
  constructor(remote, debug = false) {
285
284
  super();
286
285
  __publicField(this, "socket");
@@ -365,10 +364,10 @@ var VoiceUDPSocket = class extends import_tiny_typed_emitter.TypedEmitter {
365
364
  __name(VoiceUDPSocket, "VoiceUDPSocket");
366
365
 
367
366
  // src/networking/VoiceWebSocket.ts
367
+ var import_node_events2 = require("events");
368
368
  var import_v4 = require("discord-api-types/voice/v4");
369
- var import_tiny_typed_emitter2 = require("tiny-typed-emitter");
370
369
  var import_ws = __toESM(require("ws"));
371
- var VoiceWebSocket = class extends import_tiny_typed_emitter2.TypedEmitter {
370
+ var VoiceWebSocket = class extends import_node_events2.EventEmitter {
372
371
  constructor(address, debug) {
373
372
  super();
374
373
  __publicField(this, "heartbeatInterval");
@@ -545,7 +544,7 @@ function randomNBit(n) {
545
544
  return Math.floor(Math.random() * 2 ** n);
546
545
  }
547
546
  __name(randomNBit, "randomNBit");
548
- var Networking = class extends import_tiny_typed_emitter3.TypedEmitter {
547
+ var Networking = class extends import_node_events3.EventEmitter {
549
548
  constructor(options, debug) {
550
549
  super();
551
550
  __publicField(this, "_state");
@@ -816,7 +815,7 @@ var import_v43 = require("discord-api-types/voice/v4");
816
815
  var import_node_stream = require("stream");
817
816
 
818
817
  // src/audio/AudioPlayer.ts
819
- var import_tiny_typed_emitter4 = require("tiny-typed-emitter");
818
+ var import_node_events4 = __toESM(require("events"));
820
819
 
821
820
  // src/audio/AudioPlayerError.ts
822
821
  var AudioPlayerError = class extends Error {
@@ -869,7 +868,7 @@ function stringifyState2(state) {
869
868
  });
870
869
  }
871
870
  __name(stringifyState2, "stringifyState");
872
- var AudioPlayer = class extends import_tiny_typed_emitter4.TypedEmitter {
871
+ var AudioPlayer = class extends import_node_events4.default {
873
872
  constructor(options = {}) {
874
873
  super();
875
874
  __publicField(this, "_state");
@@ -1162,8 +1161,8 @@ var AudioReceiveStream = class extends import_node_stream.Readable {
1162
1161
  __name(AudioReceiveStream, "AudioReceiveStream");
1163
1162
 
1164
1163
  // src/receive/SSRCMap.ts
1165
- var import_tiny_typed_emitter5 = require("tiny-typed-emitter");
1166
- var SSRCMap = class extends import_tiny_typed_emitter5.TypedEmitter {
1164
+ var import_node_events5 = require("events");
1165
+ var SSRCMap = class extends import_node_events5.EventEmitter {
1167
1166
  constructor() {
1168
1167
  super();
1169
1168
  __publicField(this, "map");
@@ -1213,8 +1212,8 @@ var SSRCMap = class extends import_tiny_typed_emitter5.TypedEmitter {
1213
1212
  __name(SSRCMap, "SSRCMap");
1214
1213
 
1215
1214
  // src/receive/SpeakingMap.ts
1216
- var import_tiny_typed_emitter6 = require("tiny-typed-emitter");
1217
- var _SpeakingMap = class extends import_tiny_typed_emitter6.TypedEmitter {
1215
+ var import_node_events6 = require("events");
1216
+ var _SpeakingMap = class extends import_node_events6.EventEmitter {
1218
1217
  constructor() {
1219
1218
  super();
1220
1219
  __publicField(this, "users");
@@ -1361,7 +1360,7 @@ var VoiceConnectionDisconnectReason = /* @__PURE__ */ ((VoiceConnectionDisconnec
1361
1360
  VoiceConnectionDisconnectReason2[VoiceConnectionDisconnectReason2["Manual"] = 3] = "Manual";
1362
1361
  return VoiceConnectionDisconnectReason2;
1363
1362
  })(VoiceConnectionDisconnectReason || {});
1364
- var VoiceConnection2 = class extends import_tiny_typed_emitter7.TypedEmitter {
1363
+ var VoiceConnection2 = class extends import_node_events7.EventEmitter {
1365
1364
  constructor(joinConfig, { debug, adapterCreator }) {
1366
1365
  super();
1367
1366
  __publicField(this, "rejoinAttempts");
@@ -1999,7 +1998,7 @@ function generateDependencyReport() {
1999
1998
  __name(generateDependencyReport, "generateDependencyReport");
2000
1999
 
2001
2000
  // src/util/entersState.ts
2002
- var import_node_events = require("events");
2001
+ var import_node_events8 = require("events");
2003
2002
 
2004
2003
  // src/util/abortAfter.ts
2005
2004
  function abortAfter(delay) {
@@ -2015,7 +2014,7 @@ async function entersState(target, status, timeoutOrSignal) {
2015
2014
  if (target.state.status !== status) {
2016
2015
  const [ac, signal] = typeof timeoutOrSignal === "number" ? abortAfter(timeoutOrSignal) : [void 0, timeoutOrSignal];
2017
2016
  try {
2018
- await (0, import_node_events.once)(target, status, { signal });
2017
+ await (0, import_node_events8.once)(target, status, { signal });
2019
2018
  } finally {
2020
2019
  ac?.abort();
2021
2020
  }