diff --git a/.eslintrc.js b/.eslintrc.js index 6fd4392e60..7de812ea6e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,3 +1,5 @@ +const restrictedGlobals = require('confusing-browser-globals'); + module.exports = { root: true, plugins: [ @@ -39,6 +41,7 @@ module.exports = { 'no-floating-decimal': ['error'], 'no-multi-spaces': ['error'], 'no-multiple-empty-lines': ['error', { 'max': 1 }], + 'no-restricted-globals': ['error'].concat(restrictedGlobals), 'no-trailing-spaces': ['error'], '@babel/no-unused-expressions': ['error', { 'allowShortCircuit': true, 'allowTernary': true, 'allowTaggedTemplates': true }], //'no-unused-vars': ['error', { 'vars': 'all', 'args': 'none', 'ignoreRestSiblings': true }], diff --git a/package.json b/package.json index 654845113c..27284ccefc 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "autoprefixer": "^9.8.6", "babel-loader": "^8.0.6", "browser-sync": "^2.26.12", + "confusing-browser-globals": "^1.0.9", "copy-webpack-plugin": "^5.1.1", "css-loader": "^4.2.1", "cssnano": "^4.1.10", diff --git a/src/components/appRouter.js b/src/components/appRouter.js index 28826c55cc..f986e71357 100644 --- a/src/components/appRouter.js +++ b/src/components/appRouter.js @@ -41,7 +41,7 @@ class AppRouter { } }); - this.baseRoute = self.location.href.split('?')[0].replace(this.getRequestFile(), ''); + this.baseRoute = window.location.href.split('?')[0].replace(this.getRequestFile(), ''); // support hashbang this.baseRoute = this.baseRoute.split('#')[0]; if (this.baseRoute.endsWith('/') && !this.baseRoute.endsWith('://')) { @@ -55,7 +55,7 @@ class AppRouter { * @private */ setBaseRoute() { - let baseRoute = self.location.pathname.replace(this.getRequestFile(), ''); + let baseRoute = window.location.pathname.replace(this.getRequestFile(), ''); if (baseRoute.lastIndexOf('/') === baseRoute.length - 1) { baseRoute = baseRoute.substring(0, baseRoute.length - 1); } @@ -182,7 +182,7 @@ class AppRouter { return false; } - return history.length > 1; + return window.history.length > 1; } current() { @@ -258,7 +258,7 @@ class AppRouter { pushState(state, title, url) { state.navigate = false; - history.pushState(state, title, url); + window.history.pushState(state, title, url); } enableNativeHistory() { @@ -594,7 +594,7 @@ class AppRouter { } getRequestFile() { - let path = self.location.pathname || ''; + let path = window.location.pathname || ''; const index = path.lastIndexOf('/'); if (index !== -1) { diff --git a/src/components/apphost.js b/src/components/apphost.js index c3e9342827..33ca5a0b79 100644 --- a/src/components/apphost.js +++ b/src/components/apphost.js @@ -55,7 +55,7 @@ function replaceAll(originalString, strReplace, strWith) { function generateDeviceId() { const keys = []; - if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), self.btoa) { + if (keys.push(navigator.userAgent), keys.push(new Date().getTime()), window.btoa) { const result = replaceAll(btoa(keys.join('|')), '=', '1'); return Promise.resolve(result); } @@ -404,9 +404,9 @@ document.addEventListener(visibilityChange, function () { } }, false); -if (self.addEventListener) { - self.addEventListener('focus', onAppVisible); - self.addEventListener('blur', onAppHidden); +if (window.addEventListener) { + window.addEventListener('focus', onAppVisible); + window.addEventListener('blur', onAppHidden); } export default appHost; diff --git a/src/components/confirm/confirm.js b/src/components/confirm/confirm.js index 0670816a53..eca612ccb8 100644 --- a/src/components/confirm/confirm.js +++ b/src/components/confirm/confirm.js @@ -19,7 +19,7 @@ export default (() => { } const text = replaceAll(options.text || '', '
', '\n'); - const result = confirm(text); + const result = window.confirm(text); if (result) { return Promise.resolve(); diff --git a/src/components/dialogHelper/dialogHelper.js b/src/components/dialogHelper/dialogHelper.js index b9256714fd..e1a267fed2 100644 --- a/src/components/dialogHelper/dialogHelper.js +++ b/src/components/dialogHelper/dialogHelper.js @@ -85,9 +85,9 @@ import 'scrollStyles'; } if (!self.closedByBack && isHistoryEnabled(dlg)) { - const state = history.state || {}; + const state = window.history.state || {}; if (state.dialogId === hash) { - history.back(); + window.history.back(); } } @@ -213,7 +213,7 @@ import 'scrollStyles'; export function close(dlg) { if (isOpened(dlg)) { if (isHistoryEnabled(dlg)) { - history.back(); + window.history.back(); } else { closeDialog(dlg); } diff --git a/src/components/playback/playbackorientation.js b/src/components/playback/playbackorientation.js index 1aa939da04..b73377bade 100644 --- a/src/components/playback/playbackorientation.js +++ b/src/components/playback/playbackorientation.js @@ -18,7 +18,7 @@ events.on(playbackManager, 'playbackstart', function (e, player, state) { if (isLocalVideo && layoutManager.mobile) { /* eslint-disable-next-line compat/compat */ - var lockOrientation = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation || (screen.orientation && screen.orientation.lock); + var lockOrientation = window.screen.lockOrientation || window.screen.mozLockOrientation || window.screen.msLockOrientation || (window.screen.orientation && window.screen.orientation.lock); if (lockOrientation) { try { @@ -39,7 +39,7 @@ events.on(playbackManager, 'playbackstart', function (e, player, state) { events.on(playbackManager, 'playbackstop', function (e, playbackStopInfo) { if (orientationLocked && !playbackStopInfo.nextMediaType) { /* eslint-disable-next-line compat/compat */ - var unlockOrientation = screen.unlockOrientation || screen.mozUnlockOrientation || screen.msUnlockOrientation || (screen.orientation && screen.orientation.unlock); + var unlockOrientation = window.screen.unlockOrientation || window.screen.mozUnlockOrientation || window.screen.msUnlockOrientation || (window.screen.orientation && window.screen.orientation.unlock); if (unlockOrientation) { try { diff --git a/src/components/require/requiretext.js b/src/components/require/requiretext.js index 8c68daed92..28ddeb21c8 100644 --- a/src/components/require/requiretext.js +++ b/src/components/require/requiretext.js @@ -2,7 +2,7 @@ define(function () { 'use strict'; // hack to work around the server's auto-redirection feature - var addRedirectPrevention = self.dashboardVersion != null && self.Dashboard && !self.AppInfo.isNativeApp; + var addRedirectPrevention = window.dashboardVersion != null && window.Dashboard && !window.AppInfo.isNativeApp; return { diff --git a/src/components/serviceworker/notifications.js b/src/components/serviceworker/notifications.js index 5f96d01a4d..339d521bbc 100644 --- a/src/components/serviceworker/notifications.js +++ b/src/components/serviceworker/notifications.js @@ -26,7 +26,7 @@ }); } - self.addEventListener('notificationclick', function (event) { + window.addEventListener('notificationclick', function (event) { var notification = event.notification; notification.close(); diff --git a/src/controllers/itemDetails/index.js b/src/controllers/itemDetails/index.js index 63225f6793..f837d3fc1d 100644 --- a/src/controllers/itemDetails/index.js +++ b/src/controllers/itemDetails/index.js @@ -1067,7 +1067,7 @@ import 'emby-select'; } function enableScrollX() { - return browser.mobile && screen.availWidth <= 1000; + return browser.mobile && window.screen.availWidth <= 1000; } function getPortraitShape(scrollX) { diff --git a/src/scripts/apploader.js b/src/scripts/apploader.js index e98c82e693..f5f6850c40 100644 --- a/src/scripts/apploader.js +++ b/src/scripts/apploader.js @@ -5,8 +5,8 @@ } const script = document.createElement('script'); - if (self.dashboardVersion) { - src += `?v=${self.dashboardVersion}`; + if (window.dashboardVersion) { + src += `?v=${window.dashboardVersion}`; } script.src = src; script.setAttribute('async', ''); @@ -35,10 +35,10 @@ // Promise() being missing on some legacy browser, and a funky one // is Promise() present but buggy on WebOS 2 window.Promise = undefined; - self.Promise = undefined; + window.Promise = undefined; } - if (!self.Promise) { + if (!window.Promise) { // Load Promise polyfill if they are not natively supported injectScriptElement( './libraries/npo.js', diff --git a/src/scripts/browser.js b/src/scripts/browser.js index b10587cb09..618d930ec8 100644 --- a/src/scripts/browser.js +++ b/src/scripts/browser.js @@ -210,7 +210,7 @@ if (userAgent.toLowerCase().indexOf('xbox') !== -1) { browser.tv = true; } browser.animate = typeof document !== 'undefined' && document.documentElement.animate != null; -browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || self.tizen != null; +browser.tizen = userAgent.toLowerCase().indexOf('tizen') !== -1 || window.tizen != null; browser.web0s = userAgent.toLowerCase().indexOf('Web0S'.toLowerCase()) !== -1; browser.edgeUwp = browser.edge && (userAgent.toLowerCase().indexOf('msapphost') !== -1 || userAgent.toLowerCase().indexOf('webview') !== -1); diff --git a/src/scripts/browserDeviceProfile.js b/src/scripts/browserDeviceProfile.js index 5befcb1df5..67c75da901 100644 --- a/src/scripts/browserDeviceProfile.js +++ b/src/scripts/browserDeviceProfile.js @@ -315,10 +315,12 @@ define(['browser'], function (browser) { // Not sure how to test for this var supportsMp2VideoAudio = browser.edgeUwp || browser.tizen || browser.web0s; + /* eslint-disable compat/compat */ var maxVideoWidth = browser.xboxOne ? - (self.screen ? self.screen.width : null) : + (window.screen ? window.screen.width : null) : null; + /* eslint-enable compat/compat */ if (options.maxVideoWidth) { maxVideoWidth = options.maxVideoWidth; } diff --git a/src/scripts/clientUtils.js b/src/scripts/clientUtils.js index 1bad8bc81c..70d42d0782 100644 --- a/src/scripts/clientUtils.js +++ b/src/scripts/clientUtils.js @@ -154,7 +154,7 @@ export function capabilities(appHost) { let capabilities = { PlayableMediaTypes: ['Audio', 'Video'], SupportedCommands: ['MoveUp', 'MoveDown', 'MoveLeft', 'MoveRight', 'PageUp', 'PageDown', 'PreviousLetter', 'NextLetter', 'ToggleOsd', 'ToggleContextMenu', 'Select', 'Back', 'SendKey', 'SendString', 'GoHome', 'GoToSettings', 'VolumeUp', 'VolumeDown', 'Mute', 'Unmute', 'ToggleMute', 'SetVolume', 'SetAudioStreamIndex', 'SetSubtitleStreamIndex', 'DisplayContent', 'GoToSearch', 'DisplayMessage', 'SetRepeatMode', 'SetShuffleQueue', 'ChannelUp', 'ChannelDown', 'PlayMediaSource', 'PlayTrailers'], - SupportsPersistentIdentifier: self.appMode === 'cordova' || self.appMode === 'android', + SupportsPersistentIdentifier: window.appMode === 'cordova' || window.appMode === 'android', SupportsMediaControl: true }; return Object.assign(capabilities, appHost.getPushTokenInfo()); diff --git a/src/scripts/libraryMenu.js b/src/scripts/libraryMenu.js index e1b0ff780d..07d59c76cc 100644 --- a/src/scripts/libraryMenu.js +++ b/src/scripts/libraryMenu.js @@ -799,7 +799,7 @@ import 'flexStyles'; } function getNavDrawerOptions() { - let drawerWidth = screen.availWidth - 50; + let drawerWidth = window.screen.availWidth - 50; drawerWidth = Math.max(drawerWidth, 240); drawerWidth = Math.min(drawerWidth, 320); return { diff --git a/src/scripts/multiDownload.js b/src/scripts/multiDownload.js index b4ad95a975..d1c717af0e 100644 --- a/src/scripts/multiDownload.js +++ b/src/scripts/multiDownload.js @@ -31,7 +31,7 @@ function sameDomain(url) { var a = document.createElement('a'); a.href = url; - return location.hostname === a.hostname && location.protocol === a.protocol; + return window.location.hostname === a.hostname && window.location.protocol === a.protocol; } function download(url) { @@ -62,4 +62,3 @@ export default function (urls) { download(url); }); } - diff --git a/src/scripts/site.js b/src/scripts/site.js index 48a5044f5e..2b778f191a 100644 --- a/src/scripts/site.js +++ b/src/scripts/site.js @@ -187,9 +187,9 @@ function initClient() { } function defineResizeObserver() { - if (self.ResizeObserver) { + if (window.ResizeObserver) { define('ResizeObserver', [], function () { - return self.ResizeObserver; + return window.ResizeObserver; }); } else { define('ResizeObserver', ['resize-observer-polyfill'], returnFirstDependency); @@ -248,8 +248,8 @@ function initClient() { } function onGlobalizeInit(browser, globalize) { - if (self.appMode === 'android') { - if (self.location.href.toString().toLowerCase().indexOf('start=backgroundsync') !== -1) { + if (window.appMode === 'android') { + if (window.location.href.toString().toLowerCase().indexOf('start=backgroundsync') !== -1) { return onAppReady(browser); } } @@ -400,7 +400,7 @@ function initClient() { function registerServiceWorker() { /* eslint-disable compat/compat */ - if (navigator.serviceWorker && self.appMode !== 'cordova' && self.appMode !== 'android') { + if (navigator.serviceWorker && window.appMode !== 'cordova' && window.appMode !== 'android') { try { navigator.serviceWorker.register('serviceworker.js'); } catch (err) { @@ -437,7 +437,7 @@ function initClient() { define('castSenderApiLoader', [componentsPath + '/castSenderApi'], returnFirstDependency); - if (self.appMode === 'cordova' || self.appMode === 'android' || self.appMode === 'standalone') { + if (window.appMode === 'cordova' || window.appMode === 'android' || window.appMode === 'standalone') { AppInfo.isNativeApp = true; } diff --git a/yarn.lock b/yarn.lock index 5f962daee2..d8a5e22e60 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2751,6 +2751,11 @@ config-chain@^1.1.11: ini "^1.3.4" proto-list "~1.2.1" +confusing-browser-globals@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.9.tgz#72bc13b483c0276801681871d4898516f8f54fdd" + integrity sha512-KbS1Y0jMtyPgIxjO7ZzMAuUpAKMt1SzCL9fsrKsX6b0zJPTaT0SiSPmewwVZg9UAO83HVIlEhZF84LIjZ0lmAw== + connect-history-api-fallback@^1: version "1.6.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"