Moeki Kawakami

Javascript Transpiler and ESLint are NOT Perfect

Summary

  • Even with a transpiler, not all ECMAScript descriptions can be converted.
  • Even with ESLint, not all ECMAScript descriptions can be linted.

Inspect!

When using ECMAScript, what does the transpiler convert and what does it parse?

  • Verify what the transpiler converts and what it ignores
  • Verify what ESLint parses and what it ignores

cc-kawakami/transpilers-and-eslint-are-not-perfect

Input for validation

  • Code samples based on ES6 to ESNext standards
  • Pick a function that you may have occasion to use
/**
 * ES2015
 * ------------------------------------------------
 */
/** const, let */
const cst = 1
let lt = 2
console.log(cst)
console.log(lt)

/** Allow function */
const fn = () => {
  console.log('fn')
}

/** classes */
class Hoge {
  fuga () {
    console.log('fuga')
  }
}

/**
 * ES2016
 * ------------------------------------------------
 */
/** Array.prototype.includes */
const array = [1, 2, 3, 4, 5]
console.log(array.includes(2))

/** power operator */
console.log(2**2)

/**
 * ES2017
 * ------------------------------------------------
 */
/** Async functions */
async function log () {
  console.log('hoge')
}

/** Object.values() */
const obj = { hoge: 0, fuga: 1, piyo: 2 }
console.log(Object.values(obj))

/**
 * ES2018
 * ------------------------------------------------
 */
/** Spread Properties */
const hoge = { fuga: 'piyo' }
console.log({ .... .hoge })

/** RegExp named capture groups */
console.log(/(? <year>[0-9]{4})year/.test('2021'))

/** RegExp Lookbehind Assertions */
console.log(/(? <=[0-9]+)\. [0-9]+/.test('.34'))

/**
 * ES2019
 * ------------------------------------------------
 */
/** flat array methods */
console.log([[1, 2], 3, 4].flat())

/**
 * ES2020
 * ------------------------------------------------
 */
/** Optional chaining operator */
console.log(hoge?.fuga)

/**
 * ES2021
 * ------------------------------------------------
 */
/** Logical assignment operators */
console.log(a ||= b)

/** Numeric separators */
console.log(100_000_000)

/**
 * ESNext
 * ------------------------------------------------
 */
/** static class field */
class Foo {
  static bar = 1
}

console.log(Foo.bar)

Target transpiler and settings

Nonametarget
1Babel / conservative- ( > 1% in JP )
2Babel / progressive- ( > 5% in JP )
3esbuild / defaultESNext
4esbuild / to ES2017ES2017
5rollupnot transpile
6rollup-plugin-esbuildES2017
7Typescript / defaultES3
8Typescript / to ES2017ES2017

Inspection results.

Descriptions not converted by ALL transpiles

  • RegExp named capture groups (ES2018)
  • RegExp Lookbehind Assertions (ES2018)
  • Flat array methods (ES2019)

Descriptions that cannot be validated with ESLint

  • flat array methods (ES2019)

Other things I noticed

  • esbuild reduces comments by default.

(extra) execution time

Nonametargettime ( s )
1Babel / conservative- ( > 1% in JP )0.63
2Babel / progressive- ( > 5% in JP )0.53
3esbuild / defaultESNext0.31
4esbuild / to ES2017ES20170.18
5rollupnot transpile0.20
6rollup-plugin-esbuildES20170.27
7Typescript / defaultES31.21
8Typescript / to ES2017ES20171.36

Reference

← Back to list