Skip to content

Avoiding duck type checking #61

@Download

Description

@Download

I created this issue because I feel that the discussion in class decorator optional opts #23 has become too broad to progress further. This is intended as a much narrower problem definition. I'm hoping we can use this issue to explore solutions so we can ultimately create a very concrete proposal.

Problem

There are members in the community that want to enable their decorators to be used with and without braces alike: @deco should have the same effect as @deco(). I'll call these 'universal decorators'.
Currently, to achieve this, we need to inspect the arguments passed to the decorator and infer from those whether the function is being called as a decorator (by the runtime), or directly from client code. For this we depend on checking e.g. argument.length, typeof <argument>, etc. This creates hard to read, fragile and error-prone code.

Constraints

The discussion in #23 explores many options, but for this issue I will set up some constraints to limit options:

  • Fully backwards compatible. No code changes needed.
  • It should be possible to determine beyond doubt whether we are being called as decorator or not

Options

I'll kick off with two options, both maybe far from ideal, but satisfying above conditions:

Augment the arguments object

The runtime sets some flag on the arguments object it passes to the decorator, so inside the decorator we can check this flag:

function deco() {
  if (arguments.decoratorInvocation) {
    // called as decorator by runtime
  }
  else {
    // called as decorator factory by client code
  } 
}
Temporarily augment the decoration target

The runtime sets a non-enumerable flag on the decoration target before invoking the decorator and removes it again once the decorator has run. Inside the decorator we can simply check this flag:

function deco(target) {
  if (target && target.__es_decorator_invocation__) {
    // called as decorator by runtime
  }
  else {
    // called as decorator factory by client code
  } 
}

Feedback on these options, and of course other options, very welcome!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions