GithubHelp home page GithubHelp logo

robatwilliams / es-compat Goto Github PK

View Code? Open in Web Editor NEW
62.0 3.0 13.0 1.12 MB

Check JavaScript code compatibility with target runtime environments

License: MIT License

JavaScript 100.00%
browser compatibility compat support javascript ecmascript es checker browserslist browser-compat-data

es-compat's Introduction

npm version npm downloads

es-compat

Check JavaScript code compatibility with target browsers and Node.js versions

Checks that the language features used in your code/bundles are supported by your browserslist targets.

Tools

Rationale

You might not need a transpiler or polyfills.

Or, you may be transpiling your own code but not prebuilt 3rd-party libraries - leaving you open to breakages when they use new language features.

ESLint supports targeting a specific ECMAScript version, and eslint-plugin-es-x allows forbidding individual language features. However when building applications, what we target are particular browser/runtime versions. This project lets you check compatibility by specifying those targets directly via a browserslist. It will figure out which individual features you can use, by looking up those targets in the MDN compatibility dataset.

Usage scenario examples

If you're not using a transpiler, run the tool/linter on your source code to ensure you're not using language features that aren't supported in your application's supported browsers.

If you transpile your own code but not 3rd party libraries, run the tool/linter on your output bundles to ensure they're not using language features that aren't supported in your application's supported browsers.

Scope

ECMAScript language features only; this includes syntax, built-ins, and methods.

It doesn't check browser/runtime-specific APIs (see eslint-plugin-compat), or CSS (see doiuse).

ECMAScript version coverage

n Expand for footnotes...

1 Excluding features not statically detectable: revised Function.prototype.toString, stable Array.prototype.sort, well-formed JSON.stringify.

2 Excluding Symbol.prototype.description; as a debug feature, it's not worth the false positives that arise due to its name and not being a method.

3 ES2015 (ES6) is out of scope; it's been supported by evergreen browsers for many years. Assisting you to continue supporting IE11 is not a goal of this tool.

4 ES5 is out of scope; it's over 10 years old and supported even in IE10.

Browser compatibility data

We use a pinned version of @mdn/browser-compat-data, because their SemVer policy allows for breaking changes to the data structure even in minor and patch releases. If you need to use more up to date data, use the overrides facility of package.json to specify a later version - but be aware that it might break.

Limitations

Because JavaScript is untyped, detection of some features' usage (namely prototype methods) through static analysis requires some assumptions to be made. This shouldn't be a problem as long as you avoid creating your own methods having the same names, or write code in an unusual way to deliberately evade detection.

Support can only be checked for the browsers and runtimes covered by the MDN compatibility dataset.

The MDN compatibility dataset has very good feature coverage of the top ~6 desktop and mobile browsers, and Node.js (much more than kangax/compat-table). In case of missing data for a feature (support unknown, or unknown in which version support was added), we currently assume support.

Contributing

Contributions and feedback welcome. Please see the GitHub issues or create one, as appropriate.

Related

* Thanks to these projects in particular (and many others) for making this project possible.

es-compat's People

Contributors

amanvarshney11 avatar brabeji avatar brettz9 avatar lukeapage avatar robatwilliams avatar sobstel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

es-compat's Issues

Prints info and warning messages that aren't file-specific, for every file

It prints this complaint for every file on the command line:

es-compat: No compatibility data for target family 'op_mini'
es-compat: checking compatibility for targets {
  chrome_android: '86',
  uc_android: '12.12',
  chrome: '84',
  edge: '85',
  firefox: '81',
  safari_ios: '10.0-10.2',
  opera: '71',
  safari: '13.1',
  samsunginternet_android: '12.0'
}

Ideally it would print it once, or not at all.

Update to ES modules

Update the code of the plugin itself to use import and export rather than require and module.exports.

Update the lint rules in eslintrc to require this style, and prohibit CommonJS style.

Provide suggestions on how to make code more widely compatible (CLI)

You might be willing to avoid using some features (or polyfill them if non-syntax) in order to widen compatibility.

The CLI could provide suggestions on this.

