es-tooling / module-replacements

A manifest of JS modules and their more modern/active replacements
MIT License
101 stars 11 forks source link

direct code replacement #42

Open danielroe opened 2 weeks ago

danielroe commented 2 weeks ago

I've just started https://github.com/danielroe/unplugin-purge-polyfills and it would be very useful to depend on this database for direct code replacements, e.g. instead of:

{
  "type": "simple",
  "moduleName": "is-plain-object",
  "replacement": "Use typeof v === \"object\" && v !== null && v.constructor === Object",
  "category": "micro-utilities"
}

we could have:

{
  "type": "simple",
  "moduleName": "is-plain-object",
  "replacement": "v => typeof v === \"object\" && v !== null && v.constructor === Object",
  "category": "micro-utilities"
}

(Or another field.)

I would be more than happy to contribute this if that would be welcome.

zloirock commented 2 weeks ago

The problem here is that those snippets in most cases are not exact replacements and users should take into account differences, so automatic replacement is not safe. Sure, it will work where it's a full replacement, but it's only a little subset.

43081j commented 2 weeks ago

i think its a smart idea but understanding many of the snippets may need a bit of extra work once they've been replaced (as @zloirock mentioned)

i wonder if we could review them so we end up with two lists or some flag to know "this one will mostly work", while the others need extra care

for example, is-regexp:

    {
      "type": "simple",
      "moduleName": "is-regexp",
      "replacement": "Use v instanceof RegExp, or if cross-realm, use Object.prototype.toString.call(v) === \"[object RegExp]\"",
      "category": "micro-utilities"
    },

in most cases you can safely use v instanceof RegExp, but in the odd case where someone's using VMs or something, they need to use the latter (toString)

alternatively we could just change these ones to always check the latter as a secondary, e.g.:

v instanceof RegExp || Object.prototype.toString.call(v) === '[object RegExp]';
danielroe commented 2 weeks ago

We should not provide code if it isn't a direct replacement - or maybe provide an array of possible replacements if there are multiple options depending on use case?

In the unplugin I mention, I wouldn't want to add these as default replacements unless we'd be pretty happy they were functionally equivalent, so some way of knowing from this dataset would be ideal.

43081j commented 2 weeks ago

using the existing one as a "message" and introducing a new property might make sense, so we don't need a breaking change to the manifests

e.g.

{
  "type": "simple",
  "moduleName": "is-plain-object",
  "replacement": "Use typeof v === \"object\" && v !== null && v.constructor === Object",
  "replacementCode": "typeof v === \"object\" && v !== null && v.constructor === Object",
  "category": "micro-utilities"
}

then just update any with multiple solutions/fixes to have just one in the code string at least

it'll mean a bunch of duplication though so maybe a breaking change is more sensible 🤔