Skip to content

Instantly share code, notes, and snippets.

@betaorbust
Last active July 21, 2018 19:57
Show Gist options
  • Save betaorbust/fed8112f72005a3472d78967b8d121a2 to your computer and use it in GitHub Desktop.
Save betaorbust/fed8112f72005a3472d78967b8d121a2 to your computer and use it in GitHub Desktop.
ES2015 fallback check for Progressive Transpilation

ES2015 Syntax Check for use with Progressive Transpilation

The attached file file spits out a string for direct injection into the head of a page, which will be a lightweight test of the ability to parse and run ES2015 syntax.

Unminified version

This is the original source for the test-case below:

class ಠ_ಠ extends Array{
    constructor(j = "a", ...c) {
        const q = (({u: e}) => {
            return {
                [`s${c}`]: Symbol(j)
            };
        })({});
        super(j, q, ...c);
    }
}
new Promise((f) => {
    const a = function* (){
        return "\u{20BB7}".match(/./u)[0].length === 2 || true;
    };
    for(let vre of a()){
        const [uw, as, he, re] = [new Set(), new WeakSet(), new Map(), new WeakMap()];
        break;
    }
    f(new Proxy({}, {get: (han, h) => h in han ? han[h] : "42".repeat(0o10)}));
}).then(bi => new ಠ_ಠ(bi.rd));

Coverage

This code is a set of ES2015 syntax and features that represent a broad but not deep test case for a browser supporting es2015.

  • arrows functions
  • classes
  • enhanced object literals
  • template strings
  • destructuring
  • default + rest + spread
  • let + const
  • iterators + for..of
  • generators
  • unicode
  • proxies
  • symbols
  • subclassable built-ins
  • promises
  • math + number + string + array + object APIs
  • binary and octal literals

Background

Explanation of how this code is used can be found in the talk Jem and I gave: "Progressive Transpilation at Netflix and the road to running native ES2015 in production".

Video here. The Progressive Transpilation part starts at 25:25:

Progressive Transpilation at Netflix and the road to running native ES2015 in production

Slides here:

Progressive Transpilation at Netflix and the road to running native ES2015 in production slide

Usage

Remember, this isn't a full test suite; the intended use case is to:

  1. Parse the UA string and determine ES2015 eligibility
  2. If ES2015 is indicated, ship a page with ES2015-level code.
  3. Inject the string produced in this file in a script tag at the top of the page which will check to make sure the browser can parse ES2015 syntax and run some of the newer constructs.
  4. If it turns out the browser's UA was a lie, and it can't actually parse or run ES2015, we set a cookie to limit future requests to ES5, and bounce the page as we know the incoming JS package won't work on this browser. Because the cookie is sticky, the interaction happens only once, and is only for corner cases where browsers are lying about their capabilities -- a minority case already.
'use strict';
/*
* The whitespace minified version of the above test case. Note that because many of the
* variables/calculations above are not used, running through a good minifier would
* actually strip out some test cases -- hence, whitespace only minification.
* This is a string, so we don't need to worry about accidentally transpiling
* or minifying it later in a development build.
*/
const es2015Test = 'class ಠ_ಠ extends Array{constructor(j="a",...c){const q=(({u:e})=>{return{[`s${c}`]:Symbol(j)}})({});super(j,q,...c)}}' +
'new Promise(f=>{const a=function*(){return"𠮷".match(/./u)[0].length===2||true};' +
'for(let vre of a()){const[uw,as,he,re]=[new Set,new WeakSet,new Map,new WeakMap];break}' +
'f(new Proxy({},{get:(han,h)=>h in han?han[h]:"42".repeat(8)}))}).then(bi=>new ಠ_ಠ(bi.rd));';
/*
* This is the string to be injected into a <script> tag for attempting to parse
* ES2015 syntax. If parsing/running fails, it will set a cookie which you can pick
* up on the server in subsequent requests. It then bounces the page immediately, as
* ES2015 syntax is coming over the wire, and we know this browser can't handle it.
*/
const testBody = `try{
eval('${es2015Test}');
} catch (e) {
document.cookie = 'esVersion=5; expires=' + (new Date((new Date()).getTime() + 2678400000)).toGMTString() + '; path=/ ;domain=netflix.com';
if(location.reload){location.reload();}else{location.href = location.href;}
}`;
module.exports = testBody;
@unlight
Copy link

unlight commented Jul 21, 2018

@betaorbust
Are you using it in production or still evaluating?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment