Commit 0216728 for jssip.net

commit 0216728fbbec4cb4737fb3679119de8968ca5e77
Author: José Luis Millán <jmillan@aliax.net>
Date:   Fri Jan 9 13:45:32 2026 +0100

    Modernize eslint

diff --git a/.eslintignore b/.eslintignore
deleted file mode 100644
index 0099319..0000000
--- a/.eslintignore
+++ /dev/null
@@ -1 +0,0 @@
-src/Grammar.js
diff --git a/.eslintrc.js b/.eslintrc.js
deleted file mode 100644
index f9ee933..0000000
--- a/.eslintrc.js
+++ /dev/null
@@ -1,173 +0,0 @@
-module.exports =
-{
-	env:
-	{
-		browser: true,
-		es6: true,
-		node: true
-	},
-	plugins:
-	[
-	],
-	extends:
-	[
-		'eslint:recommended'
-	],
-	settings: {},
-	parserOptions:
-	{
-		ecmaVersion: 6,
-		sourceType: 'module',
-		ecmaFeatures:
-		{
-			impliedStrict: true
-		}
-	},
-	rules:
-	{
-		'array-bracket-spacing': [ 2, 'always',
-		{
-			objectsInArrays: true,
-			arraysInArrays: true
-		}],
-		'arrow-parens': [ 2, 'always' ],
-		'arrow-spacing': 2,
-		'block-spacing': [ 2, 'always' ],
-		'brace-style': [ 2, 'allman', { allowSingleLine: true } ],
-		'camelcase': 0,
-		'comma-dangle': 2,
-		'comma-spacing': [ 2, { before: false, after: true } ],
-		'comma-style': 2,
-		'computed-property-spacing': 2,
-		'constructor-super': 2,
-		'func-call-spacing': 2,
-		'generator-star-spacing': 2,
-		'guard-for-in': 2,
-		'indent': [ 2, 2, { 'SwitchCase': 1 } ],
-		'key-spacing': [ 2,
-		{
-			singleLine:
-			{
-				beforeColon: false,
-				afterColon: true
-			},
-			multiLine:
-			{
-				beforeColon: true,
-				afterColon: true,
-				align: 'colon'
-			}
-		}],
-		'keyword-spacing': 2,
-		'linebreak-style': [ 2, 'unix' ],
-		'lines-around-comment': [ 2,
-		{
-			allowBlockStart: true,
-			allowObjectStart: true,
-			beforeBlockComment: true,
-			beforeLineComment: false
-		}],
-		'max-len': [ 2, 90,
-		{
-			tabWidth: 2,
-			comments: 110,
-			ignoreUrls: true,
-			ignoreStrings: true,
-			ignoreTemplateLiterals: true,
-			ignoreRegExpLiterals: true
-		}],
-		'newline-after-var': 2,
-		'newline-before-return': 2,
-		'newline-per-chained-call': 2,
-		'no-alert': 2,
-		'no-caller': 2,
-		'no-case-declarations': 2,
-		'no-catch-shadow': 2,
-		'no-class-assign': 2,
-		'no-confusing-arrow': 2,
-		'no-console': [ 2, { allow: [ 'warn' ] } ],
-		'no-const-assign': 2,
-		'no-constant-condition': [ 2 , { 'checkLoops': false } ],
-		'no-debugger': 2,
-		'no-dupe-args': 2,
-		'no-dupe-keys': 2,
-		'no-duplicate-case': 2,
-		'no-div-regex': 2,
-		'no-empty': [ 2, { allowEmptyCatch: true } ],
-		'no-empty-pattern': 2,
-		'no-else-return': 0,
-		'no-eval': 2,
-		'no-extend-native': 2,
-		'no-ex-assign': 2,
-		'no-extra-bind': 2,
-		'no-extra-boolean-cast': 2,
-		'no-extra-label': 2,
-		'no-extra-semi': 2,
-		'no-fallthrough': 2,
-		'no-func-assign': 2,
-		'no-global-assign': 2,
-		'no-implicit-coercion': 2,
-		'no-implicit-globals': 2,
-		'no-inner-declarations': 2,
-		'no-invalid-regexp': 2,
-		'no-invalid-this': 0,
-		'no-irregular-whitespace': 2,
-		'no-lonely-if': 2,
-		'no-mixed-operators': 2,
-		'no-mixed-spaces-and-tabs': 2,
-		'no-multi-spaces': 2,
-		'no-multi-str': 2,
-		'no-multiple-empty-lines': 2,
-		'no-native-reassign': 2,
-		'no-negated-in-lhs': 2,
-		'no-new': 2,
-		'no-new-func': 2,
-		'no-new-wrappers': 2,
-		'no-obj-calls': 2,
-		'no-proto': 2,
-		'no-prototype-builtins': 0,
-		'no-redeclare': 2,
-		'no-regex-spaces': 2,
-		'no-restricted-imports': 2,
-		'no-return-assign': 2,
-		'no-self-assign': 2,
-		'no-self-compare': 2,
-		'no-sequences': 2,
-		'no-shadow': 2,
-		'no-shadow-restricted-names': 2,
-		'no-spaced-func': 2,
-		'no-sparse-arrays': 2,
-		'no-this-before-super': 2,
-		'no-throw-literal': 2,
-		'no-trailing-spaces': 2,
-		'no-undef': 2,
-		'no-unexpected-multiline': 2,
-		'no-unmodified-loop-condition': 2,
-		'no-unreachable': 2,
-		'no-unused-vars': [ 1, { vars: 'all', args: 'after-used' }],
-		'no-use-before-define': [ 2, { functions: false } ],
-		'no-useless-call': 2,
-		'no-useless-computed-key': 2,
-		'no-useless-concat': 2,
-		'no-useless-rename': 2,
-		'no-var': 2,
-		'no-whitespace-before-property': 2,
-		'object-curly-newline': 0,
-		'object-curly-spacing': [ 2, 'always' ],
-		'object-property-newline': [ 2, { allowMultiplePropertiesPerLine: true } ],
-		'prefer-const': 2,
-		'prefer-rest-params': 2,
-		'prefer-spread': 2,
-		'prefer-template': 2,
-		'quotes': [ 2, 'single', { avoidEscape: true } ],
-		'semi': [ 2, 'always' ],
-		'semi-spacing': 2,
-		'space-before-blocks': 2,
-		'space-before-function-paren': [ 2, 'never' ],
-		'space-in-parens': [ 2, 'never' ],
-		'spaced-comment': [ 2, 'always' ],
-		'strict': 2,
-		'valid-typeof': 2,
-		'yoda': 2
-	}
-};
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4df7ea3..7f0ad59 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,11 @@
 CHANGELOG
 =========

