index.js
1 const tests = { 2 // ECMAScript 2018 3 "object-rest-spread": ["({ ...{} })", "({ ...x } = {})"], // Babel 7.2.0 4 "async-generators": ["async function* f() {}"], // Babel 7.2.0 5 6 // ECMAScript 2019 7 "optional-catch-binding": ["try {} catch {}"], // Babel 7.2.0 8 "json-strings": ["'\\u2028'"], // Babel 7.2.0 9 10 // ECMAScript 2020 11 "bigint": ["1n"], // Babel 7.8.0 12 "optional-chaining": ["a?.b"], // Babel 7.9.0 13 "nullish-coalescing-operator": ["a ?? b"], // Babel 7.9.0 14 // import.meta is handled manually 15 16 // Stage 3 17 "numeric-separator": ["1_2"], 18 "class-properties": [ 19 "(class { x = 1 })", 20 "(class { #x = 1 })", 21 "(class { #x() {} })", 22 ], 23 "logical-assignment-operators": ["a ||= b", "a &&= b", "a ??= c"], 24 }; 25 26 const plugins = []; 27 const works = (test) => { 28 try { 29 // Wrap the test in a function to only test the syntax, without executing it 30 (0, eval)(`(() => { ${test} })`); 31 return true; 32 } catch (_error) { 33 return false; 34 } 35 }; 36 37 for (const [name, cases] of Object.entries(tests)) { 38 if (cases.some(works)) { 39 plugins.push(require.resolve(`@babel/plugin-syntax-${name}`)); 40 } 41 } 42 43 // import.meta is only allowed in modules, and modules can only be evaluated 44 // synchronously. For this reason, we cannot detect import.meta support at 45 // runtime. It is supported starting from 10.4, so we can check the version. 46 const major = parseInt(process.versions.node, 10); 47 const minor = parseInt(process.versions.node.match(/^\d+\.(\d+)/)[1], 10); 48 if (major > 10 || (major === 10 && minor >= 4)) { 49 plugins.push(require.resolve("@babel/plugin-syntax-import-meta")); 50 } 51 // Same for top level await - it is only supported in modules. It is supported 52 // from 14.3.0 53 if (major > 14 || (major === 14 && minor >= 3)) { 54 plugins.push(require.resolve("@babel/plugin-syntax-top-level-await")); 55 } 56 57 module.exports = () => ({ plugins });