From 99c722db48aa306e521cec731df0d343c903ee55 Mon Sep 17 00:00:00 2001 From: Isiah Meadows Date: Tue, 13 Nov 2018 22:21:36 -0500 Subject: [PATCH] Officially drop IE9-10 support, pull out our hacks [skip ci] - I also fixed a bunch of related comments - Drive-by: update transpiling info in CONTRIBUTING.md - Drive-by: we aren't the only ones going semicolon-free --- README.md | 2 +- api/redraw.js | 11 +++-------- docs/contributing.md | 8 +++----- docs/index.md | 2 +- docs/redraw.md | 4 ++-- docs/route.md | 6 +++--- render/render.js | 6 +++--- 7 files changed, 16 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 20b7f573d..7a33056b4 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ A modern client-side Javascript framework for building Single Page Applications. Mithril is used by companies like Vimeo and Nike, and open source platforms like Lichess 👍. -Browsers all the way back to IE9 are supported, no polyfills required 👌. +Mithril supports IE11, Firefox ESR, and the last two versions of Firefox, Edge, Safari, and Chrome. No polyfills required. 👌 ## Installation diff --git a/api/redraw.js b/api/redraw.js index a65499759..aa513e384 100644 --- a/api/redraw.js +++ b/api/redraw.js @@ -3,18 +3,13 @@ var coreRenderer = require("../render/render") function throttle(callback) { - //60fps translates to 16.6ms, round it down since setTimeout requires int - var delay = 16 - var last = 0, pending = null - var timeout = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout + var pending = null return function() { - var elapsed = Date.now() - last if (pending === null) { - pending = timeout(function() { + pending = requestAnimationFrame(function() { pending = null callback() - last = Date.now() - }, delay - elapsed) + }) } } } diff --git a/docs/contributing.md b/docs/contributing.md index 4e672470b..febd682cc 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -79,17 +79,15 @@ This simplifies the workflow for bug fixes, which means they can be fixed faster -## Why doesn't the Mithril codebase use ES6 via Babel? Would a PR to upgrade be welcome? +## Why doesn't the Mithril codebase use ES6 via Babel or Bublé? Would a PR to upgrade be welcome? -Being able to run Mithril raw source code in IE is a requirement for all browser-related modules in this repo. - -In addition, ES6 features are usually less performant than equivalent ES5 code, and transpiled code is bulkier. +Being able to run Mithril's raw source code in all supported browsers is a requirement for all browser-related modules in this repo. In addition, transpiled code is generally much bulkier. ## Why doesn't the Mithril codebase use trailing semi-colons? Would a PR to add them be welcome? -I don't use them. Adding them means the semi-colon usage in the codebase will eventually become inconsistent. +I don't use them. Adding them means the semi-colon usage in the codebase will eventually become inconsistent. Besides, [we aren't the only one who've decided to drop the semicolon](https://standardjs.com/#who-uses-javascript-standard-style). (We don't use Standard, though.) diff --git a/docs/index.md b/docs/index.md index 97dd2b139..979212dbe 100644 --- a/docs/index.md +++ b/docs/index.md @@ -44,7 +44,7 @@ Mithril is used by companies like Vimeo and Nike, and open source platforms like If you are an experienced developer and want to know how Mithril compares to other frameworks, see the [framework comparison](framework-comparison.md) page. -Mithril supports browsers all the way back to IE9, no polyfills required. +Mithril supports IE11, Firefox ESR, and the last two versions of Firefox, Edge, Safari, and Chrome. No polyfills required. --- diff --git a/docs/redraw.md b/docs/redraw.md index 0d0795922..f53612a57 100644 --- a/docs/redraw.md +++ b/docs/redraw.md @@ -44,7 +44,7 @@ When callbacks outside of Mithril run, you need to notify Mithril's rendering en To trigger a redraw, call `m.redraw()`. Note that `m.redraw` only works if you used `m.mount` or `m.route`. If you rendered via `m.render`, you should use `m.render` to redraw. -`m.redraw()` always triggers an asynchronous redraws, whereas `m.redraw.sync()` triggers a synchronous one. `m.redraw()` is tied to `window.requestAnimationFrame()` (we provide a fallback for IE9). It will thus typically fire at most 60 times per second. It may fire faster if your monitor has a higher refresh rate. +`m.redraw()` always triggers an asynchronous redraws, whereas `m.redraw.sync()` triggers a synchronous one. `m.redraw()` is tied to `window.requestAnimationFrame()`. It will thus typically fire at most 60 times per second. It may fire faster if your monitor has a higher refresh rate. `m.redraw.sync()` is mostly intended to make videos play work in iOS. That only works in response to user-triggered events. It comes with several caveat: @@ -52,4 +52,4 @@ To trigger a redraw, call `m.redraw()`. Note that `m.redraw` only works if you u - `m.redraw.sync()` called from an event handler can cause the DOM to be modified while an event is bubbling. Depending on the structure of the old and new DOM trees, the event can finish the bubbling phase in the new tree and trigger unwanted handlers. - It is not throttled. One call to `m.redraw.sync()` causes immediately one `m.render()` call per root registered with [`m.mount()`](mount.md) or [`m.route()`](route.md). -`m.redraw()` doesn't have any of those issues, you can call it from wherever you like. \ No newline at end of file +`m.redraw()` doesn't have any of those issues, you can call it from wherever you like. diff --git a/docs/route.md b/docs/route.md index c48f0e560..07357a8d9 100644 --- a/docs/route.md +++ b/docs/route.md @@ -218,11 +218,11 @@ The routing strategy dictates how a library might actually implement routing. Th - Using the querystring. A URL using this strategy typically looks like `http://localhost/?/page1` - Using the pathname. A URL using this strategy typically looks like `http://localhost/page1` -Using the hash strategy is guaranteed to work in browsers that don't support `history.pushState` (namely, Internet Explorer 9), because it can fall back to using `onhashchange`. Use this strategy if you want to support IE9. +Using the hash strategy is guaranteed to work in browsers that don't support `history.pushState`, because it can fall back to using `onhashchange`. Use this strategy if you want to keep the hashes purely local. -The querystring strategy also technically works in IE9, but it falls back to reloading the page. Use this strategy if you want to support anchored links and you are not able to make the server-side necessary to support the pathname strategy. +The querystring strategy allows server-side detection, but it doesn't appear as a normal path. Use this strategy if you want to support and potentially detect anchored links server-side and you are not able to make the changes necessary to support the pathname strategy (like if you're using Apache and can't modify your .htaccess). -The pathname strategy produces the cleanest looking URLs, but does not work in IE9 *and* requires setting up the server to serve the single page application code from every URL that the application can route to. Use this strategy if you want cleaner-looking URLs and do not need to support IE9. +The pathname strategy produces the cleanest looking URLs, but requires setting up the server to serve the single page application code from every URL that the application can route to. Use this strategy if you want cleaner-looking URLs. Single page applications that use the hash strategy often use the convention of having an exclamation mark after the hash to indicate that they're using the hash as a routing mechanism and not for the purposes of linking to anchors. The `#!` string is known as a *hashbang*. diff --git a/render/render.js b/render/render.js index 44ce338e4..84b06b61b 100644 --- a/render/render.js +++ b/render/render.js @@ -35,7 +35,7 @@ module.exports = function($window) { } } - // IE9 - IE11 (at least) throw an UnspecifiedError when accessing document.activeElement when + // IE11 (at least) throws an UnspecifiedError when accessing document.activeElement when // inside an iframe. Catch and swallow this error, and heavy-handidly return null. function activeElement() { try { @@ -255,7 +255,7 @@ module.exports = function($window) { // When the list is being traversed top-down, at any index, the DOM nodes up to the previous // vnode reflect the content of the new list, whereas the rest of the DOM nodes reflect the old // list. The next sibling must be looked for in the old list using `getNextSibling(... oldStart + 1 ...)`. - // + // // In the other scenarios (swaps, upwards traversal, map-based diff), // the new vnodes list is traversed upwards. The DOM nodes at the bottom of the list reflect the // bottom part of the new vnodes list, and we can use the `v.dom` value of the previous node @@ -880,7 +880,7 @@ module.exports = function($window) { vnodes = Vnode.normalizeChildren(Array.isArray(vnodes) ? vnodes : [vnodes]) updateNodes(dom, dom.vnodes, vnodes, hooks, null, namespace === "http://www.w3.org/1999/xhtml" ? undefined : namespace) dom.vnodes = vnodes - // document.activeElement can return null in IE https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement + // `document.activeElement` can return null: https://html.spec.whatwg.org/multipage/interaction.html#dom-document-activeelement if (active != null && activeElement() !== active && typeof active.focus === "function") active.focus() for (var i = 0; i < hooks.length; i++) hooks[i]() }