+### NEXT RELEASE
+
+* Modernize eslint.
+
+
 ### 3.11.1

 * Move code from 'lib/' to 'src/'.
diff --git a/eslint.config.js b/eslint.config.js
new file mode 100644
index 0000000..ab33e21
--- /dev/null
+++ b/eslint.config.js
@@ -0,0 +1,227 @@
+const {
+    defineConfig,
+    globalIgnores,
+} = require("eslint/config");
+
+const globals = require("globals");
+const js = require("@eslint/js");
+
+const {
+    FlatCompat,
+} = require("@eslint/eslintrc");
+
+const compat = new FlatCompat({
+    baseDirectory: __dirname,
+    recommendedConfig: js.configs.recommended,
+    allConfig: js.configs.all
+});
+
+module.exports = defineConfig([{
+    languageOptions: {
+        globals: {
+            ...globals.browser,
+            ...globals.node,
+        },
+
+        ecmaVersion: 6,
+        sourceType: "module",
+
+        parserOptions: {
+            ecmaFeatures: {
+                impliedStrict: true,
+            },
+        },
+    },
+
+    plugins: {},
+    extends: compat.extends("eslint:recommended"),
+    settings: {},
+
+    rules: {
+        "array-bracket-spacing": [2, "always", {
+            objectsInArrays: true,
+            arraysInArrays: true,
+        }],
+
+        "arrow-parens": [2, "always"],
+        "arrow-spacing": 2,
+        "block-spacing": [2, "always"],
+
+        "brace-style": [2, "allman", {
+            allowSingleLine: true,
+        }],
+
+        "camelcase": 0,
+        "comma-dangle": 2,
+
+        "comma-spacing": [2, {
+            before: false,
+            after: true,
+        }],
+
+        "comma-style": 2,
+        "computed-property-spacing": 2,
+        "constructor-super": 2,
+        "func-call-spacing": 2,
+        "generator-star-spacing": 2,
+        "guard-for-in": 2,
+
+        "indent": [2, 2, {
+            "SwitchCase": 1,
+        }],
+
+        "key-spacing": [2, {
+            singleLine: {
+                beforeColon: false,
+                afterColon: true,
+            },
+
+            multiLine: {
+                beforeColon: true,
+                afterColon: true,
+                align: "colon",
+            },
+        }],
+
+        "keyword-spacing": 2,
+        "linebreak-style": [2, "unix"],
+
+        "lines-around-comment": [2, {
+            allowBlockStart: true,
+            allowObjectStart: true,
+            beforeBlockComment: true,
+            beforeLineComment: false,
+        }],
+
+        "max-len": [2, 90, {
+            tabWidth: 2,
+            comments: 110,
+            ignoreUrls: true,
+            ignoreStrings: true,
+            ignoreTemplateLiterals: true,
+            ignoreRegExpLiterals: true,
+        }],
+
+        "newline-after-var": 2,
+        "newline-before-return": 2,
+        "newline-per-chained-call": 2,
+        "no-alert": 2,
+        "no-caller": 2,
+        "no-case-declarations": 2,
+        "no-catch-shadow": 2,
+        "no-class-assign": 2,
+        "no-confusing-arrow": 2,
+
+        "no-console": [2, {
+            allow: ["warn"],
+        }],
+
+        "no-const-assign": 2,
+
+        "no-constant-condition": [2, {
+            "checkLoops": false,
+        }],
+
+        "no-debugger": 2,
+        "no-dupe-args": 2,
+        "no-dupe-keys": 2,
+        "no-duplicate-case": 2,
+        "no-div-regex": 2,
+
+        "no-empty": [2, {
+            allowEmptyCatch: true,
+        }],
+
+        "no-empty-pattern": 2,
+        "no-else-return": 0,
+        "no-eval": 2,
+        "no-extend-native": 2,
+        "no-ex-assign": 2,
+        "no-extra-bind": 2,
+        "no-extra-boolean-cast": 2,
+        "no-extra-label": 2,
+        "no-extra-semi": 2,
+        "no-fallthrough": 2,
+        "no-func-assign": 2,
+        "no-global-assign": 2,
+        "no-implicit-coercion": 2,
+        "no-implicit-globals": 2,
+        "no-inner-declarations": 2,
+        "no-invalid-regexp": 2,
+        "no-invalid-this": 0,
+        "no-irregular-whitespace": 2,
+        "no-lonely-if": 2,
+        "no-mixed-operators": 2,
+        "no-mixed-spaces-and-tabs": 2,
+        "no-multi-spaces": 2,
+        "no-multi-str": 2,
+        "no-multiple-empty-lines": 2,
+        "no-native-reassign": 2,
+        "no-negated-in-lhs": 2,
+        "no-new": 2,
+        "no-new-func": 2,
+        "no-new-wrappers": 2,
+        "no-obj-calls": 2,
+        "no-proto": 2,
+        "no-prototype-builtins": 0,
+        "no-redeclare": 2,
+        "no-regex-spaces": 2,
+        "no-restricted-imports": 2,
+        "no-return-assign": 2,
+        "no-self-assign": 2,
+        "no-self-compare": 2,
+        "no-sequences": 2,
+        "no-shadow": 2,
+        "no-shadow-restricted-names": 2,
+        "no-spaced-func": 2,
+        "no-sparse-arrays": 2,
+        "no-this-before-super": 2,
+        "no-throw-literal": 2,
+        "no-trailing-spaces": 2,
+        "no-undef": 2,
+        "no-unexpected-multiline": 2,
+        "no-unmodified-loop-condition": 2,
+        "no-unreachable": 2,
+
+        "no-unused-vars": [1, {
+            vars: "all",
+            args: "after-used",
+        }],
+
+        "no-use-before-define": [2, {
+            functions: false,
+        }],
+
+        "no-useless-call": 2,
+        "no-useless-computed-key": 2,
+        "no-useless-concat": 2,
+        "no-useless-rename": 2,
+        "no-var": 2,
+        "no-whitespace-before-property": 2,
+        "object-curly-newline": 0,
+        "object-curly-spacing": [2, "always"],
+
+        "object-property-newline": [2, {
+            allowMultiplePropertiesPerLine: true,
+        }],
+
+        "prefer-const": 2,
+        "prefer-rest-params": 2,
+        "prefer-spread": 2,
+        "prefer-template": 2,
+
+        "quotes": [2, "single", {
+            avoidEscape: true,
+        }],
+
+        "semi": [2, "always"],
+        "semi-spacing": 2,
+        "space-before-blocks": 2,
+        "space-before-function-paren": [2, "never"],
+        "space-in-parens": [2, "never"],
+        "spaced-comment": [2, "always"],
+        "strict": 2,
+        "valid-typeof": 2,
+        "yoda": 2,
+    },
+}, globalIgnores(["src/Grammar.js"])]);
diff --git a/npm-scripts.js b/npm-scripts.js
index 2178052..946c676 100644
--- a/npm-scripts.js
+++ b/npm-scripts.js
@@ -13,29 +13,25 @@ console.log(`npm-scripts.js [INFO] running task "${task}"`);

 switch (task)
 {
-  case 'grammar':
-  {
+  case 'grammar': {
     grammar();

     break;
   }

-  case 'lint':
-  {
+  case 'lint': {
     lint();

     break;
   }

-  case 'test':
-  {
+  case 'test': {
     executeCmd('gulp test');

     break;
   }

-  case 'release':
-  {
+  case 'release': {
     lint();
     executeCmd('gulp test');
     executeCmd(`git commit -am '${version}'`);
@@ -49,8 +45,7 @@ switch (task)
     break;
   }

-  default:
-  {
+  default: {
     throw new TypeError(`unknown task "${task}"`);
   }
 }
@@ -59,9 +54,7 @@ function lint()
 {
   logInfo('lint()');

-  executeCmd(
-    `eslint --max-warnings 0 ${ESLINT_PATHS}`
-  );
+  executeCmd(`eslint -c eslint.config.js --max-warnings 0 ${ESLINT_PATHS}`);
 }

 function grammar()
@@ -74,7 +67,7 @@ function grammar()

   logInfo('compiling Grammar.pegjs into Grammar.js...');

-  executeCmd(`${local_pegjs } ${ Grammar_pegjs } ${ Grammar_js}`);
+  executeCmd(`${local_pegjs} ${Grammar_pegjs} ${Grammar_js}`);

   logInfo('grammar compiled');

@@ -82,9 +75,12 @@ function grammar()
   logInfo('applying custom changes to Grammar.js...');

   const current_grammar = fs.readFileSync('src/Grammar.js').toString();
-  let modified_grammar = current_grammar.replace(/throw new this\.SyntaxError\(([\s\S]*?)\);([\s\S]*?)}([\s\S]*?)return result;/, 'new this.SyntaxError($1);\n        return -1;$2}$3return data;');
+  let modified_grammar = current_grammar.replace(
+    /throw new this\.SyntaxError\(([\s\S]*?)\);([\s\S]*?)}([\s\S]*?)return result;/,
+    'new this.SyntaxError($1);\n        return -1;$2}$3return data;'
+  );

-  modified_grammar = modified_grammar.replace(/\s+$/mg, '');
+  modified_grammar = modified_grammar.replace(/\s+$/gm, '');
   fs.writeFileSync('src/Grammar.js', modified_grammar);

   logInfo('grammar done');
@@ -99,6 +95,7 @@ function executeCmd(command)
   {
     execSync(command, { stdio: [ 'ignore', process.stdout, process.stderr ] });
   }
+  // eslint-disable-next-line no-unused-vars
   catch (error)
   {
     process.exit(1);
@@ -110,10 +107,3 @@ function logInfo(...args)
   // eslint-disable-next-line no-console
   console.log(`npm-scripts.mjs \x1b[36m[INFO] [${task}]\x1b[0m`, ...args);
 }
-
-// eslint-disable-next-line no-unused-vars
-function logWarn(...args)
-{
-  // eslint-disable-next-line no-console
-  console.warn(`npm-scripts.mjs \x1b[33m[WARN] [${task}]\x1b\0m`, ...args);
-}
diff --git a/package.json b/package.json
index 186e732..31e86e7 100644
--- a/package.json
+++ b/package.json
@@ -27,14 +27,17 @@
     "url": "https://github.com/versatica/JsSIP/issues"
   },
   "dependencies": {
-    "@types/events": "^3.0.0",
     "@types/debug": "^4.1.7",
+    "@types/events": "^3.0.0",
     "debug": "^4.3.1",
     "events": "^3.3.0",
     "sdp-transform": "^2.14.1"
   },
   "devDependencies": {
-    "eslint": "^5.16.0",
+    "@eslint/eslintrc": "^3.3.3",
+    "@eslint/js": "^9.39.2",
+    "eslint": "^9.39.1",
+    "globals": "^17.0.0",
     "gulp": "^4.0.2",
     "gulp-expect-file": "^1.0.2",
     "gulp-nodeunit-runner": "^0.2.2",
diff --git a/src/RTCSession.js b/src/RTCSession.js
index 762555d..1b9e6eb 100644
--- a/src/RTCSession.js
+++ b/src/RTCSession.js
@@ -1,3 +1,4 @@
+// eslint-disable-next-line no-redeclare
 /* globals RTCPeerConnection: false, RTCSessionDescription: false */

 const EventEmitter = require('events').EventEmitter;
@@ -1524,8 +1525,7 @@ module.exports = class RTCSession extends EventEmitter
                 this.emit('peerconnection:setremotedescriptionfailed', error);
               });
           }
