From e6c64dfd773530378342cfca35030250b946fdfb Mon Sep 17 00:00:00 2001 From: Antoine Clausse Date: Mon, 23 Jun 2025 11:09:08 +0200 Subject: [PATCH] [web] Add `window.` prefix to globals and add `no-restricted-globals` rule (#26422) * Add `no-restricted-globals` eslint rule Co-authored-by: Rebeka * Change `self` to `window.self` * Change `innerWidth` to `window.innerWidth` * Change `confirm` to `window.confirm` * Change `location` to `window.location` * Use `location` from `useLocation` hook * Use location from useLocation hook Co-authored-by: Antoine * Disable no-restricted-globals eslint rule for use of 'self' * Use `confusing-browser-globals` from npm * Prevent unexpected globals in workers, using `no-undef` * Use `self` as a global in workers * Use unexpected globals in workers, using `no-restricted-globals` in workers --------- Co-authored-by: Rebeka Co-authored-by: Rebeka GitOrigin-RevId: 526986799f5f2edf53c7d978fa85c1e98189565f --- package-lock.json | 22 +++++++++++++++++++ services/web/.eslintrc.js | 17 ++++++++++++++ .../emails/add-secondary-email-prompt.tsx | 2 ++ .../components/emails/confirm-email-form.tsx | 2 ++ .../components/sharing-updates-root.tsx | 8 ++++--- .../js/infrastructure/error-reporter.ts | 2 +- services/web/package.json | 2 ++ 7 files changed, 51 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 53388a5732..c38221dd63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18024,6 +18024,13 @@ "proto-list": "~1.2.1" } }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true, + "license": "MIT" + }, "node_modules/connect-flash": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", @@ -45366,6 +45373,7 @@ "chartjs-plugin-datalabels": "^2.2.0", "cheerio": "^1.0.0-rc.3", "classnames": "^2.2.6", + "confusing-browser-globals": "^1.0.11", "cookie-signature": "^1.2.1", "copy-webpack-plugin": "^11.0.0", "core-js": "^3.41.0", @@ -45392,6 +45400,7 @@ "formik": "^2.2.9", "fuse.js": "^3.0.0", "glob": "^7.1.6", + "globals": "^16.2.0", "handlebars": "^4.7.8", "handlebars-loader": "^1.7.3", "html-webpack-plugin": "^5.5.3", @@ -46342,6 +46351,19 @@ "node": ">=18.11.0" } }, + "services/web/node_modules/globals": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.2.0.tgz", + "integrity": "sha512-O+7l9tPdHCU320IigZZPj5zmRCFG9xHmx9cU8FqU2Rp+JN714seHV+2S9+JslCpY4gJwU2vOGox0wzgae/MCEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "services/web/node_modules/google-auth-library": { "version": "8.7.0", "resolved": "https://registry.npmjs.org/google-auth-library/-/google-auth-library-8.7.0.tgz", diff --git a/services/web/.eslintrc.js b/services/web/.eslintrc.js index ef3cf11de5..7dd154c942 100644 --- a/services/web/.eslintrc.js +++ b/services/web/.eslintrc.js @@ -1,3 +1,7 @@ +const _ = require('lodash') +const confusingBrowserGlobals = require('confusing-browser-globals') +const globals = require('globals') + module.exports = { root: true, parser: '@typescript-eslint/parser', @@ -19,6 +23,7 @@ module.exports = { }, rules: { 'no-constant-binary-expression': 'error', + 'no-restricted-globals': ['error', ...confusingBrowserGlobals], // do not allow importing of implicit dependencies. 'import/no-extraneous-dependencies': 'error', @@ -531,5 +536,17 @@ module.exports = { 'no-console': 'error', }, }, + { + files: ['**/*.worker.{js,ts}'], + rules: { + 'no-restricted-globals': [ + 'error', + ..._.difference( + Object.keys({ ...globals.browser, ...globals.node }), + Object.keys(globals.worker) + ), + ], + }, + }, ], } diff --git a/services/web/frontend/js/features/settings/components/emails/add-secondary-email-prompt.tsx b/services/web/frontend/js/features/settings/components/emails/add-secondary-email-prompt.tsx index 04bc4edbd1..8355138a14 100644 --- a/services/web/frontend/js/features/settings/components/emails/add-secondary-email-prompt.tsx +++ b/services/web/frontend/js/features/settings/components/emails/add-secondary-email-prompt.tsx @@ -8,6 +8,7 @@ import MaterialIcon from '@/shared/components/material-icon' import { sendMB } from '@/infrastructure/event-tracking' import { ReCaptcha2 } from '../../../../shared/components/recaptcha-2' import { useRecaptcha } from '../../../../shared/hooks/use-recaptcha' +import { useLocation } from '@/shared/hooks/use-location' import { postJSON } from '../../../../infrastructure/fetch-json' import RecaptchaConditions from '@/shared/components/recaptcha-conditions' @@ -25,6 +26,7 @@ export function AddSecondaryEmailPrompt() { const [error, setError] = useState() const [isSubmitting, setIsSubmitting] = useState(false) const { ref: recaptchaRef, getReCaptchaToken } = useRecaptcha() + const location = useLocation() if (!isReady) { return null diff --git a/services/web/frontend/js/features/settings/components/emails/confirm-email-form.tsx b/services/web/frontend/js/features/settings/components/emails/confirm-email-form.tsx index d82a43315c..bf08b5dcfd 100644 --- a/services/web/frontend/js/features/settings/components/emails/confirm-email-form.tsx +++ b/services/web/frontend/js/features/settings/components/emails/confirm-email-form.tsx @@ -9,6 +9,7 @@ import MaterialIcon from '@/shared/components/material-icon' import { sendMB } from '@/infrastructure/event-tracking' import OLFormLabel from '@/features/ui/components/ol/ol-form-label' import OLButton from '@/features/ui/components/ol/ol-button' +import { useLocation } from '@/shared/hooks/use-location' type Feedback = { type: 'input' | 'alert' @@ -267,6 +268,7 @@ function ConfirmEmailSuccessfullForm({ successButtonText: string redirectTo: string }) { + const location = useLocation() const submitHandler = (e: FormEvent) => { e.preventDefault() location.assign(redirectTo) diff --git a/services/web/frontend/js/features/token-access/components/sharing-updates-root.tsx b/services/web/frontend/js/features/token-access/components/sharing-updates-root.tsx index e7b0d96c2a..ade94ba304 100644 --- a/services/web/frontend/js/features/token-access/components/sharing-updates-root.tsx +++ b/services/web/frontend/js/features/token-access/components/sharing-updates-root.tsx @@ -12,6 +12,7 @@ import { sendMB } from '@/infrastructure/event-tracking' import LeaveProjectModal from './leave-project-modal' import OLButton from '@/features/ui/components/ol/ol-button' +import { useLocation } from '@/shared/hooks/use-location' function SharingUpdatesRoot() { const [showModal, setShowModal] = useState(false) @@ -20,6 +21,7 @@ function SharingUpdatesRoot() { const { isLoading, isSuccess, isError, runAsync } = useAsync() const projectId = getMeta('ol-project_id') + const location = useLocation() const joinProject = useCallback(() => { sendMB('notification-click', { name: 'link-sharing-collaborator', @@ -30,7 +32,7 @@ function SharingUpdatesRoot() { location.assign(`/project/${projectId}`) }) .catch(debugConsole.error) - }, [runAsync, projectId]) + }, [runAsync, projectId, location]) const viewProject = useCallback(() => { sendMB('notification-click', { @@ -42,7 +44,7 @@ function SharingUpdatesRoot() { location.assign(`/project/${projectId}`) }) .catch(debugConsole.error) - }, [runAsync, projectId]) + }, [runAsync, projectId, location]) const leaveProject = useCallback(() => { sendMB('notification-click', { @@ -54,7 +56,7 @@ function SharingUpdatesRoot() { location.assign('/project') }) .catch(debugConsole.error) - }, [runAsync, projectId]) + }, [runAsync, projectId, location]) if (!isReady) { return null diff --git a/services/web/frontend/js/infrastructure/error-reporter.ts b/services/web/frontend/js/infrastructure/error-reporter.ts index 5d5734535a..e70833860c 100644 --- a/services/web/frontend/js/infrastructure/error-reporter.ts +++ b/services/web/frontend/js/infrastructure/error-reporter.ts @@ -78,7 +78,7 @@ function sentryReporter() { const refererUrl = new URL(event.request.headers.Referer) if ( - refererUrl.hostname === location.hostname && + refererUrl.hostname === window.location.hostname && refererUrl.pathname.startsWith('/read/') ) { refererUrl.pathname = '/read/' diff --git a/services/web/package.json b/services/web/package.json index bdc42673bb..d946c62151 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -278,6 +278,7 @@ "chartjs-plugin-datalabels": "^2.2.0", "cheerio": "^1.0.0-rc.3", "classnames": "^2.2.6", + "confusing-browser-globals": "^1.0.11", "cookie-signature": "^1.2.1", "copy-webpack-plugin": "^11.0.0", "core-js": "^3.41.0", @@ -304,6 +305,7 @@ "formik": "^2.2.9", "fuse.js": "^3.0.0", "glob": "^7.1.6", + "globals": "^16.2.0", "handlebars": "^4.7.8", "handlebars-loader": "^1.7.3", "html-webpack-plugin": "^5.5.3",