From 5b9be17640f9f3a2f261b88f95f2829445d8562b Mon Sep 17 00:00:00 2001 From: noahdarveau-MSFT <109628470+noahdarveau-MSFT@users.noreply.github.com> Date: Wed, 6 Sep 2023 08:43:18 -0700 Subject: [PATCH] noahdarveau/ssr-safe-window (#1902) * replaced window references with ssrSafeWindow, updated blazor sdk version * Change files * reverted blazor sdk upgrade * updated changelog * Updated Changelog message Co-authored-by: Trevor Harris * removed unnecessary ssr environment check --------- Co-authored-by: Trevor Harris --- ...-1ca9663b-733f-4143-80b8-7dfa2ffbebe0.json | 7 ++++++ .../teams-js/src/internal/communication.ts | 4 ++-- packages/teams-js/src/internal/utils.ts | 23 +++++++++++++++++++ packages/teams-js/src/internal/videoUtils.ts | 6 ++--- .../inServerSideRenderingEnvironment.ts | 3 --- packages/teams-js/src/private/videoEx.ts | 2 +- packages/teams-js/src/public/app.ts | 3 +-- .../teams-js/src/public/authentication.ts | 3 ++- packages/teams-js/src/public/teamsAPIs.ts | 9 ++------ packages/teams-js/src/public/video.ts | 7 +++--- 10 files changed, 44 insertions(+), 23 deletions(-) create mode 100644 change/@microsoft-teams-js-1ca9663b-733f-4143-80b8-7dfa2ffbebe0.json delete mode 100644 packages/teams-js/src/private/inServerSideRenderingEnvironment.ts diff --git a/change/@microsoft-teams-js-1ca9663b-733f-4143-80b8-7dfa2ffbebe0.json b/change/@microsoft-teams-js-1ca9663b-733f-4143-80b8-7dfa2ffbebe0.json new file mode 100644 index 0000000000..835ced7214 --- /dev/null +++ b/change/@microsoft-teams-js-1ca9663b-733f-4143-80b8-7dfa2ffbebe0.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Replaced `window` references with `ssrSafeWindow`", + "packageName": "@microsoft/teams-js", + "email": "noahdarveau@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/packages/teams-js/src/internal/communication.ts b/packages/teams-js/src/internal/communication.ts index 0adf46d1c1..0522da382f 100644 --- a/packages/teams-js/src/internal/communication.ts +++ b/packages/teams-js/src/internal/communication.ts @@ -9,7 +9,7 @@ import { GlobalVars } from './globalVars'; import { callHandler } from './handlers'; import { DOMMessageEvent, ExtendedWindow, MessageRequest, MessageResponse } from './interfaces'; import { getLogger } from './telemetry'; -import { validateOrigin } from './utils'; +import { ssrSafeWindow, validateOrigin } from './utils'; const communicationLogger = getLogger('communication'); @@ -63,7 +63,7 @@ export function initializeCommunication(validMessageOrigins: string[] | undefine // If we are in an iframe, our parent window is the one hosting us (i.e., window.parent); otherwise, // it's the window that opened us (i.e., window.opener) - Communication.currentWindow = Communication.currentWindow || window; + Communication.currentWindow = Communication.currentWindow || ssrSafeWindow(); Communication.parentWindow = Communication.currentWindow.parent !== Communication.currentWindow.self ? Communication.currentWindow.parent diff --git a/packages/teams-js/src/internal/utils.ts b/packages/teams-js/src/internal/utils.ts index 5d5e1db474..fb09d79d06 100644 --- a/packages/teams-js/src/internal/utils.ts +++ b/packages/teams-js/src/internal/utils.ts @@ -444,3 +444,26 @@ export function getBase64StringFromBlob(blob: Blob): Promise { reader.readAsDataURL(blob); }); } + +/** + * Returns an SSR safe reference to the window object + * @returns Window object reference + */ + +export function ssrSafeWindow(): Window { + if (!inServerSideRenderingEnvironment()) { + return window; + } else { + // This should NEVER actually be written. + // If you EVER see this error in ANY log file, something has gone horribly wrong and a bug needs to be filed. + throw new Error('window object undefined at SSR check'); + } +} + +/** + * Checks if running in a Server Side Environment + * @returns True if running in a Server Side Environment + */ +export function inServerSideRenderingEnvironment(): boolean { + return typeof window === 'undefined'; +} diff --git a/packages/teams-js/src/internal/videoUtils.ts b/packages/teams-js/src/internal/videoUtils.ts index be812f145b..2a47843376 100644 --- a/packages/teams-js/src/internal/videoUtils.ts +++ b/packages/teams-js/src/internal/videoUtils.ts @@ -1,9 +1,9 @@ -import { inServerSideRenderingEnvironment } from '../private/inServerSideRenderingEnvironment'; import { videoEx } from '../private/videoEx'; import { errorNotSupportedOnPlatform } from '../public/constants'; import { video } from '../public/video'; import { sendMessageToParent } from './communication'; import { registerHandler } from './handlers'; +import { inServerSideRenderingEnvironment, ssrSafeWindow } from './utils'; import { AllowSharedBufferSource, PlaneLayout, @@ -113,7 +113,7 @@ async function getInputVideoTrack( throw errorNotSupportedOnPlatform; } // eslint-disable-next-line @typescript-eslint/no-explicit-any - const chrome = window['chrome'] as any; + const chrome = ssrSafeWindow()['chrome'] as any; try { videoPerformanceMonitor?.reportGettingTextureStream(streamId); const mediaStream = await chrome.webview.getTextureStream(streamId); @@ -156,7 +156,7 @@ function pipeVideoSourceToGenerator( transformer: TransformerWithMetadata | DefaultTransformer, sink: WritableStream, ): void { - const MediaStreamTrackProcessor = window['MediaStreamTrackProcessor']; + const MediaStreamTrackProcessor = ssrSafeWindow()['MediaStreamTrackProcessor']; const processor = new MediaStreamTrackProcessor({ track: videoTrack }); const source = processor.readable; diff --git a/packages/teams-js/src/private/inServerSideRenderingEnvironment.ts b/packages/teams-js/src/private/inServerSideRenderingEnvironment.ts deleted file mode 100644 index f35333c229..0000000000 --- a/packages/teams-js/src/private/inServerSideRenderingEnvironment.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function inServerSideRenderingEnvironment(): boolean { - return typeof window === 'undefined'; -} diff --git a/packages/teams-js/src/private/videoEx.ts b/packages/teams-js/src/private/videoEx.ts index 03ade4209f..90a0c6d7fc 100644 --- a/packages/teams-js/src/private/videoEx.ts +++ b/packages/teams-js/src/private/videoEx.ts @@ -1,6 +1,7 @@ import { sendMessageToParent } from '../internal/communication'; import { registerHandler } from '../internal/handlers'; import { ensureInitialized } from '../internal/internalAPIs'; +import { inServerSideRenderingEnvironment } from '../internal/utils'; import { VideoPerformanceMonitor } from '../internal/videoPerformanceMonitor'; import { createEffectParameterChangeCallback, @@ -11,7 +12,6 @@ import { import { errorNotSupportedOnPlatform, FrameContexts } from '../public/constants'; import { runtime } from '../public/runtime'; import { video } from '../public/video'; -import { inServerSideRenderingEnvironment } from './inServerSideRenderingEnvironment'; /** * @hidden diff --git a/packages/teams-js/src/public/app.ts b/packages/teams-js/src/public/app.ts index ab318e1f27..4cc5bf6bc6 100644 --- a/packages/teams-js/src/public/app.ts +++ b/packages/teams-js/src/public/app.ts @@ -15,8 +15,7 @@ import { GlobalVars } from '../internal/globalVars'; import * as Handlers from '../internal/handlers'; // Conflict with some names import { ensureInitializeCalled, ensureInitialized, processAdditionalValidOrigins } from '../internal/internalAPIs'; import { getLogger } from '../internal/telemetry'; -import { compareSDKVersions, runWithTimeout } from '../internal/utils'; -import { inServerSideRenderingEnvironment } from '../private/inServerSideRenderingEnvironment'; +import { compareSDKVersions, inServerSideRenderingEnvironment, runWithTimeout } from '../internal/utils'; import { logs } from '../private/logs'; import { authentication } from './authentication'; import { ChannelType, FrameContexts, HostClientType, HostName, TeamType, UserTeamRole } from './constants'; diff --git a/packages/teams-js/src/public/authentication.ts b/packages/teams-js/src/public/authentication.ts index 8af294327b..5d17a0061a 100644 --- a/packages/teams-js/src/public/authentication.ts +++ b/packages/teams-js/src/public/authentication.ts @@ -8,6 +8,7 @@ import { import { GlobalVars } from '../internal/globalVars'; import { registerHandler, removeHandler } from '../internal/handlers'; import { ensureInitializeCalled, ensureInitialized } from '../internal/internalAPIs'; +import { ssrSafeWindow } from '../internal/utils'; import { FrameContexts, HostClientType } from './constants'; import { runtime } from './runtime'; @@ -471,7 +472,7 @@ export namespace authentication { link.href = decodeURIComponent(callbackUrl); if ( link.host && - link.host !== window.location.host && + link.host !== ssrSafeWindow().location.host && link.host === 'outlook.office.com' && link.search.indexOf('client_type=Win32_Outlook') > -1 ) { diff --git a/packages/teams-js/src/public/teamsAPIs.ts b/packages/teams-js/src/public/teamsAPIs.ts index de76c0d3e4..ac06269a37 100644 --- a/packages/teams-js/src/public/teamsAPIs.ts +++ b/packages/teams-js/src/public/teamsAPIs.ts @@ -1,6 +1,7 @@ import { GlobalVars } from '../internal/globalVars'; import * as Handlers from '../internal/handlers'; // Conflict with some names import { ensureInitialized } from '../internal/internalAPIs'; +import { ssrSafeWindow } from '../internal/utils'; import { errorNotSupportedOnPlatform } from './constants'; import { LoadContext } from './interfaces'; import { runtime } from './runtime'; @@ -41,13 +42,7 @@ export namespace teamsCore { * default print handler */ export function print(): void { - if (typeof window !== 'undefined') { - window.print(); - } else { - // This codepath only exists to enable compilation in a server-side redered environment. In standard usage, the window object should never be undefined so this code path should never run. - // If this error has actually been thrown, something has gone very wrong and it is a bug - throw new Error('window object undefined at print call'); - } + ssrSafeWindow().print(); } /** diff --git a/packages/teams-js/src/public/video.ts b/packages/teams-js/src/public/video.ts index fd7b32b42a..aa1e6ba4a8 100644 --- a/packages/teams-js/src/public/video.ts +++ b/packages/teams-js/src/public/video.ts @@ -1,9 +1,9 @@ import { sendMessageToParent } from '../internal/communication'; import { registerHandler } from '../internal/handlers'; import { ensureInitialized } from '../internal/internalAPIs'; +import { inServerSideRenderingEnvironment, ssrSafeWindow } from '../internal/utils'; import { VideoPerformanceMonitor } from '../internal/videoPerformanceMonitor'; import { createEffectParameterChangeCallback, processMediaStream } from '../internal/videoUtils'; -import { inServerSideRenderingEnvironment } from '../private/inServerSideRenderingEnvironment'; import { errorNotSupportedOnPlatform, FrameContexts } from './constants'; import { runtime } from './runtime'; @@ -406,9 +406,8 @@ export namespace video { } function isTextureStreamAvailable(): boolean { - return ( - !inServerSideRenderingEnvironment() && - !!(window['chrome']?.webview?.getTextureStream && window['chrome']?.webview?.registerTextureStream) + return !!( + ssrSafeWindow()['chrome']?.webview?.getTextureStream && ssrSafeWindow()['chrome']?.webview?.registerTextureStream ); }