Git Product home page Git Product logo

dep-member-interceptors's People

Contributors

alan-knight avatar munificent avatar sigmundch avatar zoechi avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

dep-member-interceptors's Issues

More rationale for using annotation syntax

To me, the biggest reason to use annotation syntax for interceptors is that it lets a library encapsulate the usage of interception. My awesome framework may use @foo as a regular annotation in 1.2.3 and then switch to making @foo an interceptor in 1.3.0 without breaking my users or even requiring them to know.

Interceptors and inheritance

Imagine that I have a class with an intercepted field:

class X {
  @interceptor var field;
}

what happens if I extend it and overload intercepted field:

class Y extends X {
  var _field;
  get field => _field;
  set field(value) { _field = value; }
}

as it is specified right now interceptor stops working, it will not intercept access to the field in Y. Should be make interceptors contagious, e.g. they are always pushed down to bottom most overriding implementation? Seems like the best choice to me.

(This would slightly complicate semantics of the super invocation that would have to skip interception to avoid executing interceptor twice).

We can also make it configurable and let interceptor implementor choose.

Similarly what happens if Y implements X?

Should interceptor be part of the interface, e.g. should it be "inherited" as well? This is espeically important for interceptors that are "type like", e.g. @notnull because these type like interceptors are obvious part of the interface and not of the implementation.

Related question, how do I intercept method below:

library xyz;

class PublicInterface {
  factory PublicInterface() => new _PrivateImplementation();

  method();
}

class _PrivateImplementation implements PublicInterface {
  method() { /* ... */ };
}

ordering issues with side annotations

there is a potential ordering issue with how to combine interceptors that are annotated on the side via @ApplyInterceptorTo

Original comment from @mraleph:

If I import the same library twice into two other different libraries and on both imports I apply interceptors to the same member --- then it's not entirely clear how that should "stack".

Of course there is an obvious order induced by the order of import statements - but this order is somewhat hidden from the programmer.

Bikeshed on @SideTag

The name is a bit strange because "tag" isn't used anywhere else. I don't think it's really relevant to this proposal anyway, but how about @ApplyAnnotationTo or just @Annotate?

How to have additional state for an interceptor without falling back to globals

If an interceptor needs more state than the target member (or state of a different type) - it looks like with the current proposal - one needs to fall back using globals (e.g. global Maps) (possibly indexed by target object and/or interceptor arguments). The @memoize interceptor is an example of this (e.g. @memorize fib(a,b) ). Is this correct?

In order to guarantee that the additional state has the same lifetime as the target itself (i.e. the state should be GCed at the same time), it becomes more complicated, since one may need to use weak maps, ...

It would be nice if an interceptor could introduce new state without relying on globals.

Do intercepted fields have backing state?

The proposal says:

and the _$foo field will be final.

But the example doesn't show a field at all. It might be nice if the interceptor can choose whether or not the intercepted field gets backing state or not.

Avoid using @nonnull as example?

I think contract validation is definitely a useful example to show, but I worry that if we use @nonnull as the hypothetic contract that the discussion will rathole on non-nullability. I, of course, care a lot about non-nullability, but it's not relevant to this proposal. :)

How about @nonnegative or something?

Ensure that this doesn't cause code bloat in dart2js

In terms of the actual implementation, we need to make sure that there is some path for dart2js to implement this without an unacceptable amount of code bloat. Specifically, I am concerned about having to create a class which extends Member for each field which is annotated, like this example from the getter section:

class _$nameMember extends Member {
  const _$nameMember() : super(#name);
  get(target) => target._$name;
  set(target, value) { target._$name = value; }
  invoke(target, positional, named) =>
      Function.apply(target._$name, positional, named);
}

I think there are a few ways to get around this, but just want to make sure its highlighted as something which should be watched.

Should this be in "dart:core"?

The Member and Interceptor interfaces would be added to "dart:core".

It definitely needs to be in some "dart:" library, but I wonder if this proposal will be less contentious if it's in a separate "dart:" library. Not "dart:mirrors", of course.

Change ordering of arguments for WriteInterceptor and InvokeInterceptor?

Currently the proposal is the following:

abstract class WriteInterceptor {
  set(target, value, Member member);
}

abstract class InvokeInterceptor {
  invoke(target, List positionalArguments, Map<Symbol,dynamic> namedArguments,
      Member member);
}

I would like to propose that we change member to always be the 2nd argument:

abstract class WriteInterceptor {
  set(target, Member member, value);
}

abstract class InvokeInterceptor {
  invoke(target, Member member, List positionalArguments,
      Map<Symbol,dynamic> namedArguments);
}

This is more intuitive, because it looks more like the calls its actually intercepting. For example when assigning a property:

foo.bar = 'baz';

The set method would be called with foo, a member whose name is #bar, and the value 'baz', in that order. With the current semantics 'baz' would come before the member with name #bar, which isn't as intuitive.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.