1. babel-plugin-transform-decorators-legacy
A plugin for Babel 6 that (mostly) replicates the old decorator behavior from Babel 5.
babel-plugin-transform-decorators-legacy
Package: babel-plugin-transform-decorators-legacy
Created by: loganfsmyth
Last modified: Fri, 21 Jul 2023 15:42:22 GMT
Version: 1.3.5
License: MIT
Downloads: 383,294
Repository: https://github.com/loganfsmyth/babel-plugin-transform-decorators-legacy

Install

npm install babel-plugin-transform-decorators-legacy
yarn add babel-plugin-transform-decorators-legacy

Babel Legacy Decorator plugin

This is a plugin for Babel 6 that is meant to replicate the old decorator behavior from
Babel 5 in order to allow people to more easily transition to Babel 6 without needing to
be blocked on updates to the decorator proposal or for Babel to re-implement it.

Babel >= 7.x

This plugin is specifically for Babel 6.x. If you're using Babel 7, this plugin is not for you.
Babel 7's @babel/plugin-proposal-decorators officially supports the same logic that this
plugin has, but integrates better with Babel 7's other plugins. You can enable this with

 {
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "legacy": true }],
  ]
}

in your Babel configuration. Note that legacy: true is specifically needed if you
want to get the same behavior as transform-decorators-legacy because there
are newer versions of the decorator specification coming out, and they do not
behave the same way as this plugin does.

Installation & Usage

$ npm install --save-dev babel-plugin-transform-decorators-legacy

Add the following line to your .babelrc file:

{
    "plugins": ["transform-decorators-legacy"]
}

NOTE: Order of Plugins Matters!

If you are including your plugins manually and using transform-class-properties, make sure that transform-decorators-legacy comes before transform-class-properties.

 /// WRONG

"plugins": [
  "transform-class-properties",
  "transform-decorators-legacy"
]

// RIGHT

"plugins": [
  "transform-decorators-legacy",
  "transform-class-properties"
]

Why "legacy"?

Decorators are still only a relatively new proposal, and they are (at least currently) still
in flux. Many people have started to use them in their original form, where each decorator
is essentially a function of the form

function(target, property, descriptor){}

This form is very likely to change moving forward, and Babel 6 did not wish to support
the older form when it was known that it would change in the future. As such, I created this
plugin to help people transition to Babel 6 without requiring them to drop their decorators
or requiring them to wait for the new proposal update and then update all their code.

Best Effort

This plugin is a best effort to be compatible with Babel 5's transpiler output, but there
are a few things that were difficult to reproduce, and a few things that were simply incorrect
in Babel 5 with respect to the decorators proposal.

Two main things to mention as differences, though not things you are likely to encounter:

  1. Decorators expressions are evaluated top to bottom, and executed bottom to top. e.g.

    function dec(id){
        console.log('evaluated', id);
        return (target, property, descriptor) => console.log('executed', id);
    }
    
    class Example {
        @dec(1)
        @dec(2)
        method(){}
    }
    

    In Babel 5, this would output:

    evaluated 2
    evaluated 1
    executed 2
    executed 1
    

    With this plugin, it will result in:

    evaluated 1
    evaluated 2
    executed 2
    executed 1
    

    which is what the spec dictates as the correct behavior and was incorrect in Babel 5.

  2. Static class property initializers are evaluated once up front.

    If you decorate a static class property, you will get a descriptor with an initializer property.
    However whereas with Babel 5 this could be re-executed multiple times with potentially differing
    results, decorators-legacy will precompute the value and return an initializer that will
    return that value. e.g.

    function dec(target, prop, descriptor){
        let {initializer} = descriptor;
        delete descriptor.initializer;
        delete descriptor.writable;
    
        descriptor.get = function(){
            return initializer.call(this);
        };
    }
    
    var i = 0;
    
    class Example {
        @dec
        static prop = i++;
    }
    

    In Babel 5, every access to prop would increment i.
    In Babel 6, the very first value of i will be cached for future initializer calls.

    The spec is a little vague around how initializers work for repeat calls, and I'd consider
    calling an initializer multiple times to be a mistake in general, so hopefully this will
    not cause anyone trouble.

License

MIT (c) 2015

RELATED POST

10 Must-Know Windows Shortcuts That Will Save You Time

10 Must-Know Windows Shortcuts That Will Save You Time

Arrays vs Linked Lists: Which is Better for Memory Management in Data Structures?

Arrays vs Linked Lists: Which is Better for Memory Management in Data Structures?

Navigating AWS Networking: Essential Hacks for Smooth Operation

Navigating AWS Networking: Essential Hacks for Smooth Operation

Achieving Stunning Visuals with Unity's Global Illumination

Achieving Stunning Visuals with Unity's Global Illumination

Nim's Hidden Gems: Lesser-known Features for Writing Efficient Code

Nim's Hidden Gems: Lesser-known Features for Writing Efficient Code