Commit 60100581 authored by Robert Knight's avatar Robert Knight

Apply `dir="auto"` fix in Edge Legacy

The sidebar app failed to start in Edge Legacy due to `element.dir
= "auto` assignments causing an exception during Preact component
rendering. We already had a fix for this that applied to IE 11, so the
fix for this problem is to change the check to test for the bug
specifically rather than testing the user agent.
parent 108f5ef0
import { options } from 'preact'; import { options } from 'preact';
import { isIE11 } from './user-agent';
/** /**
* Force the dir="auto" attribute to be dir="" as this otherwise causes * Setup workarounds for setting certain HTML element properties or attributes
* an exception in IE11 and breaks subsequent rendering. * in some browsers.
* *
* @param {Object} _options - Test seam * @param {Object} _options - Test seam
*/ */
export function setupIE11Fixes(_options = options) { export function setupBrowserFixes(_options = options) {
if (isIE11()) { let needsDirAutoFix = false;
try {
const el = document.createElement('div');
// The value "auto" causes an exception in IE 11 and Edge Legacy.
el.dir = 'auto';
} catch (err) {
needsDirAutoFix = true;
}
if (needsDirAutoFix) {
const prevHook = _options.vnode; const prevHook = _options.vnode;
_options.vnode = vnode => { _options.vnode = vnode => {
if (typeof vnode.type === 'string') { if (typeof vnode.type === 'string') {
......
import { createElement } from 'preact'; import { createElement } from 'preact';
import { setupIE11Fixes } from '../renderer-options'; import { setupBrowserFixes } from '../renderer-options';
import { $imports } from '../renderer-options';
describe('shared/renderer-options', () => { describe('shared/renderer-options', () => {
let fakeIsIE11; describe('setupBrowserFixes', () => {
beforeEach(() => {
fakeIsIE11 = sinon.stub().returns(true);
$imports.$mock({
'./user-agent': {
isIE11: fakeIsIE11,
},
});
});
afterEach(() => {
$imports.$restore();
});
describe('setupIE11Fixes', () => {
let fakeOptions; let fakeOptions;
let prevHook; let prevHook;
...@@ -30,36 +14,50 @@ describe('shared/renderer-options', () => { ...@@ -30,36 +14,50 @@ describe('shared/renderer-options', () => {
}; };
}); });
context('when isIE11 is false', () => { context('when all checks pass', () => {
it('does not set a new vnode option if isIE11 is false', () => { it('does not set a new vnode option', () => {
fakeIsIE11.returns(false); setupBrowserFixes(fakeOptions);
setupIE11Fixes(fakeOptions);
assert.isNotOk(fakeOptions.vnode); assert.isNotOk(fakeOptions.vnode);
}); });
}); });
context('when isIE11 is true', () => { context('when `dir = "auto"` check fails', () => {
beforeEach(() => {
const fakeElement = {
set dir(value) {
if (value === 'auto') {
throw new Error('Invalid argument');
}
},
};
sinon.stub(document, 'createElement').returns(fakeElement);
});
afterEach(() => {
document.createElement.restore();
});
it('sets a new vnode option', () => { it('sets a new vnode option', () => {
setupIE11Fixes(fakeOptions); setupBrowserFixes(fakeOptions);
assert.isOk(fakeOptions.vnode); assert.isOk(fakeOptions.vnode);
}); });
it('does not override an existing option if one exists', () => { it('does not override an existing option if one exists', () => {
fakeOptions.vnode = prevHook; fakeOptions.vnode = prevHook;
setupIE11Fixes(fakeOptions); setupBrowserFixes(fakeOptions);
fakeOptions.vnode({}); fakeOptions.vnode({});
assert.called(prevHook); assert.called(prevHook);
}); });
it("alters the `dir` attribute when its equal to 'auto'", () => { it("alters the `dir` attribute when its equal to 'auto'", () => {
setupIE11Fixes(fakeOptions); setupBrowserFixes(fakeOptions);
const vDiv = createElement('div', { dir: 'auto' }, 'text'); const vDiv = createElement('div', { dir: 'auto' }, 'text');
fakeOptions.vnode(vDiv); fakeOptions.vnode(vDiv);
assert.equal(vDiv.props.dir, ''); assert.equal(vDiv.props.dir, '');
}); });
it('does not alter the `dir` attribute when vnode.type is not a string', () => { it('does not alter the `dir` attribute when vnode.type is not a string', () => {
setupIE11Fixes(fakeOptions); setupBrowserFixes(fakeOptions);
const vDiv = createElement('div', { dir: 'auto' }, 'text'); const vDiv = createElement('div', { dir: 'auto' }, 'text');
vDiv.type = () => {}; // force it to be a function vDiv.type = () => {}; // force it to be a function
fakeOptions.vnode(vDiv); fakeOptions.vnode(vDiv);
...@@ -67,7 +65,7 @@ describe('shared/renderer-options', () => { ...@@ -67,7 +65,7 @@ describe('shared/renderer-options', () => {
}); });
it("does not alter the `dir` attribute when its value is not 'auto'", () => { it("does not alter the `dir` attribute when its value is not 'auto'", () => {
setupIE11Fixes(fakeOptions); setupBrowserFixes(fakeOptions);
const vDiv = createElement('function', { dir: 'ltr' }, 'text'); const vDiv = createElement('function', { dir: 'ltr' }, 'text');
fakeOptions.vnode(vDiv); fakeOptions.vnode(vDiv);
assert.equal(vDiv.props.dir, 'ltr'); assert.equal(vDiv.props.dir, 'ltr');
......
...@@ -43,8 +43,8 @@ const isSidebar = !( ...@@ -43,8 +43,8 @@ const isSidebar = !(
window.location.pathname.startsWith('/a/') window.location.pathname.startsWith('/a/')
); );
// Install Preact renderer options to work around IE11 quirks // Install Preact renderer options to work around browser quirks
rendererOptions.setupIE11Fixes(); rendererOptions.setupBrowserFixes();
// @ngInject // @ngInject
function setupApi(api, streamer) { function setupApi(api, streamer) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment