Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ssr): fix global window and document references #17590

Merged
merged 2 commits into from
Feb 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/src/components/button/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class Button implements ComponentInterface {
if (form) {
ev.preventDefault();

const fakeButton = document.createElement('button');
const fakeButton = this.win.document.createElement('button');
fakeButton.type = this.type;
fakeButton.style.display = 'none';
form.appendChild(fakeButton);
Expand Down
19 changes: 7 additions & 12 deletions core/src/components/col/col.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -232,30 +232,25 @@ export class Col implements ComponentInterface {
};
}

private calculateOffset() {
const isRTL = document.dir === 'rtl';

private calculateOffset(isRTL: boolean) {
return this.calculatePosition('offset', isRTL ? 'margin-right' : 'margin-left');
}

private calculatePull() {
const isRTL = document.dir === 'rtl';

private calculatePull(isRTL: boolean) {
return this.calculatePosition('pull', isRTL ? 'left' : 'right');
}

private calculatePush() {
const isRTL = document.dir === 'rtl';

private calculatePush(isRTL: boolean) {
return this.calculatePosition('push', isRTL ? 'right' : 'left');
}

hostData() {
const isRTL = this.win.document.dir === 'rtl';
return {
style: {
...this.calculateOffset(),
...this.calculatePull(),
...this.calculatePush(),
...this.calculateOffset(isRTL),
...this.calculatePull(isRTL),
...this.calculatePush(isRTL),
...this.calculateSize(),
}
};
Expand Down
4 changes: 2 additions & 2 deletions core/src/components/item-sliding/item-sliding.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,10 @@ export class ItemSliding implements ComponentInterface {
? SlidingState.Start | SlidingState.SwipeStart
: SlidingState.Start;
} else {
this.tmr = window.setTimeout(() => {
this.tmr = setTimeout(() => {
this.state = SlidingState.Disabled;
this.tmr = undefined;
}, 600);
}, 600) as any;

openSlidingItem = undefined;
style.transform = '';
Expand Down
2 changes: 1 addition & 1 deletion core/src/components/menu/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export class Menu implements ComponentInterface, MenuI {
const el = this.el;
const parent = el.parentNode as any;
const content = this.contentId !== undefined
? document.getElementById(this.contentId)
? this.doc.getElementById(this.contentId)
: parent && parent.querySelector && parent.querySelector('[main]');

if (!content || !content.tagName) {
Expand Down
2 changes: 1 addition & 1 deletion core/src/components/modal/animations/ios.leave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function iosLeaveAnimation(AnimationC: Animation, baseEl: HTMLElement): P
const wrapperElRect = wrapperEl!.getBoundingClientRect();

wrapperAnimation.beforeStyles({ 'opacity': 1 })
.fromTo('translateY', '0%', `${window.innerHeight - wrapperElRect.top}px`);
.fromTo('translateY', '0%', `${(baseEl.ownerDocument as any).defaultView.innerHeight - wrapperElRect.top}px`);

backdropAnimation.fromTo('opacity', 0.4, 0.0);

Expand Down
4 changes: 2 additions & 2 deletions core/src/components/popover/animations/ios.enter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ export function iosEnterAnimation(AnimationC: Animation, baseEl: HTMLElement, ev
const contentWidth = contentDimentions.width;
const contentHeight = contentDimentions.height;

const bodyWidth = window.innerWidth;
const bodyHeight = window.innerHeight;
const bodyWidth = (baseEl.ownerDocument as any).defaultView.innerWidth;
const bodyHeight = (baseEl.ownerDocument as any).defaultView.innerHeight;

// If ev was passed, use that for target element
const targetDim = ev && ev.target && (ev.target as HTMLElement).getBoundingClientRect();
Expand Down
7 changes: 4 additions & 3 deletions core/src/components/popover/animations/md.enter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { Animation } from '../../../interface';
* Md Popover Enter Animation
*/
export function mdEnterAnimation(AnimationC: Animation, baseEl: HTMLElement, ev?: Event): Promise<Animation> {
const isRTL = document.dir === 'rtl';
const doc = (baseEl.ownerDocument as any);
const isRTL = doc.dir === 'rtl';

let originY = 'top';
let originX = isRTL ? 'right' : 'left';
Expand All @@ -14,8 +15,8 @@ export function mdEnterAnimation(AnimationC: Animation, baseEl: HTMLElement, ev?
const contentWidth = contentDimentions.width;
const contentHeight = contentDimentions.height;

const bodyWidth = window.innerWidth;
const bodyHeight = window.innerHeight;
const bodyWidth = doc.defaultView.innerWidth;
const bodyHeight = doc.defaultView.innerHeight;

// If ev was passed, use that for target element
const targetDim =
Expand Down
15 changes: 8 additions & 7 deletions core/src/components/range/range.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class Range implements ComponentInterface {
@Element() el!: HTMLStencilElement;

@Prop({ context: 'queue' }) queue!: QueueApi;
@Prop({ context: 'document' }) doc!: Document;

@State() private ratioA = 0;
@State() private ratioB = 0;
Expand Down Expand Up @@ -240,7 +241,7 @@ export class Range implements ComponentInterface {

// figure out which knob they started closer to
let ratio = clamp(0, (currentX - rect.left) / rect.width, 1);
if (document.dir === 'rtl') {
if (this.doc.dir === 'rtl') {
ratio = 1 - ratio;
}

Expand Down Expand Up @@ -270,7 +271,7 @@ export class Range implements ComponentInterface {
// update the knob being interacted with
const rect = this.rect;
let ratio = clamp(0, (currentX - rect.left) / rect.width, 1);
if (document.dir === 'rtl') {
if (this.doc.dir === 'rtl') {
ratio = 1 - ratio;
}

Expand Down Expand Up @@ -368,7 +369,8 @@ export class Range implements ComponentInterface {
const barStart = `${ratioLower * 100}%`;
const barEnd = `${100 - ratioUpper * 100}%`;

const isRTL = document.dir === 'rtl';
const doc = this.doc;
const isRTL = doc.dir === 'rtl';
const start = isRTL ? 'right' : 'left';
const end = isRTL ? 'left' : 'right';

Expand Down Expand Up @@ -426,7 +428,7 @@ export class Range implements ComponentInterface {
style={barStyle()}
/>

{ renderKnob({
{ renderKnob(isRTL, {
knob: 'A',
pressed: this.pressedKnob === 'A',
value: this.valA,
Expand All @@ -438,7 +440,7 @@ export class Range implements ComponentInterface {
max
})}

{ this.dualKnobs && renderKnob({
{ this.dualKnobs && renderKnob(isRTL, {
knob: 'B',
pressed: this.pressedKnob === 'B',
value: this.valB,
Expand Down Expand Up @@ -468,8 +470,7 @@ interface RangeKnob {
handleKeyboard: (name: KnobName, isIncrease: boolean) => void;
}

function renderKnob({ knob, value, ratio, min, max, disabled, pressed, pin, handleKeyboard }: RangeKnob) {
const isRTL = document.dir === 'rtl';
function renderKnob(isRTL: boolean, { knob, value, ratio, min, max, disabled, pressed, pin, handleKeyboard }: RangeKnob) {
const start = isRTL ? 'right' : 'left';

const knobStyle = () => {
Expand Down
2 changes: 1 addition & 1 deletion core/src/components/router/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export class Router implements ComponentInterface {
@Method()
push(url: string, direction: RouterDirection = 'forward') {
if (url.startsWith('.')) {
url = (new URL(url, window.location.href)).pathname;
url = (new URL(url, this.win.location.href)).pathname;
}
console.debug('[ion-router] URL pushed -> updating nav', url, direction);

Expand Down
19 changes: 11 additions & 8 deletions core/src/components/split-pane/split-pane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,17 @@ export class SplitPane implements ComponentInterface {
return;
}

// Listen on media query
const callback = (q: MediaQueryList) => {
this.visible = q.matches;
};
const mediaList = this.win.matchMedia(mediaQuery);
mediaList.addListener(callback as any);
this.rmL = () => mediaList.removeListener(callback as any);
this.visible = mediaList.matches;
if ((this.win as any).matchMedia) {
// Listen on media query
const callback = (q: MediaQueryList) => {
this.visible = q.matches;
};

const mediaList = this.win.matchMedia(mediaQuery);
(mediaList as any).addListener(callback as any);
this.rmL = () => (mediaList as any).removeListener(callback as any);
this.visible = mediaList.matches;
}
}

private isPane(element: HTMLElement): boolean {
Expand Down
8 changes: 5 additions & 3 deletions core/src/components/toggle/toggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export class Toggle implements ComponentInterface {

@Prop({ context: 'queue' }) queue!: QueueApi;

@Prop({ context: 'document' }) doc!: Document;

@State() activated = false;

/**
Expand Down Expand Up @@ -146,7 +148,7 @@ export class Toggle implements ComponentInterface {
}

private onMove(detail: GestureDetail) {
if (shouldToggle(this.checked, detail.deltaX, -10)) {
if (shouldToggle(this.doc, this.checked, detail.deltaX, -10)) {
this.checked = !this.checked;
hapticSelection();
}
Expand Down Expand Up @@ -222,8 +224,8 @@ export class Toggle implements ComponentInterface {
}
}

function shouldToggle(checked: boolean, deltaX: number, margin: number): boolean {
const isRTL = document.dir === 'rtl';
function shouldToggle(doc: HTMLDocument, checked: boolean, deltaX: number, margin: number): boolean {
const isRTL = doc.dir === 'rtl';

if (checked) {
return (!isRTL && (margin > deltaX)) ||
Expand Down
11 changes: 5 additions & 6 deletions core/src/global/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,26 +34,25 @@ export class Config {
}
}

export function configFromSession(): any {
export function configFromSession(win: Window): any {
try {
const configStr = window.sessionStorage.getItem(IONIC_SESSION_KEY);
const configStr = win.sessionStorage.getItem(IONIC_SESSION_KEY);
return configStr !== null ? JSON.parse(configStr) : {};
} catch (e) {
return {};
}
}

export function saveConfig(config: any) {
export function saveConfig(win: Window, config: any) {
try {
window.sessionStorage.setItem(IONIC_SESSION_KEY, JSON.stringify(config));
win.sessionStorage.setItem(IONIC_SESSION_KEY, JSON.stringify(config));
} catch (e) {
return;
}
}

export function configFromURL() {
export function configFromURL(win: Window) {
const config: any = {};
const win = window;
win.location.search.slice(1)
.split('&')
.map(entry => entry.split('='))
Expand Down
22 changes: 13 additions & 9 deletions core/src/global/ionic-global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { isPlatform, setupPlatforms } from '../utils/platform';

import { Config, configFromSession, configFromURL, saveConfig } from './config';

const win = window;
const Ionic = (win as any)['Ionic'] = (win as any)['Ionic'] || {};
declare const Context: any;

const win = Context['window'] ? Context['window'] : typeof (window as any) !== 'undefined' ? window : {} as Window;

const Ionic = (win as any)['Ionic'] = (win as any)['Ionic'] || {};

// queue used to coordinate DOM reads and
// write in order to avoid layout thrashing
Object.defineProperty(Ionic, 'queue', {
Expand All @@ -21,25 +23,27 @@ Context.isPlatform = isPlatform;
// create the Ionic.config from raw config object (if it exists)
// and convert Ionic.config into a ConfigApi that has a get() fn
const configObj = {
...configFromSession(),
...configFromSession(win),
persistConfig: false,
...Ionic['config'],
...configFromURL()
...configFromURL(win)
};
const config = Ionic['config'] = Context['config'] = new Config(configObj);
if (config.getBoolean('persistConfig')) {
saveConfig(configObj);
saveConfig(win, configObj);
}

// first see if the mode was set as an attribute on <html>
// which could have been set by the user, or by prerendering
// otherwise get the mode via config settings, and fallback to md
const documentElement = document.documentElement!;
const mode = config.get('mode', documentElement.getAttribute('mode') || (isPlatform(win, 'ios') ? 'ios' : 'md'));
const documentElement = win.document ? win.document.documentElement : null;
const mode = config.get('mode', (documentElement && documentElement.getAttribute('mode')) || (isPlatform(win, 'ios') ? 'ios' : 'md'));
Ionic.mode = Context.mode = mode;
config.set('mode', mode);
documentElement.setAttribute('mode', mode);
documentElement.classList.add(mode);
if (documentElement) {
documentElement.setAttribute('mode', mode);
documentElement.classList.add(mode);
}
if (config.getBoolean('_testing')) {
config.set('animated', false);
}
5 changes: 3 additions & 2 deletions core/src/utils/animation/animator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ export const TRANSFORM_PROPS: {[key: string]: number} = {
'perspective': 1
};

const raf = (window as any).requestAnimationFrame
? window.requestAnimationFrame.bind(window)
const win = typeof (window as any) !== 'undefined' ? window : {};
const raf = (win as any).requestAnimationFrame
? (win as Window).requestAnimationFrame.bind(win)
: (f: FrameRequestCallback) => f(Date.now());

export class Animator {
Expand Down
2 changes: 1 addition & 1 deletion core/src/utils/input-shims/hacks/scroll-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function getScrollData(componentEl: HTMLElement, contentEl: HTMLElement,
itemEl.getBoundingClientRect(),
contentEl.getBoundingClientRect(),
keyboardHeight,
window.innerHeight
(componentEl as any).ownerDocument.defaultView.innerHeight
);
}

Expand Down
7 changes: 5 additions & 2 deletions core/src/utils/media.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ export function matchBreakpoint(win: Window, breakpoint: string | undefined) {
if (breakpoint === undefined || breakpoint === '') {
return true;
}
const mediaQuery = SIZE_TO_MEDIA[breakpoint];
return win.matchMedia(mediaQuery).matches;
if ((win as any).matchMedia) {
const mediaQuery = SIZE_TO_MEDIA[breakpoint];
return win.matchMedia(mediaQuery).matches;
}
return false;
}
13 changes: 5 additions & 8 deletions core/src/utils/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ export function setupPlatforms(win: any) {
let platforms: string[] | undefined | null = win.Ionic.platforms;
if (platforms == null) {
platforms = win.Ionic.platforms = detectPlatforms(win);
const classList = win.document.documentElement.classList;
platforms.forEach(p => classList.add(`plt-${p}`));
platforms.forEach(p => win.document.documentElement.classList.add(`plt-${p}`));
}
return platforms;
}
Expand Down Expand Up @@ -93,13 +92,11 @@ function isHybrid(win: Window) {
return isCordova(win) || isCapacitorNative(win);
}

function isCordova(window: Window): boolean {
const win = window as any;
function isCordova(win: any): boolean {
return !!(win['cordova'] || win['phonegap'] || win['PhoneGap']);
}

function isCapacitorNative(window: Window): boolean {
const win = window as any;
function isCapacitorNative(win: any): boolean {
const capacitor = win['Capacitor'];
return !!(capacitor && capacitor.isNative);
}
Expand All @@ -116,6 +113,6 @@ export function testUserAgent(win: Window, expr: RegExp) {
return expr.test(win.navigator.userAgent);
}

function matchMedia(win: Window, query: string): boolean {
return win.matchMedia(query).matches;
function matchMedia(win: any, query: string): boolean {
return win.matchMedia ? win.matchMedia(query).matches : false;
}
2 changes: 1 addition & 1 deletion core/src/utils/transition/ios.transition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function shadow<T extends Element>(el: T): ShadowRoot | T {

export function iosTransitionAnimation(AnimationC: Animation, navEl: HTMLElement, opts: TransitionOptions): Promise<Animation> {

const isRTL = document.dir === 'rtl';
const isRTL = (navEl.ownerDocument as any).dir === 'rtl';
const OFF_RIGHT = isRTL ? '-99.5%' : '99.5%';
const OFF_LEFT = isRTL ? '33%' : '-33%';

Expand Down