-          else
-          if (!this._is_confirmed)
+          else if (!this._is_confirmed)
           {
             this._confirmed('remote', request);
           }
@@ -3224,8 +3224,7 @@ module.exports = class RTCSession extends EventEmitter
           });
       }
       // No SDP answer.
-      else
-      if (eventHandlers.succeeded)
+      else if (eventHandlers.succeeded)
       {
         eventHandlers.succeeded(response);
       }
diff --git a/src/Socket.js b/src/Socket.js
index 697bc84..a45b4ad 100644
--- a/src/Socket.js
+++ b/src/Socket.js
@@ -59,7 +59,8 @@ exports.isSocket = (socket) =>
       throw new Error('missing or invalid JsSIP.Socket sip_uri property');
     }
   }
-  catch (e)
+  // eslint-disable-next-line no-unused-vars
+  catch (error)
   {
     return false;
   }
@@ -76,7 +77,8 @@ exports.isSocket = (socket) =>
       }
     });
   }
-  catch (e)
+  // eslint-disable-next-line no-unused-vars
+  catch (error)
   {
     return false;
   }
diff --git a/src/Transport.js b/src/Transport.js
index 52c6f15..ca2d715 100644
--- a/src/Transport.js
+++ b/src/Transport.js
@@ -376,10 +376,9 @@ module.exports = class Transport
         else
           data = String.fromCharCode.apply(null, new Uint8Array(data));
       }
