loganfsmyth / babel-plugin-transform-decorators-legacy Goto Github PK
View Code? Open in Web Editor NEWA plugin for Babel 6 that (mostly) replicates the old decorator behavior from Babel 5
License: MIT License
A plugin for Babel 6 that (mostly) replicates the old decorator behavior from Babel 5
License: MIT License
Turning on transform-decorators-legacy will cause errors if you use class properties in a specific way.
class Foo {
static SECOND = 1000;
static MINUTE = Foo.SECOND * 60;
}
This will say that Foo is undefined while trying to evaluate Foo.SECOND
. Without the decorators-legacy plugin this works.
I am working on a project using mobx + react. And I need to use decorators. But I am getting an Uncaught TypeError: decorator is not a function
in the Chrome console after Webpack bundle. Webpack shows no errors.
My webpack loader.
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
loader: 'babel', // 'babel-loader' is also a legal name to reference
cacheDirectory: true,
query: {
plugins: [
"transform-decorators-legacy",
],
presets: ['react', 'es2015', 'stage-1']
}
}
My dependencies:
"devDependencies": {
"babel-cli": "^6.10.1",
"babel-core": "^6.10.4",
"babel-loader": "^6.2.4",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.11.1",
"babel-preset-stage-1": "^6.5.0",
"mobx": "^2.3.6",
"mobx-react": "^3.5.0",
"react": "^15.2.1",
"react-dom": "^15.2.1",
"webpack": "^1.13.1"
}
Some further investingation points to this plugin. The errors pops out in the _applyDecoratedDescriptor
method.
Am I missing something?
Hi Logan - I think I found a bug with the target
parameter of a decorator. The target
is supposed to return the class associated for the decorator.
A decorator on the class level works fine, I get an function back that I can instantiate.
A decorator on the method level returns back an Object
of the class that I cannot instantiate.
function dec(debug) {
return (target, property, descriptor) => {
console.log(debug);
console.log(target);
}
}
@dec('from class:')
class A {
@dec('from method:')
doSomething(){
}
}
Console output:
from method:
> A {}
from class:
> function A () {
_classCallback(this, A);
}
I believe the target
should be consistent where methods and classes get the same target. The target
I received from the class level is what's useful to me here since I can't instantiate the other.
Thanks!
Is it possible to overwrite the implementation of some method? Overriding the property
on the target
does not really overwrite the method, like this:
function dec(id) {
function exec(target, property, descriptor) {
console.log('Prototype', target.prototype);
target[property] = function() {
console.log('executed', id);
};
}
return exec;
}
class Example {
@dec(1)
method() {
console.log('Method called');
}
}
let example = new Example();
example.method();
This code still prints "Method called". Also, there is no prototype
in target
.
Is it possible to overwrite the method of the target somehow?
Thanks,
'use strict';
function classDecorator(Target) {
return class DecoratedClass extends Target {
constructor(a) {
console.log(a);
super(a);
}
};
}
@classDecorator
class Test {
static create() {
return new Test(1);
}
}
Test.create();
in babel 5, it will output 1
, but not in this plugin.
.babelrc:
{
"plugins": [
"transform-decorators-legacy"
]
}
decorators only work when adding plugins: [ 'transform-decorators-legacy' ]
in jsx loader of webpack.config.js
. Is it a must?if so, please add to the Usage Doc.
I've upgraded from Babel 5 to Babel 6 and use your plugin to build this react-anything-sortable-example with gulp and browserify:
import React from 'react';
import Sortable from 'react-anything-sortable';
import { sortable } from 'react-anything-sortable';
@sortable
class DemoHOCItem extends React.Component {
render() {
return (
<div {...this.props}>
{this.props.children}
</div>
);
}
}
export default DemoHOCItem;
class Test extends React.Component {
constructor() {
super();
this.state = {
items: ['four','five','six']
};
}
render() {
function renderWithSortable(renderItem, index) {
return (
<DemoHOCItem className="vertical" sortData="renderItem" key={index} dynamic>
{console.log('rendering with sortable')}
{renderItem+' sortable'}
</DemoHOCItem>
);
}
return (
<div className="demo-container">
<Sortable className="vertical-container" direction="vertical">
{this.state.items.map(renderWithSortable, this)}
</Sortable>
</div>
);
}
};
export default Test;
On the initial rendering of <DemoHOCItem/>
I get this warning:
main.js:28024 Warning: Unknown props `sortData`, `onSortableItemMount`, `onSortableItemReadyToMove`, `sortable`, `sortHandle` on <div> tag. Remove these props from the element. For details, see https://fb.me/react-unknown-prop
in div (created by DemoHOCItem)
in DemoHOCItem (created by SortableItem)
in SortableItem (created by Test)
in div (created by Sortable)
in Sortable (created by Test)
in div (created by Test)
in Test (created by RoutingContext)
in div (created by App)
in App (created by RoutingContext)
in RoutingContext (created by Router)
in Router
also when dragging an sortable item for the first time:
main.js:28024 Warning: Unknown prop `isDragging` on <div> tag. Remove this prop from the element. For details, see https://fb.me/react-unknown-prop
in div (created by DemoHOCItem)
in DemoHOCItem (created by SortableItem)
in SortableItem (created by Test)
Subsequent renderings (Without reloading the app) no longer produce warnings, so the sortable-module does its magic.
My guess is that the "sortable"-decorator is not evaluated on the first render, therefore React does not know what to do with all the functions provided by <div {...this.props}>
in DemoHOCItem.render()
Is there something I can do to get rid of the warning?
If a class decorator is used before export default
and the class contains a nested class definition, the decorator applies to that nested class instead.
Steps to reproduce:
package.json:
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"dependencies": {},
"devDependencies": {
"babel-cli": "^6.18.0",
"babel-plugin-transform-decorators-legacy": "^1.3.4"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
wrong.es6 (the @id
decorator is applied before export default)
const id = _ => _;
class Parent {
}
@id
export default class Sample {
method() {
class Child extends Parent {
}
return Child;
}
}
Output:
./node_modules/.bin/babel --plugins transform-decorators-legacy wrong.es6
const id = _ => _;
let Parent = class Parent {};
let Sample = class Sample {
method() {
var _class;
let Child = id(_class = class Child extends Parent {}) || _class;
return Child;
}
};
export { Sample as default };
The decorator incorrectly applies to the nested class Child
right.es6 (the decorator is applied after export.default
)
const id = _ => _;
class Parent {
}
export default @id class Sample {
method() {
class Child extends Parent {
}
return Child;
}
}
Output:
./node_modules/.bin/babel --plugins transform-decorators-legacy right.es6
var _class;
const id = _ => _;
let Parent = class Parent {};
export default id(_class = class Sample {
method() {
let Child = class Child extends Parent {};
return Child;
}
}) || _class;
I expected transpiling wrong.es6
to either throw an error or apply @id
to Parent
Here is my code:
import 'babel-core/register'
import 'babel-polyfill'
function Input() {
return () => {}
}
class A {
@Input() b;
constructor() {}
}
window.a = new A()
It compiles into:
function Input() {
return function () {};
}
var A = (_class = function A() {
_classCallCheck(this, A);
this.b = _init.apply(this);
}, (_desc = Input()(_class.prototype, 'b', _desc = {
enumerable: true,
configurable: true,
writable: true,
initializer: null
}) || _desc, _init = _desc.initializer), _class);
window.a = new A();
Which looks fine at first, but then...
Uncaught TypeError: Cannot read property 'apply' of null
Here it is:
this.b = _init.apply(this);
It is a part of not implemented yet behavior? I really need it for Input() decorators in ng-forward.
I have such error: Cannot assign to read only property 'name' of object '#<Category>'
when I use non initialized properties decorated with decorators and then trying to assign values to these properties.
import {Entity, PrimaryColumn, Column} from "typeorm";
@Entity()
export class Category {
@PrimaryColumn("int", { generated: true })
id;
@Column("string")
name;
}
Solution is to do it this way:
import {Entity, PrimaryColumn, Column} from "typeorm";
@Entity()
export class Category {
@PrimaryColumn("int", { generated: true })
id = undefined;
@Column("string")
name = "";
}
Which is ugly. I guess the reason is that it does not make descriptor writable. Is there any better solution for this problem?
Thanks for this plugin. It sucks that a lot of React infrastructure started using decorators and now Babel isn't supporting it. I'm a little confused from the docs and the thread on Phabricator if decorating methods is supported by this plugin.
In my app I have this decorator for toggling classes on the react render method. Works fine with Babel 5 but chokes with Babel 6. Please let me know if I'm doing something wrong or if this behavior is not supported
//.babelrc
{
"presets": ["react", "es2015", "stage-0"],
"env": {
"development": {
"plugins": [
"rewire",
"transform-runtime",
"transform-decorators-legacy",
"typecheck",
["react-transform",
{
"transforms": [{
"transform": "react-transform-hmr",
"imports": ["react"],
"locals": ["module"]
}, {
"transform": "react-transform-catch-errors",
"imports": ["react", "redbox-react"]
}]
}]
]
},
"production": {
"plugins": [
"transform-runtime",
"transform-decorators-legacy",
"typecheck"
]
}
}
}
//decorator.js
import React from 'react';
import _ from 'lodash';
import cx from 'classnames';
export default function(...args) {
/*eslint no-use-before-define:0*/
let decArgs;
if (args.length === 1) {
//if the decorator is called with an `omit` argument then return the function
decArgs = args[0];
return decorate;
} else if (args.length === 3) {
//if the decorator is called with by the method with no initial arguments
return decorate.apply(null, args);
}
function decorate(target, key, descriptor) {
return {
...descriptor,
value(...args) {
const {someFluxProp, anotherFluxProp} = this.props;
const {omit} = decArgs || {};
const Comp = descriptor.value.apply(this, args);
const className = cx(_.assign({}, makeClasses(Comp.props.className), _.omit({
'step-current': anotherFluxProp,
'is-hidden': someFluxProp
}, omit)));
return React.cloneElement(Comp, {className});
}
};
}
}
SomeClass extends React.Component {
@addClassDec({omit: 'is-hidden'})
render() {
return <div className="whatevs" />
}
}
When I do this I get output:
ERROR in ./src/js/components/sample.jsx
Module parse failed: /Users/davidfox-powell/dev/frontend-boilerplate/node_modules/babel-loader/index.js?{"presets":["react","es2015","stage-0"],"plugins":["transform-decorators-legacy","transform-runtime","typecheck",["react-transform",{"transforms":[{"transform":"react-transform-hmr","imports":["react"],"locals":["module"]},{"transform":"react-transform-catch-errors","imports":["react","redbox-react"]}]}]]}!/Users/davidfox-powell/dev/frontend-boilerplate/node_modules/eslint-loader/index.js!/Users/davidfox-powell/dev/frontend-boilerplate/src/js/components/sample.jsx Line 3: Unexpected token
You may need an appropriate loader to handle this file type.
| 'use strict';
|
| import _Object$defineProperty from 'babel-runtime/core-js/object/define-property';
|
| var _dec, _dec2, _class, _desc, _value, _class2, _class3, _temp;
When you name a async method get
and try to decorate it, it will get called whenever it is referenced and not function as expected.
let decorator = target => {
return target;
};
class Example {
@decorator async get () {
console.log('called');
}
}
let instance = new Example();
typeof instance.get;
I don't have enough insight to determine if this is due to babel 6 transform-class-properties or transform-decorators-legacy, but there is inconsistencies when migrating from babel5 decorators.
I created a sample project to demonstrate it: https://github.com/themouette/demo-decorators-classprops
Static properties are applied to the decorated class instead of the original class.
Current generated code looks like:
// ...
var Test = decorator(_class = function () {
function Test() {
_classCallCheck(this, Test);
}
_createClass(Test, [{
key: 'render',
value: function render() {
return 'foo';
}
}]);
return Test;
}()) || _class;
Test.propTypes = {
foo: 'Hello'
};
// ...
When it should look someting like:
// ...
_class = function () {
function Test() {
_classCallCheck(this, Test);
}
_createClass(Test, [{
key: 'render',
value: function render() {
return 'foo';
}
}]);
return Test;
}()) || _class;
_class.propTypes = {
foo: 'Hello'
};
var Test = decorator(_class);
// ...
Am I doing something wrong?
class User {
static func = User
}
console.log(User.func) // undefined
Its error
Example, a use ORM and i cant declarate database structure types
class User extends Model {
static schema = {
name: String,
age: String,
friends: [User], // User is undefined
}
// this code will be located in constructor
name = User.createRandomName() // i cant call this
}
I've included the plug-in in my webpack config, but I'm still seeing "Decorators are not supported yet in 6.x pending proposal update" errors during transpilation.
Here is the related webpack loader:
{
test: /\.js/,
loader: 'babel',
exclude: /node_modules/,
query: {
plugins: ['transform-decorators-legacy'],
presets: ['es2015', 'react', 'stage-0']
}
}
Relevant parts of my package.json are:
{
"babel-cli": "6.3.17",
"babel-core": "6.3.13",
"babel-loader": "6.2.0",
"babel-plugin-rewire": "1.0.0-beta-3",
"babel-plugin-transform-decorators-legacy": "1.3.1",
"babel-preset-es2015": "6.3.13",
"babel-preset-react": "6.3.13",
"babel-preset-stage-0": "6.3.13"
}
All decorators in my project are class-level, for example:
@Foo()
export default class Bar
...and
@Do(Something)
export default class Bar
It seems like I shouldn't see the "Decorators are not supported yet in 6.x pending proposal update" message with this plugin installed. Am I doing something wrong?
TC39 now says decorators are stage 2. Could this plugin's readme be updated to reflect the current status?
My impression (after an hour of reading conflicting info in various readmes) is that decorators are now well and truly on the standards track, and we're now waiting for an official Babel plugin. But I'm not clear on whether the official plugin will be essentially the same as this 'legacy' one, or if they will work differently. In other words I want some guidance on whether I should start using decorators today via this plugin - will it be easy to switch?
If you know the current situation it would be great to explain it the 'why legacy' section in this readme.
When running in babelify with browserify debug option set to true it leads to error in generating source map.
If i have a base class, extend it, then apply a decorator to the property of that new class, the base class and all the classes that extend from it have that decorator. It seems to be an issue from applying the decorator to the prototype, which is the base class. I'm not sure if this is a babel issue or this plugin's issue.
From the generated code:
_applyDecoratedDescriptor(_class2.prototype, 'logo', [_dec3], {
enumerable: true,
configurable: true,
initializer: function initializer() {
return '';
}
})
_class2
is the new class, and _class2.prototype
is the base class. the decorator gets applied to the base class and all of it's children, adding the property to the children.
The spec says that decorators have to support syntax like this:
var o = {
@F("color")
@G
bar() { }
}
But in fact the transformer doesn't do any transformation(decorations).
Since this is a legacy/maintain old functionality plugin, I'm just reporting this, I realise it may not be worth fixing, the plugin is great anyway and has saved me a lot of trouble :)
The following (stripped down a bit) works:
import CSSModules from 'react-css-modules' ;
import styles from './accordion.css' ;
export function layoutAccordion (Header, Content) {
class __Accordion extends React.Component {
....
}
return CSSModules(__Accordion, styles) ;
}
but the decorated version doesn't:
import CSSModules from 'react-css-modules' ;
import styles from './accordion.css' ;
export function layoutAccordion (Header, Content) {
@CSSModules(styles)
class __Accordion extends React.Component {
....
}
return __Accordion
}
The full error:
Error: app/layout/accordion.js: We don't know what to do with this node type. We were previously a Statement but we can't fit in here?
at NodePath.insertBefore (/usr/lib/node_modules/babel-cli/node_modules/babel-core/node_modules/babel-traverse/lib/path/modification.js:62:13)
at NodePath.unshiftContainer (/usr/lib/node_modules/babel-cli/node_modules/babel-core/node_modules/babel-traverse/lib/path/modification.js:254:15)
at Scope.push (/usr/lib/node_modules/babel-cli/node_modules/babel-core/node_modules/babel-traverse/lib/scope/index.js:1031:41)
at Scope.generateDeclaredUidIdentifier (/usr/lib/node_modules/babel-cli/node_modules/babel-core/node_modules/babel-traverse/lib/scope/index.js:308:10)
at /home/mike/applify2/node_modules/babel-plugin-transform-decorators-legacy/lib/index.js:27:56
at Array.map (native)
at applyEnsureOrdering (/home/mike/applify2/node_modules/babel-plugin-transform-decorators-legacy/lib/index.js:25:53)
at PluginPass.ClassExpression (/home/mike/applify2/node_modules/babel-plugin-transform-decorators-legacy/lib/index.js:223:38)
at newFn (/usr/lib/node_modules/babel-cli/node_modules/babel-core/node_modules/babel-traverse/lib/visitors.js:278:19)
at NodePath._call (/usr/lib/node_modules/babel-cli/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js:76:18)
When using babel-plugin-transform-class-properties
any decorated class property is undefined
function myDecorator(){
// Decorate stuff
}
...
class Person{
@myDecorator
age = 43; // Nope - doesn't work
@myDecorator
toString(){ // Yep - works
}
constructor(){
console.log(this.age) // undefined
}
}
Furthermore, the decorator is never called for the class property. Am I missing something?
Is there any chance that this transform will be smart enough to keep it's code in separate module, like "transform-runtime" does?
Of course, it's not necessary to joyfully use it – just to be, you know, and ideal tool =)
Hello,
I have the error: Parsing error: Unexpected character '@'. I am not sure what is wrong.
the code is:
import ui from 'redux-ui';
**@**ui({})
my configuration is:
{
"parser": "babel-eslint",
"extends": ["eslint:recommended", "plugin:react/recommended"],
"env": {
"es6": true,
"browser": true,
"node": true
},
"plugins": ["react"],
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"modules": true,
"jsx": true
}
},
"rules": {
"eqeqeq": [2, "allow-null"],
"jsx-quotes": 2,
"react/display-name": 2,
"react/jsx-curly-spacing": [2, "never"],
"react/self-closing-comp": 2,
"react/jsx-indent-props": [2, 2],
"react/jsx-no-duplicate-props": 2,
"no-console":0,
"strict": 0
}
}
I am using this plugins and presets:
presets: ["es2015", "react", "stage-0"],
"plugins": ["babel-plugin-transform-decorators-legacy", "transform-runtime"]
The source code includes @decorators, which are not officially supported by babel and the only way to make them work is by introducing "babel-plugin-transform-decorators-legacy".
Can we please rewrite code to include them in a more vanilla style?
For class functions decorators the target argument is not an actual reference to the real class but a reference to an instance, sounds weird to me. Is it correct/intended?
let assert = require('assert');
let fnTarget = null;
let fnTargetConstructor = null;
function fnDec(target, methodName, descriptor) {
fnTarget = target;
fnTargetConstructor = target.constructor;
return descriptor;
}
class A {
@fnDec
doSomething() {}
}
assert(fnTarget !== A);
assert(fnTargetConstructor === A);
My package.json
:
"babel-core": "^6.11.4",
"babel-plugin-transform-decorators-legacy": "1.3.4"
My .babelrc
:
{
"plugins": [
"transform-decorators-legacy"
]
}
It's a little unclear as to when instance members' initializers are run.
There are two functions in the transpiled code: _initDefineProp
, and _applyDecoratedDescriptor
.
Both may run initializers.
While the _initDefineProp
runs initializer with this
bound to a class instance,
the _applyDecoratedDescriptor
runs initializer (if it decides to run it) with this
bound to a class constructor function.
E.g. I was trying to create a decorator @BindThis
that would bind function to this
instance during construction.
class My { @BindThis() mouseclick(e) {...} }
BindThis had to replace value with initializer like this:
'function() { return originalFn.bind(this); }'
Unfortunately this initializer is called at _applyDecoratedDescriptor where this
is constructor.
Can you please clarify?
Thanks.
this works:
class MyClass {
static MY_CONSTANT = 'foo';
static MY_ANOTHER_CONSTANT = {
[MyClass.MY_CONSTANT]: 'bar',
};
}
but it won't work after enabling transform-decorators-legacy
: Cannot read property 'MY_CONSTANT' of undefined.
I am using Material-UI for my react application.
Here is an example from their documentation
This doesn't work after compiling with this plugin.
import MyRawTheme from 'path/to/your/raw/theme/file';
import ThemeManager from 'material-ui/lib/styles/theme-manager';
import ThemeDecorator from 'material-ui/lib/styles/theme-decorator';
const theme = ThemeManager.getMuiTheme(MyRawTheme);
@ThemeDecorator(theme)
class MyComponent extends Component {
}
export default MyComponent;
However this works
export default ThemeDecorator(theme)((MyComponent));
var count = 0;
@connect(state => ({
products: state.products
}))
export default class ParameterNode extends React.Component {
constructor(props, context) {
super(props, context);
console.log('props', props);
}
render() {
count = count + 1;
if(count < 5) {
return <ParameterNode />;
}
else {
return <div></div>;
}
}
}
And the console output:
props Object {products: Object}
props Object {}
props Object {}
props Object {}
props Object {}
On the babel 5 it's ok.
Hi
Am getting the Unknown plugin error when deploying to CI server. Do you have any idea what could be the cause?
My webpack configuration is following:
var webpack = require('webpack');
var babelSettings = { presets: ['react', 'es2015', 'stage-0'] };
babelSettings.plugins = ['transform-decorators-legacy'];
module.exports = {
entry: './entry',
module: {
loaders: [
{ test: /\.tsx?$/, loader: 'babel?' + JSON.stringify(babelSettings) + '!awesome-typescript', exclude: /node_modules|lib/ },
{ test: /\.jsx?$/, loader: 'babel', query: babelSettings, exclude: /node_modules/ },
{ test: /\.css$/, loader: 'null' },
{ test: /\.(png|jpe?g)(\?.*)?$/, loader: 'url?limit=8182' },
{ test: /\.(svg|ttf|woff2?|eot)(\?.*)?$/, loader: 'file' }
]
}
};
if (process.env.NODE_ENV !== 'production') {
var ForkCheckerPlugin = require('awesome-typescript-loader').ForkCheckerPlugin;
module.exports.plugins = [new ForkCheckerPlugin()]
}
This is the error I am recieveing:
Errors prevented bundling:
While processing files with webpack:webpack (for target web.browser):
entry/client/webpack.conf.js: ./entry/client/entry.js
Module build failed: ReferenceError: Unknown plugin
"transform-decorators-legacy" specified in "base" at 0, attempted to resolve
relative to
"/home/rof/src/github.com/tomitrescak/kickstart-flowrouter/entry/client"
at
/home/rof/src/github.com/tomitrescak/kickstart-flowrouter/.meteor/local/webpack-npm/node_modules/babel-core/lib/transformation/file/options/option-manager.js:193:17
Previously this worked in babel 5:
@connect()
export default class Page extends React.Component {
}
However it doesn't seem like this case is covered by this plugin. Curious if it's possible to add support for it?
Disclaimer: thanks a lot for taking the time and effort to implement this, I know you tried your best to provide us with a tentative implementation regardless of the decorator spec being questioned at the time.
It seems that this implementation currently doesn't support decorating static properties; I couldn't find any reference to them in either the source or the tests. Do you plan to add support for them in the near future?
I have a following code, but the decorator is not called.
const sandbox = (...args) => (target) => {
target.prototype = new Sandbox(...args);
};
// Docorator doesn't work
// @sandbox(child, {
// perimeters: [
// perimeter
// ]
// })
class MyClass {}
// but this works
sandbox(child, {
perimeters: [
perimeter
]
})(MyClass);
Here is my package.json:
// ...
"babel-cli": "^6.11.4",
"babel-core": "^6.11.4",
"babel-eslint": "^6.1.1",
"babel-plugin-check-es2015-constants": "^6.3.13",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-es2015-arrow-functions": "^6.3.13",
"babel-plugin-transform-es2015-block-scoped-functions": "^6.3.13",
"babel-plugin-transform-es2015-block-scoping": "^6.3.13",
"babel-plugin-transform-es2015-classes": "^6.3.13",
"babel-plugin-transform-es2015-computed-properties": "^6.3.13",
"babel-plugin-transform-es2015-destructuring": "^6.3.13",
"babel-plugin-transform-es2015-for-of": "^6.3.13",
"babel-plugin-transform-es2015-function-name": "^6.3.13",
"babel-plugin-transform-es2015-literals": "^6.3.13",
"babel-plugin-transform-es2015-modules-commonjs": "^6.3.13",
"babel-plugin-transform-es2015-object-super": "^6.3.13",
"babel-plugin-transform-es2015-parameters": "^6.3.13",
"babel-plugin-transform-es2015-shorthand-properties": "^6.3.13",
"babel-plugin-transform-es2015-spread": "^6.3.13",
"babel-plugin-transform-es2015-sticky-regex": "^6.3.13",
"babel-plugin-transform-es2015-template-literals": "^6.3.13",
"babel-plugin-transform-es2015-unicode-regex": "^6.3.13",
"babel-plugin-transform-object-rest-spread": "^6.3.13",
"babel-preset-es2015": "^6.6.0",
"babel-register": "^6.3.13",
"babelify": "^7.2.0",
"browserify": "^13.0.1",
// ...
and .babelrc:
{
"plugins": [
["transform-es2015-template-literals", { "loose": true }],
"transform-es2015-literals",
"transform-es2015-function-name",
"transform-es2015-arrow-functions",
"transform-es2015-block-scoped-functions",
["transform-es2015-classes", { "loose": true }],
"transform-es2015-object-super",
"transform-es2015-shorthand-properties",
["transform-es2015-computed-properties", { "loose": true }],
["transform-es2015-for-of", { "loose": true }],
"transform-es2015-sticky-regex",
"transform-es2015-unicode-regex",
"check-es2015-constants",
["transform-es2015-spread", { "loose": true }],
"transform-es2015-parameters",
["transform-es2015-destructuring", { "loose": true }],
"transform-es2015-block-scoping",
"transform-object-rest-spread",
"transform-decorators-legacy"
],
"env": {
"commonjs": {
"plugins": [
["transform-es2015-modules-commonjs", { "loose": true }]
]
},
"es": {
"plugins": [
"./build/use-lodash-es"
]
}
}
}
Just stumbled across this one
function decorator(target, attr, descriptor)
{
return descriptor;
}
class Foo
{
@decorator
* gen() { yield 1; }
}
will result in the following error
SyntaxError: src/test.es: Unexpected token (xx:xx)
xx | @decorator
> xx | *gen() { yield 1; }
Is this by design or can this be fixed?
Because, when doing this instead
class Foo
{
@decorator
async gen() {}
}
the decorator will be applied just fine.
And, by looking at the spec, in 14.3 it states that the GeneratorDefinition from 14.4 is a valid MethodDefinition.
And according to https://github.com/wycats/javascript-decorators#grammar PropertyDefinition refers to MethodDefinition.
I have the following code:
import React, from 'react'
import { observer } from 'mobx-react'
@observer
class OrgsPage extends React.Component {
render = () =>
<div>Hello</div>
}
export default OrgsPage
When I try and use this as a component in React I get:
babel-runtime.js?hash=71fe7d0…:108 Uncaught TypeError: Cannot call a class as a function
at classCallCheck (http://localhost:4000/packages/babel-runtime.js?hash=71fe7d0d01dc808e2a80cb0a7958fb31e46323d5:108:13)
at Constructor.OrgsPage (http://localhost:4000/app/app.js?hash=7ba134c41c0997baa4644e0e7b2750d3c4341f2f:1794:37)
at Constructor.render (http://localhost:4000/packages/modules.js?hash=58c8b0b77d6bd50615c786bc9f20afd954ec52db:129542:32)
at Object.allowStateChanges (http://localhost:4000/packages/modules.js?hash=58c8b0b77d6bd50615c786bc9f20afd954ec52db:116825:15)
at Reaction.<anonymous> (http://localhost:4000/packages/modules.js?hash=58c8b0b77d6bd50615c786bc9f20afd954ec52db:129440:44)
...
This does not happen if I do any of the following:
@observer
render
method to be a normal method (not a class property)render
as a normal method and add in another class property under a different nameMy .babelrc
:
{
"presets": [
"react",
"es2015",
"stage-3"
],
"plugins": [
"transform-decorators-legacy",
"transform-class-properties"
]
}
And (what I think is) relevant package.json
:
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-0": "^6.16.0",
This was working for me, and then updated some of my npm packages (like babel-preset-es2015
) and then it stopped working. But npm being npm I can't see to get my node_modules back into that state again to prove it's a change between 6.16.0 and 6.18.0 of babel-preset-es2015
.
function classDecorator(Target) {
return class DecoratedClass extends Target {
test() {
return 'decorated';
}
};
}
@classDecorator
class Test {
static test() {
return 'original';
}
static run() {
// `Test` is not the *decorated* class here, but it is in bebel 5.
console.log(Test.test());
}
}
Test.run();
In bebel 5, it will return 'decorated', in this plugin, it return 'original'.
Why decorators was removed from Babel?
I use it in many projects.
function Hack(classTarget) {
classTarget.prototype.method = function() {
console.log("Echo:", this.echo);
}
}
@Hack
class Random {
constructor() {
this.echo = "Entropy";
}
}
let obj = new Random();
obj.method();
Hello @loganfsmyth, thanks again for your dedication.
It seems that v1.3.0 may be broken, related to importing _Object$defineProperty
.
In this gist you will find my original test source, and its transpiled version with v1.2.0 and v1.3.1. In the output of v1.3.0, the following line is present:
import _Object$defineProperty from 'babel-runtime/core-js/object/define-property';
I get the following error when I run the file:
import _Object$defineProperty from 'babel-runtime/core-js/object/define-property';
^^^^^^
SyntaxError: Unexpected token import
at exports.runInThisContext (vm.js:54:16)
at Module._compile (module.js:375:25)
at Object.Module._extensions..js (module.js:406:10)
at Module.load (module.js:345:32)
at Function.Module._load (module.js:302:12)
at Module.require (module.js:355:17)
at require (internal/module.js:13:17)
I've checked my babel config and babel-plugin-transform-es2015-modules-commonjs
is after babel-plugin-transform-decorators-legacy
though. v1.2.0 still works fine for the given example.
Any idea what could cause this? Is there any way I can contribute?
From: https://phabricator.babeljs.io/T2645
@loganfsmyth: I tried on the day of the latest release a few days ago, but had to stop because I couldn't get it to work with mobservable. I'm trying again today and trying to track down the problems....
First problem: Uncaught Error: Decorating class property failed. Please ensure that transform-class-properties is enabled
my .babelrc has stage-1 enabled:
{
presets: ['es2015', 'stage-1', 'react'],
plugins: ['add-module-exports', 'transform-decorators-legacy']
}
If I manually add transform-class-properties (maybe I'm configuring incorrectly?) I do not get the warning:
{
presets: ['es2015', 'stage-1', 'react'],
plugins: ['add-module-exports', 'transform-class-properties', 'transform-decorators-legacy']
}
but I run into a second problem:
class MyClass {
@observable hello = {things: []};
@observable get world() { return this.hello.things; }
}
The world decorator is added, but the hello one is missing from the class decoration section. So it looks like there is a change / bug in how decorators handle class properties...(other more simple ones like @observable hello = null;
are skipped too)
The current transformation treats functions in object literals differently depending on whether they are inlined or referenced. I am trying to apply a simple wrapper decorator to functions in an object literal, as in this example:
function decorator(target, name, descriptor) {
const original = descriptor.value;
descriptor.value = function decorated() {
console.log(`wrapper: ${name}`);
return original(...arguments);
};
}
function foo() {
console.log('foo');
}
const obj = {
// Referenced function is not decorated
@decorator foo,
// Inline function is decorated
@decorator bar() {
console.log('bar');
}
};
I would expect these syntaxes to work identically, but they do not:
obj.foo();
// "foo"
obj.bar();
// "wrapper: bar"
// "bar"
I found a workaround, but it's fairly ugly, because it needs to refer to the initializer
property of the descriptor, which seems to be internal to this plugin:
function decorator(target, name, descriptor) {
const original = descriptor.initializer ?
descriptor.initializer() :
descriptor.value;
delete descriptor.initializer;
descriptor.value = function decorated() {
console.log(`wrapper: ${name}`);
return original(...arguments);
};
}
Hi.
Trying to use this plugin. I'm probably doing something wrong.
I created a gist with a simplified test case
https://gist.github.com/cowchimp/fd1f2d19ba55997d371e861d09ddd76f
When I try to use a class decorator I get a _dec is not a function
error.
When I comment out the line with the use of the decorator foo
everything works.
Can you please let me know what I'm doing wrong?
Thanks.
Decorating class properties with computed names throws an error during compilation and class properties whose names are strings will generate code which will throw an error with the message: Decorating class property failed. Please ensure that transform-class-properties is enabled.
.
Google-ing for that error turned up issue #13 and looking through the other issues #59 seems to actually be the same problem.
I'd like to add the reproduction cases from the attached gist to the unit test but I am not confident enough I'll be able to actually solve this issue by myself. :)
See this gist for all the files: Decorating properties with computed names
I'm encountering a bug due to a wrong scope variable definition.
I have a component:
@props({
label: React.PropTypes.string,
className: React.PropTypes.string,
style: React.PropTypes.object
})
class Component extends React.Component {
render() {
const { label, ...props } = this.props;
return (
<div {...props}>
{label}
</div>
);
}
}
but in render
method props
variable is equal to function es7PropsDecorator(type, options) { ... }
, while with babel@^5
works just fine.
I don't have a minimal test case yet, but this babelrc works pre-6.5.0, and throws this error with 6.5.0:
ModuleBuildError: Module build failed: SyntaxError: /project/ui/views/Component.jsx: Decorators are not supported yet in 6.x pending proposal update.
The .babelrc:
{
"presets": [
"es2015",
"stage-0",
"react",
"async-to-bluebird"
],
"plugins": [
]
}
Edit: Appears at this time that putting the plugin in the babelrc (and not in babel-loader's query) fixes the issue.
Using a decorator on a Symbol
class member throws:
function C(target, property, descriptor) {
return descriptor;
}
const B = Symbol();
class A {
@C
[B] = null;
}
The following error, in the above case:
return decorator(target, property, desc) || desc;
^
TypeError: decorator is not a function
Is this intended to work?
I see in the current decorators spec (2.1.1 - 1. Let propKey
be the result of evaluating propertyName
), this will work once that reaches implementation, but is there a specific reason not to for the legacy transform (would it break existing modules, was it explicitly disallowed in the original proposal)?
I have compiled this
class Foo{
/**
* method 1
*/
@decorator
method1(){
return "method1";
}
/**
* method 2
*/
method2(){
return "method2";
}
}
I got
var Foo = (_class = function () {
function Foo() {
_classCallCheck(this, Foo);
}
_createClass(Foo, [{
key: "method1",
value: function method1() {
return "method1";
}
/**
* method 2
*/
}, {
key: "method2",
value: function method2() {
return "method2";
}
}]);
return Foo;
}(), (_applyDecoratedDescriptor(_class.prototype, "method1", [decorator], Object.getOwnPropertyDescriptor(_class.prototype, "method1"), _class.prototype)), _class);
missing /** method1 **/
After transpiling my project to UMD code,
all decorated methods, or all methods which calls other decorated methods, are undefined when called.
Some of those methods are mobx getters, computed values, or actions.
Config files:
Demo files:
Apologies ... but I can't figure out how I should enable this plugin in Webpack.
I tried adding it like this
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: [
'es2015',
'react',
'stage-0'
]
},
plugins: ['transform-decorators-legacy']
}
but I still get the error Decorators are not supported yet in 6.x pending proposal update.
Glad to have found this! There's a case where it's failing for me, which is when a method name is quoted (due to being a reserved word). I'm not familiar with Babel internals so I don't know exactly where this occurs but I think it may be here -- looks like it expects property names to always be naked string literals?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.