andreypopp / autobind-decorator

Decorator to automatically bind methods to class instances
MIT License
1.45k stars 66 forks source link

Property descriptor is undefined into boundMethod method(used inheritance) #64

Closed DDzia closed 5 years ago

DDzia commented 6 years ago

image image image

IIIristraM commented 6 years ago

Is any progress in this issue ?

stevemao commented 6 years ago

Can you provide the steps of how to replicate this? Actually, if you could submit a PR with failing unit test it would make me understand the problem a lot faster...

IIIristraM commented 6 years ago

I use TypeScript v2.8.4

The problem appears in the following example

class A {
     @autobind
     protected static method() {}
}

class B extends A {
    @autobind
    protected static method() {}
}

typescript has __decorate (tslib.es6.js) helper with the following code

function __decorate(decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
}

when __decorate applied to B.method the result of Object.getOwnPropertyDescriptor(target, key) is undefined which leads to an error in

function boundMethod(target, key, descriptor) {
  var fn = descriptor.value;

where descriptor is undefined

As far as I understand, it happens because of lazy initialization of autobind. If I set breakpoint at the beginning of __decorate and invoke target[key] in browser's console, Object.getOwnPropertyDescriptor(target, key) returns descriptor as expected

stevemao commented 5 years ago

Any updates on this? Please send a failing unit test to illustrate the problem.

bennypowers commented 5 years ago

I have this with

.babelrc

{
  "presets": [ "@babel/preset-env" ],
  "plugins": [
    "@babel/plugin-syntax-dynamic-import",
    "@babel/proposal-class-properties",
    ["@babel/plugin-proposal-decorators", {
      "decoratorsBeforeExport": true
    }]
  ]
}

app.js

import { boundMethod } from 'autobind-decorator';
class LibraryShell extends LitElement {
  @boundMethod
  onRoute(route, params, query) {
    console.log(route, params, query);
    this.route = route;
    this.params = params;
    this.importPage(route);
  }
}
stevemao commented 5 years ago

@bennypowers did you follow https://github.com/andreypopp/autobind-decorator#modern?