I wrote a library that detects the version of the ECMAScript that is running on JavaScript, and that also allows to check support for few syntax-features.
For the ECMAScript version detection I run 4 checks, each check tests if JavaScript supports some features of a specific ECMAScript version. Until a check is successful, its specific ECMAScript version is returned. If no check matches, the return is null
. Each check is just a detection for a specific ECMAScript version. Check 1 detects ES7, check 2 detects ES6, check 3 detects ES5 and check 4 detects ES3.
For the syntax-features detection I basically have an object, which is pre-declared in my library's factory, containing raw codes to be evaluated, that's syntax-features mixed with others. In this detection I build a string, which will be a code to be evaluated. The string will always contain an anonymous function, inside this anonymous function will be pushed raw codes according to the syntax features I want (if the raw code for any of these syntax features isn't specified in the earlier object, the non-existent specific(s) feature(s) won't affect anything), with an extra empty statement (semicolon). Finally, the result code will be evaluated. If an error is thrown, that means one or more of the features aren't supported, so we get false
as detection result. Else, the detection result is true
.
This is my library code:
;(function (root, name, factory) {
'use strict';
if (("function" === typeof define) && define.amd)
define([exports], factory);
else if (typeof exports === 'object')
factory(exports);
else
factory(root[name] = {});
})(this, 'esx', function (exports) {
'use strict';
var features = {
"arrayComprehensions": "[for(_ of [0])_]"
, "arrowFunction": "(_=>_)"
, "class": "(class{})"
, "const": "const c=true"
, "defaultParams": "(function(a=false){})"
, "destructuring": "let {d}={a:true}"
, "forOf": "for(var b of [])"
, "generator": "(function*(){})"
, "getter": "({get a(){}})"
, "label": "l:0"
, "let": "let o"
, "reservedWords": "({catch:true})"
, "setter": "({set a(v){}})"
, "spread": "[...[]]"
, "stringInterpolation": "`$\{0}`"
, "stringLineBreak": "'\\\n'"
, "super": "({b(){super.a}})"
, "yield": "(function*(){yield true})"
};
// exports.features = features;
function evaluate (code) {
try {
eval(code);
return true;
} catch(e) {
return false;
}
}
/**
* Check if a set of features are supported.
*/
function supports () {
var code = "(function(){";
var i = 0, len = arguments.length;
for (; i < len; ++i) {
var feature = arguments[i].toString();
if (features.hasOwnProperty(feature))
code += features[feature] + ';';
}
code += "})()";
return evaluate(code);
}
exports.supports = supports;
function checkES7 () {
return supports("arrayComprehensions");
}
function checkES6 () {
var methods = 'function' === typeof Object.assign &&
'function' === typeof Object.freeze;
var syntax = supports(
"arrowFunction"
, "class"
, "const"
, "forOf"
, "defaultParams"
, "destructuring"
, "super"
, "yield"
);
return methods && syntax;
}
function checkES5 () {
var methods = 'function' === typeof [].filter &&
'function' === typeof Function.prototype.bind &&
'function' === typeof Object.defineProperty &&
'function' === typeof ''.trim &&
'object' === typeof JSON;
var syntax = supports("reservedWords");
return methods && syntax;
}
function checkES3 () {
return "function" === typeof [].hasOwnProperty;
}
/**
* Check for ECMAScript version.
*/
exports.detectVersion = function () {
return checkES7() ? 7 :
checkES6() ? 6 :
checkES5() ? 5 :
checkES3() ? 3 :
null;
};
});
My library can be used so, then:
console.log(esx.detectVersion() >= 6); // true here
console.log(esx.supports("arrowFunction", "super"));
// ^^^^^^ true here (supports arrow functions and super)
Please give your constructive criticisms and suggestions.
esx.features.arrowFunctions = 'throw ":P"'
and see what happens "possible exploit if ES version does not match expectation" Maybe do the tests within the libs context andesx.features.feature
true/false and not let the monkeys get in before tests. Just a thought... \$\endgroup\$esx.detectVersion() >= 6
... Bad ! I accidentaly exposed the features raw because I worried about something, but I'll update that. The problem is that it's light-ening in here :/ (thundering) \$\endgroup\$Non-standard. Do not use!
on developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…, which was used forcheckES7
. \$\endgroup\$