Skip to content

Commit 1a869b3

Browse files
committed
fix(youtube-player): avoid errors with clobbered variables
Sometimes the browser exposes elements globally based on their `id` or `name` which can break the `youtube-player`. These changes add some protections around it.
1 parent e9089fd commit 1a869b3

2 files changed

Lines changed: 19 additions & 8 deletions

File tree

goldens/youtube-player/index.api.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
/// <reference types="youtube" />
88

99
import { AfterViewInit } from '@angular/core';
10+
import * as _angular_core from '@angular/core';
1011
import { ElementRef } from '@angular/core';
11-
import * as i0 from '@angular/core';
1212
import { InjectionToken } from '@angular/core';
1313
import { Observable } from 'rxjs';
1414
import { OnChanges } from '@angular/core';
@@ -97,9 +97,9 @@ export class YouTubePlayer implements AfterViewInit, OnChanges, OnDestroy {
9797
set width(width: number | undefined);
9898
youtubeContainer: ElementRef<HTMLElement>;
9999
// (undocumented)
100-
static ɵcmp: i0.ɵɵComponentDeclaration<YouTubePlayer, "youtube-player", never, { "videoId": { "alias": "videoId"; "required": false; }; "height": { "alias": "height"; "required": false; }; "width": { "alias": "width"; "required": false; }; "startSeconds": { "alias": "startSeconds"; "required": false; }; "endSeconds": { "alias": "endSeconds"; "required": false; }; "suggestedQuality": { "alias": "suggestedQuality"; "required": false; }; "playerVars": { "alias": "playerVars"; "required": false; }; "disableCookies": { "alias": "disableCookies"; "required": false; }; "loadApi": { "alias": "loadApi"; "required": false; }; "disablePlaceholder": { "alias": "disablePlaceholder"; "required": false; }; "showBeforeIframeApiLoads": { "alias": "showBeforeIframeApiLoads"; "required": false; }; "placeholderButtonLabel": { "alias": "placeholderButtonLabel"; "required": false; }; "placeholderImageQuality": { "alias": "placeholderImageQuality"; "required": false; }; }, { "ready": "ready"; "stateChange": "stateChange"; "error": "error"; "apiChange": "apiChange"; "playbackQualityChange": "playbackQualityChange"; "playbackRateChange": "playbackRateChange"; }, never, never, true, never>;
100+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<YouTubePlayer, "youtube-player", never, { "videoId": { "alias": "videoId"; "required": false; }; "height": { "alias": "height"; "required": false; }; "width": { "alias": "width"; "required": false; }; "startSeconds": { "alias": "startSeconds"; "required": false; }; "endSeconds": { "alias": "endSeconds"; "required": false; }; "suggestedQuality": { "alias": "suggestedQuality"; "required": false; }; "playerVars": { "alias": "playerVars"; "required": false; }; "disableCookies": { "alias": "disableCookies"; "required": false; }; "loadApi": { "alias": "loadApi"; "required": false; }; "disablePlaceholder": { "alias": "disablePlaceholder"; "required": false; }; "showBeforeIframeApiLoads": { "alias": "showBeforeIframeApiLoads"; "required": false; }; "placeholderButtonLabel": { "alias": "placeholderButtonLabel"; "required": false; }; "placeholderImageQuality": { "alias": "placeholderImageQuality"; "required": false; }; }, { "ready": "ready"; "stateChange": "stateChange"; "error": "error"; "apiChange": "apiChange"; "playbackQualityChange": "playbackQualityChange"; "playbackRateChange": "playbackRateChange"; }, never, never, true, never>;
101101
// (undocumented)
102-
static ɵfac: i0.ɵɵFactoryDeclaration<YouTubePlayer, never>;
102+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<YouTubePlayer, never>;
103103
}
104104

105105
// @public
@@ -113,11 +113,11 @@ export interface YouTubePlayerConfig {
113113
// @public (undocumented)
114114
export class YouTubePlayerModule {
115115
// (undocumented)
116-
static ɵfac: i0.ɵɵFactoryDeclaration<YouTubePlayerModule, never>;
116+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<YouTubePlayerModule, never>;
117117
// (undocumented)
118-
static ɵinj: i0.ɵɵInjectorDeclaration<YouTubePlayerModule>;
118+
static ɵinj: _angular_core.ɵɵInjectorDeclaration<YouTubePlayerModule>;
119119
// (undocumented)
120-
static ɵmod: i0.ɵɵNgModuleDeclaration<YouTubePlayerModule, never, [typeof YouTubePlayer], [typeof YouTubePlayer]>;
120+
static ɵmod: _angular_core.ɵɵNgModuleDeclaration<YouTubePlayerModule, never, [typeof YouTubePlayer], [typeof YouTubePlayer]>;
121121
}
122122

123123
// (No @packageDocumentation comment for this package)

src/youtube-player/youtube-player.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,13 @@ export class YouTubePlayer implements AfterViewInit, OnChanges, OnDestroy {
496496
return;
497497
}
498498

499-
if (!window.YT || !window.YT.Player) {
499+
// Might be clobbered by something like `<form id="YT"><input name="Player"></form>`.
500+
if (
501+
typeof window.YT !== 'object' ||
502+
!window.YT ||
503+
!window.YT.Player ||
504+
typeof window.YT.Player !== 'function'
505+
) {
500506
if (this.loadApi) {
501507
this._isLoading = true;
502508
loadApi(this._nonce);
@@ -508,7 +514,12 @@ export class YouTubePlayer implements AfterViewInit, OnChanges, OnDestroy {
508514
);
509515
}
510516

511-
this._existingApiReadyCallback = (window as YoutubeWindow).onYouTubeIframeAPIReady;
517+
const existingCallback = (window as YoutubeWindow).onYouTubeIframeAPIReady;
518+
519+
// The callback might be clobbered by an element with an ID of `onYouTubeIframeAPIReady`.
520+
if (typeof existingCallback === 'function') {
521+
this._existingApiReadyCallback = (window as YoutubeWindow).onYouTubeIframeAPIReady;
522+
}
512523

513524
(window as YoutubeWindow).onYouTubeIframeAPIReady = () => {
514525
this._existingApiReadyCallback?.();

0 commit comments

Comments
 (0)