Procházet zdrojové kódy

chore(*) fix sue of isNaN

- It can throw exceptions
- It doesn't return false on things which are not Number, just on things
  that are not NaN

Fixes: https://github.com/jitsi/lib-jitsi-meet/issues/2743
dev0
Saúl Ibarra Corretgé před 6 měsíci
rodič
revize
154817b640

+ 11
- 10
JitsiConference.js Zobrazit soubor

@@ -35,7 +35,7 @@ import LocalStatsCollector from './modules/statistics/LocalStatsCollector';
35 35
 import SpeakerStatsCollector from './modules/statistics/SpeakerStatsCollector';
36 36
 import Statistics from './modules/statistics/statistics';
37 37
 import EventEmitter from './modules/util/EventEmitter';
38
-import { safeSubtract } from './modules/util/MathUtil';
38
+import { isValidNumber, safeSubtract } from './modules/util/MathUtil';
39 39
 import RandomUtil from './modules/util/RandomUtil';
40 40
 import { getJitterDelay } from './modules/util/Retry';
41 41
 import ComponentsVersions from './modules/version/ComponentsVersions';
@@ -247,15 +247,14 @@ export default function JitsiConference(options) {
247 247
      */
248 248
     this.deferredStartP2PTask = null;
249 249
 
250
-    const delay
251
-        = parseInt(options.config.p2p && options.config.p2p.backToP2PDelay, 10);
250
+    const delay = Number.parseInt(options.config.p2p?.backToP2PDelay, 10);
252 251
 
253 252
     /**
254 253
      * A delay given in seconds, before the conference switches back to P2P
255 254
      * after the 3rd participant has left.
256 255
      * @type {number}
257 256
      */
258
-    this.backToP2PDelay = isNaN(delay) ? 5 : delay;
257
+    this.backToP2PDelay = isValidNumber(delay) ? delay : 5;
259 258
     logger.info(`backToP2PDelay: ${this.backToP2PDelay}`);
260 259
 
261 260
     /**
@@ -3078,8 +3077,8 @@ JitsiConference.prototype._onIceConnectionEstablished = function(jingleSession)
3078 3077
         done = true;
3079 3078
     }
3080 3079
 
3081
-    if (!isNaN(this.p2pEstablishmentDuration)
3082
-        && !isNaN(this.jvbEstablishmentDuration)) {
3080
+    if (isValidNumber(this.p2pEstablishmentDuration)
3081
+            && isValidNumber(this.jvbEstablishmentDuration)) {
3083 3082
         const establishmentDurationDiff
3084 3083
             = this.p2pEstablishmentDuration - this.jvbEstablishmentDuration;
3085 3084
 
@@ -3678,19 +3677,21 @@ JitsiConference.prototype.getP2PConnectionState = function() {
3678 3677
  * @returns {boolean} true if the operation is successful, false otherwise.
3679 3678
  */
3680 3679
 JitsiConference.prototype.setDesktopSharingFrameRate = function(maxFps) {
3681
-    if (typeof maxFps !== 'number' || isNaN(maxFps)) {
3680
+    if (!isValidNumber(maxFps)) {
3682 3681
         logger.error(`Invalid value ${maxFps} specified for desktop capture frame rate`);
3683 3682
 
3684 3683
         return false;
3685 3684
     }
3686 3685
 
3687
-    this._desktopSharingFrameRate = maxFps;
3686
+    const fps = Number(maxFps);
3687
+
3688
+    this._desktopSharingFrameRate = fps;
3688 3689
 
3689 3690
     // Set capture fps for screenshare.
3690
-    this.jvbJingleSession && this.jvbJingleSession.peerconnection.setDesktopSharingFrameRate(maxFps);
3691
+    this.jvbJingleSession && this.jvbJingleSession.peerconnection.setDesktopSharingFrameRate(fps);
3691 3692
 
3692 3693
     // Set the capture rate for desktop sharing.
3693
-    this.rtc.setDesktopSharingFrameRate(maxFps);
3694
+    this.rtc.setDesktopSharingFrameRate(fps);
3694 3695
 
3695 3696
     return true;
3696 3697
 };

+ 4
- 3
modules/RTC/JitsiLocalTrack.js Zobrazit soubor

@@ -21,6 +21,7 @@ import {
21 21
 } from '../../service/statistics/AnalyticsEvents';
22 22
 import browser from '../browser';
23 23
 import Statistics from '../statistics/statistics';
24
+import { isValidNumber } from '../util/MathUtil';
24 25
 
25 26
 import JitsiTrack from './JitsiTrack';
26 27
 import RTCUtils from './RTCUtils';
@@ -116,7 +117,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
116 117
                 }
117 118
 
118 119
                 // If the constraints are still empty, fallback to the constraints used for initial gUM.
119
-                if (isNaN(this._constraints.height.ideal) && isNaN(this._constraints.width.ideal)) {
120
+                if (!isValidNumber(this._constraints.height.ideal) && !isValidNumber(this._constraints.width.ideal)) {
120 121
                     this._constraints.height = { ideal: constraints.height.ideal };
121 122
                     this._constraints.width = { ideal: constraints.width.ideal };
122 123
                 }
@@ -126,7 +127,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
126 127
             // picked for the given constraints, fallback to the constraints if MediaStreamTrack.getSettings() doesn't
127 128
             // return the height.
128 129
             this.resolution = this.getHeight();
129
-            if (isNaN(this.resolution) && this._constraints.height?.ideal) {
130
+            if (!isValidNumber(this.resolution) && this._constraints.height?.ideal) {
130 131
                 this.resolution = this._constraints.height.ideal;
131 132
             }
132 133
             this.maxEnabledResolution = this.resolution;
@@ -931,7 +932,7 @@ export default class JitsiLocalTrack extends JitsiTrack {
931 932
      * @param {number} ssrc The SSRC.
932 933
      */
933 934
     setSsrc(ssrc) {
934
-        if (!isNaN(ssrc)) {
935
+        if (isValidNumber(ssrc)) {
935 936
             this._ssrc = ssrc;
936 937
         }
937 938
     }

+ 2
- 1
modules/RTC/JitsiRemoteTrack.js Zobrazit soubor

@@ -3,6 +3,7 @@ import { VideoType } from '../../service/RTC/VideoType';
3 3
 import { createTtfmEvent } from '../../service/statistics/AnalyticsEvents';
4 4
 import TrackStreamingStatusImpl, { TrackStreamingStatus } from '../connectivity/TrackStreamingStatus';
5 5
 import Statistics from '../statistics/statistics';
6
+import { isValidNumber } from '../util/MathUtil';
6 7
 
7 8
 import JitsiTrack from './JitsiTrack';
8 9
 
@@ -329,7 +330,7 @@ export default class JitsiRemoteTrack extends JitsiTrack {
329 330
         const gumStart = window.connectionTimes['obtainPermissions.start'];
330 331
         const gumEnd = window.connectionTimes['obtainPermissions.end'];
331 332
         const gumDuration
332
-            = !isNaN(gumEnd) && !isNaN(gumStart) ? gumEnd - gumStart : 0;
333
+            = isValidNumber(gumEnd) && isValidNumber(gumStart) ? gumEnd - gumStart : 0;
333 334
 
334 335
         // Subtract the muc.joined-to-session-initiate duration because jicofo
335 336
         // waits until there are 2 participants to start Jingle sessions.

+ 2
- 5
modules/RTC/RTCUtils.js Zobrazit soubor

@@ -12,6 +12,7 @@ import { AVAILABLE_DEVICE } from '../../service/statistics/AnalyticsEvents';
12 12
 import browser from '../browser';
13 13
 import Statistics from '../statistics/statistics';
14 14
 import Listenable from '../util/Listenable';
15
+import { isValidNumber } from '../util/MathUtil';
15 16
 
16 17
 import screenObtainer from './ScreenObtainer';
17 18
 
@@ -336,7 +337,7 @@ class RTCUtils extends Listenable {
336 337
         return new Promise((resolve, reject) => {
337 338
             let gumTimeout, timeoutExpired = false;
338 339
 
339
-            if (typeof timeout === 'number' && !isNaN(timeout) && timeout > 0) {
340
+            if (isValidNumber(timeout) && timeout > 0) {
340 341
                 gumTimeout = setTimeout(() => {
341 342
                     timeoutExpired = true;
342 343
                     gumTimeout = undefined;
@@ -369,10 +370,6 @@ class RTCUtils extends Listenable {
369 370
                     if (jitsiError.name === JitsiTrackErrors.PERMISSION_DENIED) {
370 371
                         this._updateGrantedPermissions(umDevices, undefined);
371 372
                     }
372
-
373
-                    // else {
374
-                    // Probably the error is not caused by the lack of permissions and we don't need to update them.
375
-                    // }
376 373
                 });
377 374
         });
378 375
     }

+ 3
- 2
modules/RTC/TraceablePeerConnection.js Zobrazit soubor

@@ -21,6 +21,7 @@ import SDPUtil from '../sdp/SDPUtil';
21 21
 import SdpSimulcast from '../sdp/SdpSimulcast';
22 22
 import { SdpTransformWrap } from '../sdp/SdpTransformUtil';
23 23
 import Statistics from '../statistics/statistics';
24
+import { isValidNumber } from '../util/MathUtil';
24 25
 
25 26
 import JitsiRemoteTrack from './JitsiRemoteTrack';
26 27
 import RTCUtils from './RTCUtils';
@@ -922,7 +923,7 @@ TraceablePeerConnection.prototype._remoteTrackAdded = function(stream, track, tr
922 923
     const trackSsrc = Number(ssrcStr);
923 924
     const ownerEndpointId = this.signalingLayer.getSSRCOwner(trackSsrc);
924 925
 
925
-    if (isNaN(trackSsrc) || trackSsrc < 0) {
926
+    if (!isValidNumber(trackSsrc) || trackSsrc < 0) {
926 927
         logger.error(`Invalid SSRC for remote stream[ssrc=${trackSsrc},id=${streamId},type=${mediaType}]`
927 928
                 + 'track creation failed!');
928 929
 
@@ -2065,7 +2066,7 @@ TraceablePeerConnection.prototype.setRemoteDescription = function(description) {
2065 2066
  * @returns {Promise} promise that will be resolved when the operation is successful and rejected otherwise.
2066 2067
  */
2067 2068
 TraceablePeerConnection.prototype.setSenderVideoConstraints = function(frameHeight, localVideoTrack, preferredCodec) {
2068
-    if (frameHeight < 0 || isNaN(frameHeight)) {
2069
+    if (frameHeight < 0 || !isValidNumber(frameHeight)) {
2069 2070
         throw new Error(`Invalid frameHeight: ${frameHeight}`);
2070 2071
     }
2071 2072
     if (!localVideoTrack) {

+ 2
- 1
modules/qualitycontrol/QualityController.ts Zobrazit soubor

@@ -12,6 +12,7 @@ import {
12 12
 } from '../../service/RTC/StandardVideoQualitySettings';
13 13
 import JitsiLocalTrack from '../RTC/JitsiLocalTrack';
14 14
 import TraceablePeerConnection from '../RTC/TraceablePeerConnection';
15
+import { isValidNumber } from '../util/MathUtil';
15 16
 import JingleSessionPC from '../xmpp/JingleSessionPC';
16 17
 
17 18
 import { CodecSelection } from './CodecSelection';
@@ -318,7 +319,7 @@ export class QualityController {
318 319
         const { encodeResolution, localTrack, qualityLimitationReason, tpc } = sourceStats;
319 320
 
320 321
         // Older browser versions might not report the resolution in the stats.
321
-        if (Number.isNaN(encodeResolution)) {
322
+        if (!isValidNumber(encodeResolution)) {
322 323
             return;
323 324
         }
324 325
         const trackId = localTrack.rtcId;

+ 13
- 12
modules/statistics/AvgRTPStatsReporter.js Zobrazit soubor

@@ -11,6 +11,7 @@ import {
11 11
     createTransportStatsEvent
12 12
 } from '../../service/statistics/AnalyticsEvents';
13 13
 import browser from '../browser';
14
+import { isValidNumber } from '../util/MathUtil';
14 15
 
15 16
 import Statistics from './statistics';
16 17
 
@@ -46,7 +47,7 @@ class AverageStatReport {
46 47
 
47 48
         if (typeof nextValue !== 'number') {
48 49
             logger.error(`${this.name} - invalid value for idx: ${this.count}`, nextValue);
49
-        } else if (!isNaN(nextValue)) {
50
+        } else if (isValidNumber(nextValue)) {
50 51
             this.sum += nextValue;
51 52
             this.samples.push(nextValue);
52 53
             this.count += 1;
@@ -222,7 +223,7 @@ class ConnectionAvgStats {
222 223
                     const jvbEnd2EndRTT = this
223 224
                         ._avgRtpStatsReporter.jvbStatsMonitor._avgEnd2EndRTT;
224 225
 
225
-                    if (!isNaN(jvbEnd2EndRTT)) {
226
+                    if (isValidNumber(jvbEnd2EndRTT)) {
226 227
                         // eslint-disable-next-line dot-notation
227 228
                         batchReport['rtt_diff']
228 229
                             = this._avgRTT.calculate() - jvbEnd2EndRTT;
@@ -234,7 +235,7 @@ class ConnectionAvgStats {
234 235
 
235 236
                     this._avgEnd2EndRTT = avgLocalRTT + avgRemoteRTT;
236 237
 
237
-                    if (!isNaN(avgLocalRTT) && !isNaN(avgRemoteRTT)) {
238
+                    if (isValidNumber(avgLocalRTT) && isValidNumber(avgRemoteRTT)) {
238 239
                         // eslint-disable-next-line dot-notation
239 240
                         batchReport['end2end_rtt_avg'] = this._avgEnd2EndRTT;
240 241
                     }
@@ -261,7 +262,7 @@ class ConnectionAvgStats {
261 262
         for (const remoteAvg of this._avgRemoteRTTMap.values()) {
262 263
             const avg = remoteAvg.calculate();
263 264
 
264
-            if (!isNaN(avg)) {
265
+            if (isValidNumber(avg)) {
265 266
                 sum += avg;
266 267
                 count += 1;
267 268
                 remoteAvg.reset();
@@ -715,20 +716,20 @@ export default class AvgRTPStatsReporter {
715 716
             this._avgPacketLossTotal.appendReport(batchReport);
716 717
 
717 718
             this._avgRemoteFPS.appendReport(batchReport);
718
-            if (!isNaN(this._avgRemoteScreenFPS.calculate())) {
719
+            if (isValidNumber(this._avgRemoteScreenFPS.calculate())) {
719 720
                 this._avgRemoteScreenFPS.appendReport(batchReport);
720 721
             }
721 722
             this._avgLocalFPS.appendReport(batchReport);
722
-            if (!isNaN(this._avgLocalScreenFPS.calculate())) {
723
+            if (isValidNumber(this._avgLocalScreenFPS.calculate())) {
723 724
                 this._avgLocalScreenFPS.appendReport(batchReport);
724 725
             }
725 726
 
726 727
             this._avgRemoteCameraPixels.appendReport(batchReport);
727
-            if (!isNaN(this._avgRemoteScreenPixels.calculate())) {
728
+            if (isValidNumber(this._avgRemoteScreenPixels.calculate())) {
728 729
                 this._avgRemoteScreenPixels.appendReport(batchReport);
729 730
             }
730 731
             this._avgLocalCameraPixels.appendReport(batchReport);
731
-            if (!isNaN(this._avgLocalScreenPixels.calculate())) {
732
+            if (isValidNumber(this._avgLocalScreenPixels.calculate())) {
732 733
                 this._avgLocalScreenPixels.appendReport(batchReport);
733 734
             }
734 735
 
@@ -769,7 +770,7 @@ export default class AvgRTPStatsReporter {
769 770
                     const peerAvgPixels = this._calculatePeerAvgVideoPixels(
770 771
                         videosResolution, participant, videoType);
771 772
 
772
-                    if (!isNaN(peerAvgPixels)) {
773
+                    if (isValidNumber(peerAvgPixels)) {
773 774
                         peerPixelsSum += peerAvgPixels;
774 775
                         peerCount += 1;
775 776
                     }
@@ -829,7 +830,7 @@ export default class AvgRTPStatsReporter {
829 830
                 = Number(videos[ssrc].height) * Number(videos[ssrc].width);
830 831
 
831 832
             // FPS is reported as 0 for users with no video
832
-            if (!isNaN(peerSsrcPixels) && peerSsrcPixels > 0) {
833
+            if (isValidNumber(peerSsrcPixels) && peerSsrcPixels > 0) {
833 834
                 peerPixelsSum += peerSsrcPixels;
834 835
                 peerSsrcCount += 1;
835 836
             }
@@ -866,7 +867,7 @@ export default class AvgRTPStatsReporter {
866 867
                         = this._calculatePeerAvgVideoFps(
867 868
                             videosFps, participant, videoType);
868 869
 
869
-                    if (!isNaN(peerAvgFPS)) {
870
+                    if (isValidNumber(peerAvgFPS)) {
870 871
                         peerFpsSum += peerAvgFPS;
871 872
                         peerCount += 1;
872 873
                     }
@@ -923,7 +924,7 @@ export default class AvgRTPStatsReporter {
923 924
             const peerSsrcFps = Number(videos[ssrc]);
924 925
 
925 926
             // FPS is reported as 0 for users with no video
926
-            if (!isNaN(peerSsrcFps) && peerSsrcFps > 0) {
927
+            if (isValidNumber(peerSsrcFps) && peerSsrcFps > 0) {
927 928
                 peerFpsSum += peerSsrcFps;
928 929
                 peerSsrcCount += 1;
929 930
             }

+ 6
- 5
modules/statistics/RTPStatsCollector.js Zobrazit soubor

@@ -4,6 +4,7 @@ import { MediaType } from '../../service/RTC/MediaType';
4 4
 import * as StatisticsEvents from '../../service/statistics/Events';
5 5
 import browser from '../browser';
6 6
 import FeatureFlags from '../flags/FeatureFlags';
7
+import { isValidNumber } from '../util/MathUtil';
7 8
 
8 9
 const logger = getLogger('modules/statistics/RTPStatsCollector');
9 10
 
@@ -305,7 +306,7 @@ StatsCollector.prototype._processAndEmitReport = function() {
305 306
             if (!FeatureFlags.isSsrcRewritingSupported()) {
306 307
                 logger.error(`No participant ID returned by ${track}`);
307 308
             }
308
-            continue; // eslint-disable-line no-continue
309
+            continue;
309 310
         }
310 311
 
311 312
         const userCodecs = codecs[participantId] ?? { };
@@ -319,11 +320,11 @@ StatsCollector.prototype._processAndEmitReport = function() {
319 320
         const { resolution } = ssrcStats;
320 321
 
321 322
         if (!track.isVideoTrack()
322
-            || isNaN(resolution?.height)
323
-            || isNaN(resolution?.width)
323
+            || !isValidNumber(resolution?.height)
324
+            || !isValidNumber(resolution?.width)
324 325
             || resolution.height === -1
325 326
             || resolution.width === -1) {
326
-            continue; // eslint-disable-line no-continue
327
+            continue;
327 328
         }
328 329
         const userResolutions = resolutions[participantId] || {};
329 330
 
@@ -413,7 +414,7 @@ StatsCollector.prototype.getNonNegativeValue = function(v) {
413 414
         value = Number(value);
414 415
     }
415 416
 
416
-    if (isNaN(value)) {
417
+    if (!isValidNumber(value)) {
417 418
         return 0;
418 419
     }
419 420
 

+ 13
- 1
modules/util/MathUtil.ts Zobrazit soubor

@@ -103,5 +103,17 @@ export class RunningAverage {
103 103
  * @returns {number} - x - y or 0 if x or y is not a number.
104 104
  */
105 105
 export function safeSubtract(x: any, y: any): number {
106
-    return !isNaN(x) && !isNaN(y) ? x - y : 0;
106
+    return isValidNumber(x) && isValidNumber(y) ? x - y : 0;
107
+}
108
+
109
+/**
110
+ * Checks if the given value is a valid number.
111
+ *
112
+ * @param n - The value to check.
113
+ * @returns - `true` if the value is a valid number, `false` otherwise.
114
+ */
115
+export function isValidNumber(n: any): boolean {
116
+    const v = Number.parseInt(n, 10);
117
+
118
+    return Number.isFinite(v); // Filter out NaN and Infinity.
107 119
 }

+ 2
- 1
service/RTC/SignalingLayer.ts Zobrazit soubor

@@ -1,4 +1,5 @@
1 1
 import Listenable from '../../modules/util/Listenable';
2
+import { isValidNumber } from '../../modules/util/MathUtil';
2 3
 
3 4
 import { MediaType } from './MediaType';
4 5
 import { VideoType } from './VideoType';
@@ -69,7 +70,7 @@ export function getSourceIndexFromSourceName(sourceName: SourceName): number {
69 70
     const nameParts = sourceName.split('-');
70 71
     const trackIdx = Number(nameParts[nameParts.length - 1].substring(1));
71 72
 
72
-    if (Number.isNaN(trackIdx)) {
73
+    if (!isValidNumber(trackIdx)) {
73 74
         throw new Error(`Failed to parse track idx for source name: ${sourceName}`);
74 75
     }
75 76
 

Načítá se…
Zrušit
Uložit