diff options
| author | Tobias Järvelöv <tobias.jarvelov@mullvad.net> | 2025-08-15 10:20:29 +0200 |
|---|---|---|
| committer | Tobias Järvelöv <tobias.jarvelov@mullvad.net> | 2025-08-15 10:20:29 +0200 |
| commit | 5eb54c409647ff43b807617df0486d5a70603f51 (patch) | |
| tree | 8519858a9685221618b877e24af52780f1b43867 | |
| parent | 04cf484cf9d0f4f5449393a2483c974ef5c1508a (diff) | |
| parent | 0a8fcda430f58d09d5455a70a7b023ed54eefcdb (diff) | |
| download | mullvadvpn-5eb54c409647ff43b807617df0486d5a70603f51.tar.xz mullvadvpn-5eb54c409647ff43b807617df0486d5a70603f51.zip | |
Merge branch 'upgrade-to-react-19-des-1287'
31 files changed, 379 insertions, 215 deletions
diff --git a/desktop/package-lock.json b/desktop/package-lock.json index 5e463aaded..728fb2c2ca 100644 --- a/desktop/package-lock.json +++ b/desktop/package-lock.json @@ -2904,15 +2904,6 @@ "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", "dev": true }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, "node_modules/@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", @@ -2986,38 +2977,24 @@ "xmlbuilder": ">=11.0.1" } }, - "node_modules/@types/prop-types": { - "version": "15.7.3", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", - "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" - }, "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "version": "19.1.9", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.9.tgz", + "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==", + "devOptional": true, + "license": "MIT", "dependencies": { - "@types/prop-types": "*", "csstype": "^3.0.2" } }, "node_modules/@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.7.tgz", + "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==", "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/react-redux": { - "version": "7.1.24", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz", - "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==", - "dependencies": { - "@types/hoist-non-react-statics": "^3.3.0", - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0", - "redux": "^4.0.0" + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.0.0" } }, "node_modules/@types/react-router": { @@ -3074,6 +3051,12 @@ "@types/geojson": "*" } }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, "node_modules/@types/verror": { "version": "1.10.11", "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", @@ -5402,15 +5385,16 @@ } }, "node_modules/eslint-plugin-react-compiler": { - "version": "0.0.0-experimental-42acc6a-20241001", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-0.0.0-experimental-42acc6a-20241001.tgz", - "integrity": "sha512-pzkTsWowlHK4yKHsK1d9tTKOUtApZzL7wI6jT5iN31d00DhI9JGDD0pkLohQ6Wfkll+2aiqTPGj9esJoGYmRaw==", + "version": "19.1.0-rc.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.1.0-rc.2.tgz", + "integrity": "sha512-oKalwDGcD+RX9mf3NEO4zOoUMeLvjSvcbbEOpquzmzqEEM2MQdp7/FY/Hx9NzmUwFzH1W9SKTz5fihfMldpEYw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "@babel/plugin-proposal-private-methods": "^7.18.6", - "hermes-parser": "^0.20.1", + "hermes-parser": "^0.25.1", "zod": "^3.22.4", "zod-validation-error": "^3.0.3" }, @@ -5422,10 +5406,11 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "0.0.0-experimental-2d16326d-20240930", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-0.0.0-experimental-2d16326d-20240930.tgz", - "integrity": "sha512-6SrTdUGjhhQ51U6a695UlDFzR46pFlhz0yYyLrO5f4pXGHA0aE9X0TrqcB1gPyqB7LhSKjDSaoHC5/J48GG2UQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -6513,18 +6498,20 @@ } }, "node_modules/hermes-estree": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.20.1.tgz", - "integrity": "sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==", - "dev": true + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" }, "node_modules/hermes-parser": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.20.1.tgz", - "integrity": "sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", "dev": true, + "license": "MIT", "dependencies": { - "hermes-estree": "0.20.1" + "hermes-estree": "0.25.1" } }, "node_modules/hoist-non-react-statics": { @@ -8998,6 +8985,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -9009,6 +8997,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -9023,34 +9012,28 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "node_modules/react-redux": { - "version": "7.2.9", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", - "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "license": "MIT", "dependencies": { - "@babel/runtime": "^7.15.4", - "@types/react-redux": "^7.1.20", - "hoist-non-react-statics": "^3.3.2", - "loose-envify": "^1.4.0", - "prop-types": "^15.7.2", - "react-is": "^17.0.2" + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" }, "peerDependencies": { - "react": "^16.8.3 || ^17 || ^18" + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" }, "peerDependenciesMeta": { - "react-dom": { + "@types/react": { "optional": true }, - "react-native": { + "redux": { "optional": true } } }, - "node_modules/react-redux/node_modules/react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", @@ -9163,12 +9146,12 @@ "dev": true }, "node_modules/redux": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", - "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", - "dependencies": { - "@babel/runtime": "^7.9.2" - } + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/reflect.getprototypeof": { "version": "1.0.6", @@ -9556,6 +9539,7 @@ "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "peer": true, "dependencies": { "loose-envify": "^1.1.0" } @@ -10720,6 +10704,15 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/utf8-byte-length": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", @@ -11327,9 +11320,9 @@ "management-interface": "0.0.0", "node-gettext": "^3.0.0", "nseventforwarder": "0.0.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-redux": "^7.2.9", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-redux": "^9.2.0", "react-router": "^5.3.4", "redux": "^4.2.0", "simple-plist": "^1.3.1", @@ -11347,8 +11340,8 @@ "@types/history": "^4.7.11", "@types/mocha": "^10.0.0", "@types/node-gettext": "^3.0.3", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", + "@types/react": "^19.1.9", + "@types/react-dom": "^19.1.7", "@types/react-router": "^5.1.19", "@types/sinon": "^10.0.13", "@types/sprintf-js": "^1.1.2", @@ -11362,8 +11355,8 @@ "electron-builder": "26.0.18", "electron-devtools-installer": "^3.2.0", "eslint-plugin-react": "^7.36.1", - "eslint-plugin-react-compiler": "^0.0.0-experimental-42acc6a-20241001", - "eslint-plugin-react-hooks": "^0.0.0-experimental-2d16326d-20240930", + "eslint-plugin-react-compiler": "^19.1.0-rc.2", + "eslint-plugin-react-hooks": "^5.2.0", "gettext-extractor": "^3.5.4", "globals": "^15.9.0", "mocha": "^10.8.2", @@ -11621,6 +11614,42 @@ "dev": true, "license": "MIT" }, + "packages/mullvad-vpn/node_modules/react": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", + "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "packages/mullvad-vpn/node_modules/react-dom": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", + "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.1" + } + }, + "packages/mullvad-vpn/node_modules/redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.9.2" + } + }, + "packages/mullvad-vpn/node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==", + "license": "MIT" + }, "packages/mullvad-vpn/node_modules/which": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", @@ -13576,15 +13605,6 @@ "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==", "dev": true }, - "@types/hoist-non-react-statics": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz", - "integrity": "sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==", - "requires": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, "@types/http-cache-semantics": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz", @@ -13655,39 +13675,21 @@ "xmlbuilder": ">=11.0.1" } }, - "@types/prop-types": { - "version": "15.7.3", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", - "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" - }, "@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", + "version": "19.1.9", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.9.tgz", + "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==", + "devOptional": true, "requires": { - "@types/prop-types": "*", "csstype": "^3.0.2" } }, "@types/react-dom": { - "version": "18.3.0", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", - "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "version": "19.1.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.7.tgz", + "integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==", "dev": true, - "requires": { - "@types/react": "*" - } - }, - "@types/react-redux": { - "version": "7.1.24", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz", - "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==", - "requires": { - "@types/hoist-non-react-statics": "^3.3.0", - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0", - "redux": "^4.0.0" - } + "requires": {} }, "@types/react-router": { "version": "5.1.19", @@ -13743,6 +13745,11 @@ "@types/geojson": "*" } }, + "@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==" + }, "@types/verror": { "version": "1.10.11", "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", @@ -15437,23 +15444,23 @@ } }, "eslint-plugin-react-compiler": { - "version": "0.0.0-experimental-42acc6a-20241001", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-0.0.0-experimental-42acc6a-20241001.tgz", - "integrity": "sha512-pzkTsWowlHK4yKHsK1d9tTKOUtApZzL7wI6jT5iN31d00DhI9JGDD0pkLohQ6Wfkll+2aiqTPGj9esJoGYmRaw==", + "version": "19.1.0-rc.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-19.1.0-rc.2.tgz", + "integrity": "sha512-oKalwDGcD+RX9mf3NEO4zOoUMeLvjSvcbbEOpquzmzqEEM2MQdp7/FY/Hx9NzmUwFzH1W9SKTz5fihfMldpEYw==", "dev": true, "requires": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "@babel/plugin-proposal-private-methods": "^7.18.6", - "hermes-parser": "^0.20.1", + "hermes-parser": "^0.25.1", "zod": "^3.22.4", "zod-validation-error": "^3.0.3" } }, "eslint-plugin-react-hooks": { - "version": "0.0.0-experimental-2d16326d-20240930", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-0.0.0-experimental-2d16326d-20240930.tgz", - "integrity": "sha512-6SrTdUGjhhQ51U6a695UlDFzR46pFlhz0yYyLrO5f4pXGHA0aE9X0TrqcB1gPyqB7LhSKjDSaoHC5/J48GG2UQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, "requires": {} }, @@ -16159,18 +16166,18 @@ "dev": true }, "hermes-estree": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.20.1.tgz", - "integrity": "sha512-SQpZK4BzR48kuOg0v4pb3EAGNclzIlqMj3Opu/mu7bbAoFw6oig6cEt/RAi0zTFW/iW6Iz9X9ggGuZTAZ/yZHg==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", "dev": true }, "hermes-parser": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.20.1.tgz", - "integrity": "sha512-BL5P83cwCogI8D7rrDCgsFY0tdYUtmFP9XaXtl2IQjC+2Xo+4okjfXintlTxcIwl4qeGddEl28Z11kbVIw0aNA==", + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", "dev": true, "requires": { - "hermes-estree": "0.20.1" + "hermes-estree": "0.25.1" } }, "hoist-non-react-statics": { @@ -17393,8 +17400,8 @@ "@types/history": "^4.7.11", "@types/mocha": "^10.0.0", "@types/node-gettext": "^3.0.3", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", + "@types/react": "^19.1.9", + "@types/react-dom": "^19.1.7", "@types/react-router": "^5.1.19", "@types/sinon": "^10.0.13", "@types/sprintf-js": "^1.1.2", @@ -17409,8 +17416,8 @@ "electron-builder": "26.0.18", "electron-devtools-installer": "^3.2.0", "eslint-plugin-react": "^7.36.1", - "eslint-plugin-react-compiler": "^0.0.0-experimental-42acc6a-20241001", - "eslint-plugin-react-hooks": "^0.0.0-experimental-2d16326d-20240930", + "eslint-plugin-react-compiler": "^19.1.0-rc.2", + "eslint-plugin-react-hooks": "^5.2.0", "gettext-extractor": "^3.5.4", "gettext-parser": "^6.0.0", "gl-matrix": "^3.4.3", @@ -17422,9 +17429,9 @@ "nseventforwarder": "0.0.0", "playwright": "^1.41.1", "postject": "^1.0.0-alpha.6", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-redux": "^7.2.9", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-redux": "^9.2.0", "react-router": "^5.3.4", "redux": "^4.2.0", "simple-plist": "^1.3.1", @@ -17620,6 +17627,32 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "react": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", + "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==" + }, + "react-dom": { + "version": "19.1.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.1.tgz", + "integrity": "sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==", + "requires": { + "scheduler": "^0.26.0" + } + }, + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==" + }, "which": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", @@ -18179,6 +18212,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "peer": true, "requires": { "loose-envify": "^1.1.0" } @@ -18187,6 +18221,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, "requires": { "loose-envify": "^1.1.0", "scheduler": "^0.23.2" @@ -18198,23 +18233,12 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, "react-redux": { - "version": "7.2.9", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", - "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "requires": { - "@babel/runtime": "^7.15.4", - "@types/react-redux": "^7.1.20", - "hoist-non-react-statics": "^3.3.2", - "loose-envify": "^1.4.0", - "prop-types": "^15.7.2", - "react-is": "^17.0.2" - }, - "dependencies": { - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" - } + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" } }, "react-refresh": { @@ -18314,12 +18338,11 @@ } }, "redux": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", - "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", - "requires": { - "@babel/runtime": "^7.9.2" - } + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "optional": true, + "peer": true }, "reflect.getprototypeof": { "version": "1.0.6", @@ -18578,6 +18601,7 @@ "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "peer": true, "requires": { "loose-envify": "^1.1.0" } @@ -19397,6 +19421,12 @@ "punycode": "^2.1.0" } }, + "use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "requires": {} + }, "utf8-byte-length": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", diff --git a/desktop/packages/mullvad-vpn/package.json b/desktop/packages/mullvad-vpn/package.json index 1ba5754669..10d115feda 100644 --- a/desktop/packages/mullvad-vpn/package.json +++ b/desktop/packages/mullvad-vpn/package.json @@ -20,9 +20,9 @@ "management-interface": "0.0.0", "node-gettext": "^3.0.0", "nseventforwarder": "0.0.0", - "react": "^18.3.1", - "react-dom": "^18.3.1", - "react-redux": "^7.2.9", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "react-redux": "^9.2.0", "react-router": "^5.3.4", "redux": "^4.2.0", "simple-plist": "^1.3.1", @@ -40,8 +40,8 @@ "@types/history": "^4.7.11", "@types/mocha": "^10.0.0", "@types/node-gettext": "^3.0.3", - "@types/react": "^18.3.3", - "@types/react-dom": "^18.3.0", + "@types/react": "^19.1.9", + "@types/react-dom": "^19.1.7", "@types/react-router": "^5.1.19", "@types/sinon": "^10.0.13", "@types/sprintf-js": "^1.1.2", @@ -55,8 +55,8 @@ "electron-builder": "26.0.18", "electron-devtools-installer": "^3.2.0", "eslint-plugin-react": "^7.36.1", - "eslint-plugin-react-compiler": "^0.0.0-experimental-42acc6a-20241001", - "eslint-plugin-react-hooks": "^0.0.0-experimental-2d16326d-20240930", + "eslint-plugin-react-compiler": "^19.1.0-rc.2", + "eslint-plugin-react-hooks": "^5.2.0", "gettext-extractor": "^3.5.4", "globals": "^15.9.0", "mocha": "^10.8.2", diff --git a/desktop/packages/mullvad-vpn/src/main/windows-pe-parser.ts b/desktop/packages/mullvad-vpn/src/main/windows-pe-parser.ts index f4d6ebc852..fbc670e128 100644 --- a/desktop/packages/mullvad-vpn/src/main/windows-pe-parser.ts +++ b/desktop/packages/mullvad-vpn/src/main/windows-pe-parser.ts @@ -150,7 +150,7 @@ export class ArrayValue<T extends ArrayWrapper = ArrayWrapper> extends Value<T> const datatype = this.datatype.array[0]; const itemSize = Value.sizeOf(datatype); const offset = index * itemSize; - const buffer = this.buffer.slice(offset, offset + itemSize); + const buffer = this.buffer.subarray(offset, offset + itemSize); return this.createNew(buffer, datatype, offset) as U; } @@ -172,7 +172,7 @@ export class StructValue<T extends StructWrapper = StructWrapper> extends Value< const slicedType = { struct: this.datatype.struct.slice(0, index) }; const offset = Value.sizeOf(slicedType); const size = Value.sizeOf(datatype); - const buffer = this.buffer.slice(offset, offset + size); + const buffer = this.buffer.subarray(offset, offset + size); return this.createNew(buffer, datatype, offset) as U; } diff --git a/desktop/packages/mullvad-vpn/src/renderer/app.tsx b/desktop/packages/mullvad-vpn/src/renderer/app.tsx index 368654e475..44ee6d8084 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/app.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/app.tsx @@ -1,5 +1,5 @@ import { StrictMode } from 'react'; -import { batch, Provider } from 'react-redux'; +import { Provider } from 'react-redux'; import { Router } from 'react-router'; import { bindActionCreators } from 'redux'; import { StyleSheetManager } from 'styled-components'; @@ -920,32 +920,30 @@ export default class AppRenderer { this.tunnelState = tunnelState; - batch(() => { - switch (tunnelState.state) { - case 'connecting': - actions.connection.connecting(tunnelState.details, tunnelState.featureIndicators); - break; + switch (tunnelState.state) { + case 'connecting': + actions.connection.connecting(tunnelState.details, tunnelState.featureIndicators); + break; - case 'connected': - actions.connection.connected(tunnelState.details, tunnelState.featureIndicators); - break; + case 'connected': + actions.connection.connected(tunnelState.details, tunnelState.featureIndicators); + break; - case 'disconnecting': - actions.connection.disconnecting(tunnelState.details); - break; + case 'disconnecting': + actions.connection.disconnecting(tunnelState.details); + break; - case 'disconnected': - actions.connection.disconnected(tunnelState.lockedDown); - break; + case 'disconnected': + actions.connection.disconnected(tunnelState.lockedDown); + break; - case 'error': - actions.connection.blocked(tunnelState.details); - break; - } + case 'error': + actions.connection.blocked(tunnelState.details); + break; + } - // Update the location when entering a new tunnel state since it's likely changed. - this.updateLocation(); - }); + // Update the location when entering a new tunnel state since it's likely changed. + this.updateLocation(); } private setSettings(newSettings: ISettings) { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx index f932139a2b..b7c1f2354a 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/Account.tsx @@ -37,6 +37,11 @@ export default function Account() { }); const onMount = useEffectEvent(() => updateAccountData()); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => onMount(), []); // Hack needed because if we just call `logout` directly in `onClick` diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/AriaGroup.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/AriaGroup.tsx index 184971b562..59536e6109 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/AriaGroup.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/AriaGroup.tsx @@ -78,7 +78,7 @@ export function AriaInputGroup(props: IAriaGroupProps) { } interface IAriaElementProps { - children: React.ReactElement; + children: React.ReactElement<React.LabelHTMLAttributes<HTMLLabelElement>>; } export function AriaInput(props: IAriaElementProps) { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ErrorBoundary.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ErrorBoundary.tsx index 84425471cf..b289f2cd75 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/ErrorBoundary.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/ErrorBoundary.tsx @@ -40,7 +40,7 @@ export default class ErrorBoundary extends React.Component<IProps, IState> { messages .pgettext('error-boundary-view', 'Something went wrong. Please contact us at %(email)s') .split('%(email)s', 2); - reachBackMessage.splice(1, 0, <Email>{strings.supportEmail}</Email>); + void reachBackMessage.splice(1, 0, <Email>{strings.supportEmail}</Email>); return <ErrorView settingsUnavailable>{reachBackMessage}</ErrorView>; } else { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Focus.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Focus.tsx index c29cbe653e..116c2ccb11 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Focus.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/Focus.tsx @@ -66,7 +66,7 @@ function Focus(props: IFocusProps, ref: React.Ref<IFocusHandle>) { export default React.memo(React.forwardRef(Focus)); interface IFocusFallbackProps { - children: React.ReactElement; + children: React.ReactElement<React.HTMLAttributes<HTMLElement>>; } export function FocusFallback(props: IFocusFallbackProps) { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/KeyboardNavigation.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/KeyboardNavigation.tsx index 2dff95ec5d..79fde5e536 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/KeyboardNavigation.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/KeyboardNavigation.tsx @@ -129,6 +129,11 @@ function BackActionTracker(props: IBackActionTracker) { props.registerBackAction(backActions.at(0)); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => registerBackActionEvent(backActions), [backActions]); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/List.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/List.tsx index 4961855fba..3773b563e2 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/List.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/List.tsx @@ -53,6 +53,11 @@ export default function List<T>(props: ListProps<T>) { }); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => itemChangeEvent(props.items), [props.items]); useEffect(() => { @@ -79,6 +84,11 @@ export default function List<T>(props: ListProps<T>) { }); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => handleDisplayItemsChange(displayItems), [displayItems]); useEffect( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/MacOsScrollbarDetection.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/MacOsScrollbarDetection.tsx index 520b6f3f3b..0e862b7be5 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/MacOsScrollbarDetection.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/MacOsScrollbarDetection.tsx @@ -35,6 +35,11 @@ export default function MacOsScrollbarDetection() { } }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => detectVisibility(visibility), [visibility]); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Map.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Map.tsx index c4df7ebbbe..a8e41e8078 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Map.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/Map.tsx @@ -34,9 +34,12 @@ export default function Map() { const hasLocationValue = hasLocation(connection); const location = useMemo<Coordinate | undefined>(() => { - return hasLocationValue ? connection : defaultLocation; - // eslint-disable-next-line react-compiler/react-compiler - // eslint-disable-next-line react-hooks/exhaustive-deps + return hasLocationValue + ? { + latitude: connection.latitude, + longitude: connection.longitude, + } + : defaultLocation; }, [hasLocationValue, connection.longitude, connection.latitude]); if (window.env.e2e) { @@ -84,19 +87,17 @@ function MapInner(props: MapInnerProps) { const { getMapData } = useAppContext(); // When location or connection state changes it's stored here until passed to 3dmap - const newParams = useRef<MapParams>(); + const newParams = useRef<MapParams>(undefined); // This is set to true when rendering should be paused const pause = useRef<boolean>(false); - const mapRef = useRef<GlMap>(); - const canvasRef = useRef<HTMLCanvasElement>(); + const mapRef = useRef<GlMap>(undefined); + const canvasRef = useRef<HTMLCanvasElement>(undefined); - // eslint-disable-next-line react-compiler/react-compiler const width = applyPixelRatio(canvasRef.current?.clientWidth ?? window.innerWidth); // This constant is used for the height the first frame that is rendered only. - // eslint-disable-next-line react-compiler/react-compiler const height = applyPixelRatio(canvasRef.current?.clientHeight ?? 493); // Hack to rerender when window size changes or when ref is set. @@ -125,6 +126,11 @@ function MapInner(props: MapInnerProps) { } }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps const render = useCallback(() => requestAnimationFrame(animationFrameCallback), []); // This is called when the canvas has been rendered the first time and initializes the gl context @@ -171,11 +177,21 @@ function MapInner(props: MapInnerProps) { useEffect(() => { addEventListener('resize', onSizeChange); return () => removeEventListener('resize', onSizeChange); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { const unsubscribe = window.ipc.window.listenScaleFactorChange(onSizeChange); return () => unsubscribe(); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const devicePixelRatio = window.devicePixelRatio; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Modal.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Modal.tsx index ba2077ec03..85b73fa82a 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Modal.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/Modal.tsx @@ -55,7 +55,7 @@ interface IModalContainerProps { interface IModalContext { activeModal: boolean; setActiveModal: (value: boolean) => void; - previousActiveElement: React.MutableRefObject<HTMLElement | undefined>; + previousActiveElement: React.RefObject<HTMLElement | undefined>; } const noActiveModalContextError = new Error('ActiveModalContext.Provider missing'); @@ -66,14 +66,14 @@ const ActiveModalContext = React.createContext<IModalContext>({ setActiveModal(_value) { throw noActiveModalContextError; }, - get previousActiveElement(): React.MutableRefObject<HTMLElement | undefined> { + get previousActiveElement(): React.RefObject<HTMLElement | undefined> { throw noActiveModalContextError; }, }); export function ModalContainer(props: IModalContainerProps) { const [activeModal, setActiveModal] = useState(false); - const previousActiveElement = useRef<HTMLElement>(); + const previousActiveElement = useRef<HTMLElement>(undefined); const contextValue = useMemo( () => ({ @@ -193,6 +193,11 @@ export function ModalAlert(props: IModalAlertProps & { isOpen: boolean }) { })); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => onOpenStateChange(isOpen), [isOpen]); if (!openState.wasOpen && !isOpen && !openState.isClosing) { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx index 0c088674aa..8aadf5b1c6 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/NavigationScrollbars.tsx @@ -21,7 +21,7 @@ export const NavigationScrollbars = React.forwardRef(function NavigationScrollba const { setNavigationHistory } = useAppContext(); const { onScroll } = useContext(NavigationScrollContext); - const ref = useRef<CustomScrollbarsRef>(); + const ref = useRef<CustomScrollbarsRef>(undefined); const combinedRefs = useCombinedRefs(forwardedRef, ref); const beforeunload = useEffectEvent(() => { @@ -34,6 +34,11 @@ export const NavigationScrollbars = React.forwardRef(function NavigationScrollba useEffect(() => { window.addEventListener('beforeunload', beforeunload); return () => window.removeEventListener('beforeunload', beforeunload); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const onMount = useEffectEvent(() => { @@ -53,6 +58,11 @@ export const NavigationScrollbars = React.forwardRef(function NavigationScrollba useLayoutEffect(() => { onMount(); return () => onUnmount(); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const handleScroll = useCallback( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx index e2adf4d10f..83e6efb322 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/ProblemReport.tsx @@ -231,7 +231,7 @@ function Sent() { messages .pgettext('support-view', 'If needed we will contact you at %(email)s') .split('%(email)s', 2); - reachBackMessage.splice(1, 0, <StyledEmail key="email">{email}</StyledEmail>); + void reachBackMessage.splice(1, 0, <StyledEmail key="email">{email}</StyledEmail>); return ( <StyledContent> @@ -422,7 +422,7 @@ const useCollectLog = () => { const { collectProblemReport } = useAppContext(); const accountHistory = useSelector((state) => state.account.accountHistory); - const collectLogPromise = useRef<Promise<string>>(); + const collectLogPromise = useRef<Promise<string>>(undefined); const collectLog = useCallback(async (): Promise<string> => { if (collectLogPromise.current) { @@ -504,6 +504,11 @@ const ProblemReportContextProvider = ({ children }: { children: ReactNode }) => /** * Save the form whenever email or message gets updated */ + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => onMount(email, message), [email, message]); const value: ProblemReportContextType = useMemo( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx index e8e47bf15d..0eda7027ca 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/ProxyForm.tsx @@ -292,6 +292,11 @@ function EditShadowsocks(props: EditProxyProps<ShadowsocksCustomProxy>) { ); // Report back to form component with the proxy values when all required values are set. + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => onUpdate(ip, port, password, cipher), [ip, port, password, cipher]); return ( @@ -371,6 +376,11 @@ function EditSocks5Remote(props: EditProxyProps<Socks5RemoteCustomProxy>) { ); // Report back to form component with the proxy values when all required values are set. + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => onUpdate(ip, port, username, password), [ip, port, username, password]); return ( @@ -467,6 +477,11 @@ function EditSocks5Local(props: EditProxyProps<Socks5LocalCustomProxy>) { useEffect( () => onUpdate(remoteIp, remotePort, localPort, remoteTransportProtocol), + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps [remoteIp, remotePort, localPort, remoteTransportProtocol], ); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SearchBar.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SearchBar.tsx index edbcb6df97..fb896b95e0 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/SearchBar.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/SearchBar.tsx @@ -86,6 +86,11 @@ export default function SearchBar(props: ISearchBarProps) { } }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => focusInput(), []); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx index 541e5cab44..f25e411cc3 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsImport.tsx @@ -100,6 +100,11 @@ export default function SettingsImport() { } }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => void onMount(), []); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx index 26fe69ab7c..d18f671b5f 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx @@ -126,6 +126,11 @@ function LinuxSplitTunnelingSettings(props: IPlatformSplitTunnelingSettingsProps }); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => void updateApplications(), []); const launchApplication = useCallback( @@ -367,6 +372,11 @@ export function SplitTunnelingSettings(props: IPlatformSplitTunnelingSettingsPro }); }); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => void onMount(), []); const filteredSplitApplications = useMemo( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx index e7f129ca73..c1d9405b4b 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Input.tsx @@ -147,6 +147,11 @@ function InputWithRef(props: IInputProps, forwardedRef: React.Ref<HTMLInputEleme // then we want to update the value. useEffect(() => { handleInitialValueChange(props.initialValue); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, [props.initialValue]); const valid = validateValue?.(value); @@ -373,6 +378,11 @@ export function RowInput(props: IRowInputProps) { useEffect(() => { focusOnMount(); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); useEffect(() => { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx index a21a70c034..38cdbb6820 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Section.tsx @@ -79,6 +79,11 @@ export function ExpandableSection(props: ExpandableSectionProps) { useEffect(() => { updateHistory(expanded); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, [expanded]); const title = ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsForm.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsForm.tsx index 9a901d88d8..f986101e04 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsForm.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsForm.tsx @@ -43,6 +43,11 @@ export function useSettingsFormSubmittableReporter() { useEffect(() => { // Remove from required fields if unmounted. return () => clearRequiredFields(); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return reportInputSubmittable; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsSelect.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsSelect.tsx index 3f6ccf3297..9acecc0222 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsSelect.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsSelect.tsx @@ -145,6 +145,11 @@ export function SettingsSelect<T extends string>(props: SettingsSelectProps<T>) // Update the parent when the value changes. useEffect(() => { updateEvent(value); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, [value]); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsTextInput.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsTextInput.tsx index 73b7a55e4e..45ced44d66 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsTextInput.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/SettingsTextInput.tsx @@ -119,6 +119,11 @@ function Input<T extends ValueTypes>(props: InputProps<T>) { // Report submittability to form context on load. useEffect(() => { updateReportSubmittable(); + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ( diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx index 0c093af313..89f9edaee5 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/RelayListContext.tsx @@ -320,6 +320,11 @@ function useExpandedLocations(filteredLocations: Array<IRelayLocationCountryRedu ); // Expand locations when filters are changed + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps useEffect(() => expandLocationsForSearch(filteredLocations), [filteredLocations]); return { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/ScrollPositionContext.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/ScrollPositionContext.tsx index 55ee8dae97..73d402393b 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/ScrollPositionContext.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/ScrollPositionContext.tsx @@ -13,11 +13,11 @@ import { SpacePreAllocationView } from './SpacePreAllocationView'; interface ScrollPositionContext { scrollPositions: React.RefObject<Partial<Record<LocationType, ScrollPosition>>>; // The selected location element is used to scroll to it when opening the view - selectedLocationRef: React.RefObject<HTMLDivElement>; + selectedLocationRef: React.RefObject<HTMLDivElement | null>; // The scroll view container is used to get the current scroll position and to restore an old one - scrollViewRef: React.RefObject<CustomScrollbarsRef>; + scrollViewRef: React.RefObject<CustomScrollbarsRef | null>; // The space pre allocation view is used to enable smooth scrolling when opening locations - spacePreAllocationViewRef: React.RefObject<SpacePreAllocationView>; + spacePreAllocationViewRef: React.RefObject<SpacePreAllocationView | null>; saveScrollPosition: () => void; resetScrollPositions: () => void; scrollIntoView: (rect: DOMRect) => void; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SpacePreAllocationView.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SpacePreAllocationView.tsx index 4b493aeed1..40d1e241b8 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SpacePreAllocationView.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/select-location/SpacePreAllocationView.tsx @@ -5,7 +5,7 @@ interface ISpacePreAllocationView { } export class SpacePreAllocationView extends React.Component<ISpacePreAllocationView> { - private ref = React.createRef<HTMLDivElement>(); + private ref = React.createRef<HTMLDivElement | null>(); public allocate(height: number) { if (this.ref.current) { diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/api-access-methods.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/api-access-methods.ts index 90d406cc3d..d52d9ab0e2 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/api-access-methods.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/api-access-methods.ts @@ -22,7 +22,7 @@ export function useApiAccessMethodTest( const [testResult, setTestResult] = useState<boolean>(); // We keep the promise for the most recent test to compare it when we receive the results to know // if it's canceled or not. - const lastTestPromise = useRef<Promise<boolean>>(); + const lastTestPromise = useRef<Promise<boolean>>(undefined); // A few seconds after the test has finished the result should not be displayed anymore. This // scheduler is used to clear it. diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/history.tsx b/desktop/packages/mullvad-vpn/src/renderer/lib/history.tsx index f209dc8acf..bd2cd15883 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/history.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/history.tsx @@ -221,7 +221,7 @@ export default class History { } private getRandomKey() { - return Math.random().toString(36).substr(8); + return Math.random().toString(36).substring(8); } } diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/transition-hooks.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/transition-hooks.ts index ee4a8f7eae..e48048c058 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/transition-hooks.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/transition-hooks.ts @@ -30,7 +30,7 @@ export function useAfterTransition() { export function useViewTransitions(onTransition?: () => void): Location<LocationState> { const history = useHistory(); const [currentLocation, setCurrentLocation] = useState(history.location); - const queuedLocationRef = useRef<QueueItem | undefined>(); + const queuedLocationRef = useRef<QueueItem>(undefined); const { setNavigationHistory } = useAppContext(); const reduceMotion = getReduceMotion(); @@ -83,6 +83,11 @@ export function useViewTransitions(onTransition?: () => void): Location<Location return () => { unobserveHistory?.(); }; + // These lint rules are disabled for now because the react plugin for eslint does + // not understand that useEffectEvent should not be added to the dependency array. + // Enable these rules again when eslint can lint useEffectEvent properly. + // eslint-disable-next-line react-compiler/react-compiler + // eslint-disable-next-line react-hooks/exhaustive-deps }, [history]); return currentLocation; diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/utility-hooks.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/utility-hooks.ts index 1efc49c804..0fe9a9314e 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/utility-hooks.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/utility-hooks.ts @@ -14,8 +14,8 @@ export function useMounted() { return isMounted; } -export function useStyledRef<T>(): React.MutableRefObject<T> { - return useRef() as React.MutableRefObject<T>; +export function useStyledRef<T>(): React.RefObject<T | null> { + return useRef<T>(null); } export function useCombinedRefs<T>(...refs: (React.Ref<T> | undefined)[]): React.RefCallback<T> { @@ -26,7 +26,7 @@ export function assignToRef<T>(element: T | null, ref?: React.Ref<T>) { if (typeof ref === 'function') { ref(element); } else if (ref && element) { - (ref as React.MutableRefObject<T>).current = element; + (ref as React.RefObject<T>).current = element; } } |