-      catch (evt)
+      catch (error)
       {
-        logger.debug('received binary message failed to be converted into string,' +
-              ' message discarded');
+        logger.debug(`received binary message failed to be converted into string: ${error}`);

         return;
       }
diff --git a/src/UA.js b/src/UA.js
index c352408..4d66fdc 100644
--- a/src/UA.js
+++ b/src/UA.js
@@ -94,11 +94,11 @@ module.exports = class UA extends EventEmitter
     {
       this._loadConfig(configuration);
     }
-    catch (e)
+    catch (error)
     {
       this._status = C.STATUS_NOT_READY;
       this._error = C.CONFIGURATION_ERROR;
-      throw e;
+      throw error;
     }

     // Initialize registrator.
@@ -330,6 +330,7 @@ module.exports = class UA extends EventEmitter
       {
         logger.debug(`closing session ${session}`);
         try { this._sessions[session].terminate(); }
+        // eslint-disable-next-line no-unused-vars
         catch (error) {}
       }
     }
@@ -339,6 +340,7 @@ module.exports = class UA extends EventEmitter
     {
       if (Object.prototype.hasOwnProperty.call(this._applicants, applicant))
         try { this._applicants[applicant].close(); }
+        // eslint-disable-next-line no-unused-vars
         catch (error) {}
     }