(feature follows-on from #5)

$ npx check-es-compat -- --widen source.js
✔ Chrome 80+
    73+ without
      nullish coalescing operator (??)
    earlier without
      Object.fromEntries [or polyfill]
...

Console logs mess up structured output from ESLint

Hi there! Really enjoying this library so far, but unfortunately the console log that says which targets are being checked makes it difficult for CI tools to parse the output from eslint. Would it be possible to put these logs behind a DEBUG= env var or something? Thanks!

Report all targets where the code would work (CLI)

Answer "where will this work" as opposed to "will this work there".

CLI feature, triggered by flag.

$ npx check-es-compat -- --where source.js
✔ Chrome 75+
✖ Edge
✔ Firefox 70+
✔ iOS 13+
...

Flat config support / ESLint 9

Hi,

As of ESLint 8, there is now a new format for ESLint config files which requires that plugins follow a specific format. In ESLint 9, this format will be the only one available by default (and other API changes have occurred in ESLint 9 that may affect this plugin).

Info:

  1. https://eslint.org/docs/latest/use/configure/configuration-files-new
  2. https://eslint.org/blog/2022/08/new-config-system-part-1/
  3. https://eslint.org/blog/2022/08/new-config-system-part-2/
  4. https://eslint.org/docs/latest/use/configure/migration-guide

Thanks!

Sustainability of continued dependency on mysticatea/eslint-plugin-es

The last commit and interaction on the project was over 2 years ago. The author is still active on GitHub but hasn't responded to attempts by people to contact them.

  • Blocks enhancements for newer ES versions, unless we implement rules from scratch (#44)
  • Lack of fixes for possible bugs and compatibility issues with newer ESLint versions
  • Generally bad things about depending on an abandoned project

The author has been invited to transfer the repo to the eslint-community organisation: mysticatea/eslint-plugin-es#92

Deal with breaking changes from MDN compat DB

They have a non-traditional SemVer policy, which includes releasing breaking changes as minor and patch releases.

In #60 and other upgrades I find these breaking changes, but they could happen to package users any time, because we don't depend on a fixed patch version (we use ^x.x.x). The user workaround would be to manually install an older version, but I can't expect that users would be able to figure out what the problem is (with the current error caused, at least).

There has been some discussion on mdn/browser-compat-data#7563 and other linked issues on their repo.

Ideas to solve:

  • write a warning in the readme
  • improve error handling
  • pin to specific patch version
  • use dependabot as suggested here mdn/browser-compat-data#7563 (comment)
  • MDN DB to become more normal when it comes to semver

Tool does not disable all other plugins and rules

I noticed warnings printed from other rules / plugins that I don't want:

/home/ubuntu/app/dist/web/vnd.draft-js-plugins-editor.js
  429:3   error  Definition for rule 'react/no-unused-prop-types' was not found  react/no-unused-prop-types
  850:1   error  Definition for rule 'import/no-named-as-default' was not found  import/no-named-as-default

Allow-listing syntax rules, like is already possible for polyfills

Is there a way to whitelist any rule i.e., not only the ones there are polyfills for? In my use case, I would like the plugin to enforce according the browserslist but whitelist the no-rest-spread-properties rule:

{
ruleConfig: { definition: esPlugin.rules['no-rest-spread-properties'] },
compatFeatures: [
compatData.javascript.operators.destructuring.rest_in_objects,
compatData.javascript.operators.spread.spread_in_object_literals,
],
},

ES module support for check-es-compat

Its parserOptions doesn't include sourceType: 'module', and top-level await can only be used in ES modules.

Parsing error: Unexpected token Promise

Include reason within error message for feature being forbidden

Instead of

"ES2018 rest/spread properties are forbidden."

say

"ES2018 rest/spread properties are not supported in Chrome 10, Firefox 11"

But... is it really useful to know that? The outcome regardless is that you can't use the feature. And you can always look it up on MDN yourself. So it might not be worth complicating the plugin with this.

ES2018-2023 RegExp Unicode property escapes

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_expressions/Unicode_property_escapes

New escapes are added with every ES version.

The plugin had rules for ES2018 and ES2019, but the latter isn't used because:

/**
  * New values were added in the following ES2019.
  * The rule no-regexp-unicode-property-escapes-2019 accepts these, but is omitted
  * because the compatibility data doesn't distinguish the two
  */

In v6, the plugin added rules for every year to 2023: https://github.com/eslint-community/eslint-plugin-es-x/releases/tag/v6.0.0

The compat data has javascript.regular_expressions.unicode_character_class_escape, but it doesn't distinguish when support for each one was added. So this issue is blocked on that.

The examples in the eslint-plugin-es-x docs have examples of escapes that were introduced in different years.

Allow overriding of rules

hi!

In an attempt to find a workaround for #72, I was wondering if it's an option to allow additional lint rules to be passed into ecmascript-compat/compat in addition to polyfills ?
That way I could work around the missing BigInt polyfill by declaring

'ecmascript-compat/compat': [
      'error',
      {
        rules: {
          'es-x/no-bigint': 'warn',
        },
        polyfills: [
          'globalThis',
        ],
      },
    ],

Popularity and usage monitoring

The ESLint plugin gets ~3k downloads a week, and the CLI tool ~800. The project has 55 stars. I don't really have an idea how many projects are using this or how useful it is to them (i.e. is it catching problems, or is it just installed because they thought they should have it). Without that, I'm not sure whether my continued time spent maintaining this project is worth it for anything more than my own interest.

NPM download counts are a poor measure. It shows downloads in the past 7 days, broken down by version. I've no idea how much of these are mirrors or uncached CI servers.

I don't believe there are any known good solutions to this for NPM packages. Tools such as Yeoman do "phone home" with usage data, but that's not really expected of NPM packages. This library implemented a file download so they could count installs, it didn't work well and caused some outrage.

Things to think about:

  • what data is useful (downloads, unique projects using, detections)
  • what decisions could be made with this data
  • privacy, terms and conditions
  • reliability of the package for users
  • risk of online backlash against the project/me
  • precedents (that worked or didn't)
  • is this a problem I should tackle or one for someone else

Being an ESLint plugin, this is going to be a direct dependency of users' application projects - they know they're using it. Perhaps a setting could allow opting-in. It would likely need to be mandatory to specify true/false otherwise most users would probably ignore it. If every plugin did this it would be messy. Doesn't seem nice.

In conclusion (so far) I think it's desirable but I don't have any good ideas on how to do it.

Version comparison inadequately compares strings

Test file:

[].includes( 'x' );

Browserslist: safari >= 14, ios_saf >= 14

Expected output:

es-compat: checking compatibility for targets { safari_ios: '14.0-14.4', safari: '14' }

No issues found. Files are compatible with the target runtimes.

Actual output:

es-compat: checking compatibility for targets { safari_ios: '14.0-14.4', safari: '14' }

/tmp/foo.js
  1:1  error  ES2016 method 'Array.prototype.includes' is forbidden  ecmascript-compat/compat

✖ 1 problem (1 error, 0 warnings)

Notes:
The dataset used reports that the feature was added in version 9 of both browsers. While 14 > 9 is true, '14' > '9' is false.

Ignore usages that are part of feature test expressions

If your code (or library code) is using a feature support test conditional statement before using a feature, then you still get an error reported by this plugin. It doesn't know your intent when doing such checks.

The current workaround is to configure the options to say you have a polyfill for that feature, even if you don't. This is dangerous as it will ignore all usages of that feature, including those without a feature test guard. This workaround isn't an option for non-polyfillable features namely BigInt and Atomics, as raised in #70.

It's the responsibility of https://github.com/eslint-community/eslint-plugin-es-x to do the detection. es-compat simply passes through all reports raised by it.

It might be possible to implement something here to guess if an expression looks like a feature test. We have the AST node there. But really eslint-plugin-es-x would be the ideal place for this, as this problem is not unique to es-compat, and it's the root of where the problem arises.

Cautious mode option for missing compatibility data

The MDN compatibility database is missing information for some features in some target runtimes. This is especially so for mobile browsers. Missing can mean unknown support, or that a feature is supported but it's not known from which version.

The plugin currently assumes support in such cases.

There should be an option to disable that assumption, because it could be wrong.

Cannot read property 'exponentiation' of undefined

Getting this error when trying to run the tool from the command line

$ check-es-compat dist/web/*.js
/home/ubuntu/app/node_modules/check-es-compat/node_modules/eslint/lib/cli-engine/config-array/config-array.js:180
                throw sourceValue.error;
                ^

TypeError: Failed to load plugin 'ecmascript-compat' declared in 'CLIOptions': Cannot read property 'exponentiation' of undefined
    at Object.<anonymous> (/home/ubuntu/app/node_modules/eslint-plugin-ecmascript-compat/lib/features/es2016.js:18:65)

Seems like something is not defined in the compatibility data.

Allow specifying polyfills option via CLI

#86 proposed this but needed further work to be accepted. The implementation and my comments on it sketch out how it should probably work.

If there is demand (please like this issue), I might implement it. It would be good for completeness anyway.

(Are you using this project ?)

I'd be interest to hear, however little you can say.

Knowing people are using this certainly helps my ongoing decision to spend time on it.

ES2024

Like #57 but for ES2024

The es-x plugin already has some (all?) rules, but I doubt the contents of 2024 are finalised and the compat DB has caught up. As of Jan 2024.

Error detected but no issues

When running check-es-compat it reports:

dist/registry.js
  10:50  error  ES2020 optional chaining is forbidden  ecmascript-compat/compat
  11:50  error  ES2020 optional chaining is forbidden  ecmascript-compat/compat

✖ 2 problems (2 errors, 0 warnings)

No issues found. Files are compatible with the target runtimes.

So there are 2 errors but no issues found? The return code is also 0 ("ok")

warning File ignored because of a matching ignore pattern

When I run it I get these warnings:

/home/ubuntu/app/dist/web/vnd.timers-browserify.js
  0:0  warning  File ignored because of a matching ignore pattern. Use "--no-ignore" to override

It seems to be applying the rules from .eslintignore. It might be nice if I could use --no-ignore as suggested, but that option is not propagated through by the command line tool.

Update or replace Lerna

Most things have fallen behind.

Most notably, these key/major dependencies:

  • ✔ browserslist - Nov 2019
  • Lerna - Feb 2021
  • ✔ ESLint - December 2021
  • Jest - Jan 2022

ES2015 (ES6) coverage

It shouldn't be difficult, just the work of joining up rules from eslint-plugin-es or ESLint core with the MDN compatibility data.

It's pretty old, and has a lot of features compared to the other versions, so it might not be worth doing.

New release

Hi Robat,

I'm after this commit:
00be982

but it isn't published.. is it possible to make a new release?

Use underlying plugin's prototype detection rules instead of custom no-restricted-syntax

ES2016 method 'Array.prototype.includes' is forbidden _eslint(ecmascript-compat/compat)_

I'm using plugin:ecmascript-compat/recommended and my browserslist is set to last 5 Chrome versions which absolutely supports ES2016 and Array.prototype.includes, yet ecma-compat/compat says this is forbidden?

In mdn/browser-compat-data, it lists Array.prototype.includes as being added in Chrome 47, which is certainly older than the last 5 Chrome versions.

If I'm reading things correctly, this is actually being picked up by eslint's no-restricted-syntax rule, as configured by eslint-plugin-ecmascript-compat's es2016.js.

Am I misunderstanding what this eslint plugin is supposed to do? Or is this a bug somewhere, because Array.prototype.inclues is definitely available in modern Chrome.

I'm silencing the error with eslint-disable-next-line ecmascript-compat/compat for now, but is less than ideal.

Allow specifying provided polyfills

Whitelist particular non-syntax features as "polyfill provided", so they aren't reported as problems.

The list would be specified as an option to the rule:

{
  "rules": {
    "ecmascript-compat/compat": [
      "error",
      {
        "polyfills": [
          "Array.prototype.flat"
        ]
      }
    ]
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.