164 lines
3.9 KiB
JavaScript
164 lines
3.9 KiB
JavaScript
|
'use strict'
|
||
|
|
||
|
const vm = require('vm')
|
||
|
|
||
|
const context = vm.createContext()
|
||
|
function test (code) {
|
||
|
try {
|
||
|
return vm.runInContext(`(function () {
|
||
|
'use strict'
|
||
|
${code}
|
||
|
})()`, context) === true
|
||
|
} catch (err) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const support = {}
|
||
|
|
||
|
// Tests from <https://github.com/kangax/compat-table/blob/c0a3b882b27e4e9f4ef449a1c985ee7857326b94/data-es6.js#L12733:L13115>.
|
||
|
support.functionStatements = test(`
|
||
|
function foo(){};
|
||
|
return foo.name === 'foo' &&
|
||
|
(function(){}).name === '';
|
||
|
`)
|
||
|
|
||
|
support.functionExpressions = test(`
|
||
|
return (function foo(){}).name === 'foo' &&
|
||
|
(function(){}).name === '';
|
||
|
`)
|
||
|
|
||
|
support.newFunction = test(`
|
||
|
return (new Function).name === "anonymous";
|
||
|
`)
|
||
|
|
||
|
support.boundFunctions = test(`
|
||
|
function foo() {};
|
||
|
return foo.bind({}).name === "bound foo" &&
|
||
|
(function(){}).bind({}).name === "bound ";
|
||
|
`)
|
||
|
|
||
|
support.functionVariables = test(`
|
||
|
var foo = function() {};
|
||
|
var bar = function baz() {};
|
||
|
return foo.name === "foo" && bar.name === "baz";
|
||
|
`)
|
||
|
|
||
|
support.functionObjectMethods = test(`
|
||
|
var o = { foo: function(){}, bar: function baz(){}};
|
||
|
o.qux = function(){};
|
||
|
return o.foo.name === "foo" &&
|
||
|
o.bar.name === "baz" &&
|
||
|
o.qux.name === "";
|
||
|
`)
|
||
|
|
||
|
support.accessorProperties = test(`
|
||
|
var o = { get foo(){}, set foo(x){} };
|
||
|
var descriptor = Object.getOwnPropertyDescriptor(o, "foo");
|
||
|
return descriptor.get.name === "get foo" &&
|
||
|
descriptor.set.name === "set foo";
|
||
|
`)
|
||
|
|
||
|
support.shorthandMethods = test(`
|
||
|
var o = { foo(){} };
|
||
|
return o.foo.name === "foo"
|
||
|
`)
|
||
|
|
||
|
support.symbolKeyedMethods = test(`
|
||
|
var sym1 = Symbol("foo");
|
||
|
var sym2 = Symbol();
|
||
|
var o = {
|
||
|
[sym1]: function(){},
|
||
|
[sym2]: function(){}
|
||
|
};
|
||
|
|
||
|
return o[sym1].name === "[foo]" &&
|
||
|
o[sym2].name === "";
|
||
|
`)
|
||
|
|
||
|
support.classStatements = test(`
|
||
|
class foo {};
|
||
|
class bar { static name() {} };
|
||
|
return foo.name === "foo" &&
|
||
|
typeof bar.name === "function";
|
||
|
`)
|
||
|
|
||
|
support.classExpressions = test(`
|
||
|
return class foo {}.name === "foo" &&
|
||
|
typeof class bar { static name() {} }.name === "function";
|
||
|
`)
|
||
|
|
||
|
support.classVariables = test(`
|
||
|
var foo = class {};
|
||
|
var bar = class baz {};
|
||
|
var qux = class { static name() {} };
|
||
|
return foo.name === "foo" &&
|
||
|
bar.name === "baz" &&
|
||
|
typeof qux.name === "function";
|
||
|
`)
|
||
|
|
||
|
support.classObjectMethods = test(`
|
||
|
var o = { foo: class {}, bar: class baz {}};
|
||
|
o.qux = class {};
|
||
|
return o.foo.name === "foo" &&
|
||
|
o.bar.name === "baz" &&
|
||
|
o.qux.name === "";
|
||
|
`)
|
||
|
|
||
|
support.classPrototypeMethods = test(`
|
||
|
class C { foo(){} };
|
||
|
return (new C).foo.name === "foo";
|
||
|
`)
|
||
|
|
||
|
support.classStaticMethods = test(`
|
||
|
class C { static foo(){} };
|
||
|
return C.foo.name === "foo";
|
||
|
`)
|
||
|
|
||
|
exports.support = Object.freeze(support)
|
||
|
|
||
|
const hasFullSupport =
|
||
|
support.functionStatements &&
|
||
|
support.functionExpressions &&
|
||
|
support.newFunction &&
|
||
|
support.boundFunctions &&
|
||
|
support.functionVariables &&
|
||
|
support.functionObjectMethods &&
|
||
|
support.accessorProperties &&
|
||
|
support.shorthandMethods &&
|
||
|
support.symbolKeyedMethods &&
|
||
|
support.classStatements &&
|
||
|
support.classExpressions &&
|
||
|
support.classVariables &&
|
||
|
support.classObjectMethods &&
|
||
|
support.classPrototypeMethods &&
|
||
|
support.classStaticMethods
|
||
|
exports.hasFullSupport = hasFullSupport
|
||
|
|
||
|
const bitFlags = [
|
||
|
'functionStatements',
|
||
|
'functionExpressions',
|
||
|
'newFunction',
|
||
|
'boundFunctions',
|
||
|
'functionVariables',
|
||
|
'functionObjectMethods',
|
||
|
'accessorProperties',
|
||
|
'shorthandMethods',
|
||
|
'symbolKeyedMethods',
|
||
|
'classStatements',
|
||
|
'classExpressions',
|
||
|
'classVariables',
|
||
|
'classObjectMethods',
|
||
|
'classPrototypeMethods',
|
||
|
'classStaticMethods'
|
||
|
// Add new flags at the end. Reordering flags is a breaking change.
|
||
|
].reduce((acc, key, index) => {
|
||
|
return support[key] === true
|
||
|
? acc + (1 << index)
|
||
|
: acc
|
||
|
}, 0b0)
|
||
|
exports.bitFlags = bitFlags
|
||
|
|
||
|
exports.isSubsetOf = otherFlags => (bitFlags & otherFlags) === bitFlags
|
||
|
exports.isSupersetOf = otherFlags => (bitFlags & otherFlags) === otherFlags
|