@@ -764,8 +766,7 @@ module.exports = class UA extends EventEmitter
        * Exception: ACK for an Invite request for which a dialog has not
        * been created.
        */
-      else
-      if (method !== JsSIP_C.ACK)
+      else if (method !== JsSIP_C.ACK)
       {
         request.reply(481);
       }
@@ -830,14 +831,8 @@ module.exports = class UA extends EventEmitter
   _loadConfig(configuration)
   {
     // Check and load the given configuration.
-    try
-    {
-      config.load(this._configuration, configuration);
-    }
-    catch (e)
-    {
-      throw e;
-    }
+    // This can throw.
+    config.load(this._configuration, configuration);

     // Post Configuration Process.

@@ -877,9 +872,9 @@ module.exports = class UA extends EventEmitter
       this._transport.ondisconnect = onTransportDisconnect.bind(this);
       this._transport.ondata = onTransportData.bind(this);
     }
-    catch (e)
+    catch (error)
     {
-      logger.warn(e);
+      logger.warn(error);
       throw new Exceptions.ConfigurationError('sockets', this._configuration.sockets);
     }

diff --git a/src/Utils.js b/src/Utils.js
index 71edb62..065873e 100644
--- a/src/Utils.js
+++ b/src/Utils.js
@@ -529,6 +529,7 @@ exports.closeMediaStream = (stream) =>
       }
     }
   }
+  // eslint-disable-next-line no-unused-vars
   catch (error)
   {
     // Deprecated by the spec, but still in use.
diff --git a/src/WebSocketInterface.js b/src/WebSocketInterface.js
index c212b9f..8d9de81 100644
--- a/src/WebSocketInterface.js
+++ b/src/WebSocketInterface.js
@@ -88,9 +88,9 @@ module.exports = class WebSocketInterface
       this._ws.onmessage = this._onMessage.bind(this);
       this._ws.onerror = this._onError.bind(this);
     }
-    catch (e)
+    catch (error)
     {
-      this._onError(e);
+      this._onError(error);
     }
   }