ECMAScript Version Detector

image

ECMAScript Version Detectorというツールとライブラリを書きました。

azu.github.io/ecmascript-version-detector/へアクセスして、好きなコードをペーストすると、そのコードの構文がECMAScriptのどのバージョンから使える機能なのかを表示してくれます。

たとえば、以下のコードはasyncとawaitの部分がまだProposalであるAsync Functionsであることを検出してくれたりします。

// Async/Await
async function countUp() {
  await delay(1000);
}

目的

Babelなどの変換ツールでECMAScriptのProposalな機能などが身近になりました。 しかし、それがまだ仕様に入ってないもの(Proposal段階であるもの)ということを意識しないで書いてる人もよく見かけるようになりました。

そのため、まだProposalの段階である標準化されてない機能/構文を標準化される前提にして話すなというあったりします。

例えば、次のコードは既に仕様に入ってる(ES2015)構文で書かれたコードでしょうか?

const initialState = {};
export function friends(state = initialState, action) {  
  switch (action.type) {
    case "FRIEND":
      return {
        friendsById: {
          ...state.friendsById,
          [newId]: {
            name: action.name
          }
        }
      }
    default:
      return state;
  }
}

ECMAScript Version Detectorに入れてみると分かりますが、{...property}はまだ標準化されていない機能です。

result

これはObject Rest/Spread Propertiesで、Stage 2のProposalです。

こういう見た目から分かりにくいものも、構文を解析して一覧を出すのが目的です。

JavaScriptに詳しい人は問題ないですが、JavaScriptを今から始めるような人は、どの機能がいつから使える機能なのかが分からない場合があります。

また、最近のブラウザは先行して実装したりしています。 ブラウザに入ってる = 標準化されたもの ではないので、そういうのをコードから検索できる必要が出てくる気がしています。

asciidwango/js-primer: JavaScriptの入門書を書いていて、演算子はGoogle検索が難しいので、1ページに殆どの演算子記号を並べて書いたりしています。

JavaScriptのコードにおいても、コードからこの構文って何なのかを知りたい事があると思うので作りました。

おわり

azu/ecmascript-version-detector: ECMAScript Version Detectorは結構ラフスケッチな感じなので、もっといい感じの表示したりするPull Request待っています。

一応、ライブラリとして使えます。 コードをパースしたら、バージョンとかASTが入ったものを返します。

const parse = require("ecmascript-version-detector").parse;
parse(`const x = 1 ** 2;`);
/*
[
    {
        "selector": "//BinaryExpression[@operator=='**']",
        "version": "2016",
        "en": {
            "name": "BinaryExpression exponentiation operator"
        },
        "node": {
            "type": "BinaryExpression",
            "start": 0,
            "end": 6,
            "loc": {
                "start": {
                    "line": 1,
                    "column": 0
                },
                "end": {
                    "line": 1,
                    "column": 6
                }
            },
            "left": {
                "type": "NumericLiteral",
                "start": 0,
                "end": 1,
                "loc": {
                    "start": {
                        "line": 1,
                        "column": 0
                    },
                    "end": {
                        "line": 1,
                        "column": 1
                    }
                },
                "extra": {
                    "rawValue": 1,
                    "raw": "1"
                },
                "value": 1
            },
            "operator": "**",
            "right": {
                "type": "NumericLiteral",
                "start": 5,
                "end": 6,
                "loc": {
                    "start": {
                        "line": 1,
                        "column": 5
                    },
                    "end": {
                        "line": 1,
                        "column": 6
                    }
                },
                "extra": {
                    "rawValue": 2,
                    "raw": "2"
                },
                "value": 2
            }
        }
    },
    ....
]
*/

Contributingに書いていますが、コードからのバージョンの判定はastqを使ってセレクタにマッチするかを見ています。

まだ足りてない判定などもあるので、気軽にPull Requestを投げてください。