Skip to content

Commit

Permalink
InOb: Force polyfill for WebKit document=root (#32182)
Browse files Browse the repository at this point in the history
* InOb: Force polyfill for WebKit documnent=root

* lint

* Use Platform Service. TODO: stub.

* Stop using Platform service, use navigator.vendor

* typo
  • Loading branch information
samouri committed Jan 26, 2021
1 parent 6da0658 commit c357ab9
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 3 deletions.
17 changes: 16 additions & 1 deletion src/polyfillstub/intersection-observer-stub.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,25 @@ export function shouldLoadPolyfill(win) {
!win.IntersectionObserver ||
!win.IntersectionObserverEntry ||
!!win.IntersectionObserver[STUB] ||
!supportsDocumentRoot(win)
!supportsDocumentRoot(win) ||
isWebkit(win)
);
}

/**
* All current WebKit (as of Safari 14.x) {root:document} IntersectionObservers
* will report incorrect rootBounds, intersectionRect, and intersectionRatios
* and therefore we force the polyfill in this case.
* See: https://bugs.webkit.org/show_bug.cgi?id=219495.
*
* @param {!Window} win
* @return {boolean}
*/
function isWebkit(win) {
// navigator.vendor is always "Apple Computer, Inc." for all iOS browsers and Mac OS Safari.
return /apple/i.test(win.navigator.vendor);
}

/**
* @param {typeof IntersectionObserver} Native
* @param {typeof IntersectionObserver} Polyfill
Expand Down
1 change: 0 additions & 1 deletion src/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,6 @@ function getAmpdocService(win) {
* @param {!Object} holder Object holding the service instance.
* @param {string} id of the service.
* @return {Object}
* @template T
*/
function getServiceInternal(holder, id) {
devAssert(
Expand Down
31 changes: 30 additions & 1 deletion test/unit/polyfills/test-intersection-observer.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
shouldLoadPolyfill,
upgradePolyfill,
} from '../../../src/polyfillstub/intersection-observer-stub';
import {Services} from '../../../src/services';
import {
install,
installForChildWin,
Expand Down Expand Up @@ -59,15 +60,40 @@ class NativeIntersectionObserverEntry {
get isIntersecting() {}
}

describes.sandboxed('shouldLoadPolyfill', {}, () => {
const APPLE_NAVIGATOR = {vendor: 'Apple Computer, Inc.'};
const CHROME_NAVIGATOR = {vendor: 'Google Inc.'};

describes.sandboxed('shouldLoadPolyfill', {}, (env) => {
let isIos;
let isSafari;
beforeEach(() => {
isIos = false;
isSafari = false;
const platform = {isIos: () => isIos, isSafari: () => isSafari};
env.sandbox.stub(Services, 'platformFor').returns(platform);
});

it('should not load with native', () => {
const win = {
IntersectionObserver: NativeIntersectionObserver,
IntersectionObserverEntry: NativeIntersectionObserverEntry,
navigator: CHROME_NAVIGATOR,
};
expect(shouldLoadPolyfill(win)).to.be.false;
});

it('should always load in WebKit/Safari', () => {
const win = {
IntersectionObserver: NativeIntersectionObserver,
IntersectionObserverEntry: NativeIntersectionObserverEntry,
navigator: CHROME_NAVIGATOR,
};
expect(shouldLoadPolyfill(win)).to.be.false;

win.navigator = APPLE_NAVIGATOR;
expect(shouldLoadPolyfill(win)).to.be.true;
});

it('should load when native does not support {root: document}', () => {
class NativeNoDocumentRoot {
constructor(_unused, opts) {
Expand All @@ -80,6 +106,7 @@ describes.sandboxed('shouldLoadPolyfill', {}, () => {
IntersectionObserver: NativeNoDocumentRoot,
IntersectionObserverEntry: NativeIntersectionObserverEntry,
document: {nodeType: 9},
navigator: CHROME_NAVIGATOR,
};
expect(shouldLoadPolyfill(win)).to.be.true;
});
Expand All @@ -93,6 +120,7 @@ describes.sandboxed('shouldLoadPolyfill', {}, () => {
const win = {
IntersectionObserver: IntersectionObserverStub,
IntersectionObserverEntry: NativeIntersectionObserverEntry,
navigator: CHROME_NAVIGATOR,
};
installStub(win);
expect(shouldLoadPolyfill(win)).to.be.true;
Expand All @@ -101,6 +129,7 @@ describes.sandboxed('shouldLoadPolyfill', {}, () => {
it('should load when no native entry', () => {
const win = {
IntersectionObserver: NativeIntersectionObserver,
navigator: CHROME_NAVIGATOR,
};
expect(shouldLoadPolyfill(win)).to.be.true;
});
Expand Down

0 comments on commit c357ab9

Please sign in to comment.