Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Decorating JavaScript - source{d} edition

Decorating JavaScript - source{d} edition

An introduction to Class and property decorators, Stage 2, proposal.

Avatar for Sergio Arbeo

Sergio Arbeo

June 24, 2017
Tweet

More Decks by Sergio Arbeo

Other Decks in Programming

Transcript

  1. History • Early work from March, 2015 • Stage 2

    for 11 months • PR for babylon merged 2 days ago.
  2. What is a decorator? import Evented from 'evented'; import {

    mixins, readOnly } from 'decorators'; @mixins(Evented) class AbbaSong { @readOnly artist = 'ABBA'; } export default AbbaSong;
  3. What is a decorator? import Evented from 'evented'; import {

    mixins, readOnly } from 'decorators'; @mixins(Evented) class AbbaSong { @readOnly artist = 'ABBA'; } export default AbbaSong;
  4. What is a decorator? import Evented from 'evented'; import {

    mixins, readOnly } from 'decorators'; @mixins(Evented) class AbbaSong { @readOnly artist = 'ABBA'; } export default AbbaSong;
  5. Syntax Valid @foo @foo(…args) @foo.bar @foo.bar(…args) @foo.bar.baz @foo.bar.baz(…args) Invalid @foo[bar]

    @foo[bar](…args) @foo(…args).bar @foo(…args).bar(…args) @foo.bar(…args).baz @foo.bar(…args).baz(…args)
  6. Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:

    boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
  7. Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:

    boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
  8. Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:

    boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
  9. Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:

    boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
  10. Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:

    boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
  11. Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:

    boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
  12. Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:

    boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
  13. Member Descriptor interface MemberDescriptor { kind: "Property”, key: string, isStatic:

    boolean, descriptor: PropertyDescriptor, extras?: MemberDescriptor[], finisher?: (klass): void; }
  14. Simple validator function validator(predicate) { return function(memberDescriptor) { let {

    descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
  15. Simple validator function validator(predicate) { return function(memberDescriptor) { let {

    descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
  16. Simple validator function validator(predicate) { return function(memberDescriptor) { let {

    descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
  17. Simple validator function validator(predicate) { return function(memberDescriptor) { let {

    descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
  18. Simple validator function validator(predicate) { return function(memberDescriptor) { let {

    descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
  19. Simple validator function validator(predicate) { return function(memberDescriptor) { let {

    descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
  20. Simple validator function validator(predicate) { return function(memberDescriptor) { let {

    descriptor } = memberDescriptor; if ('writable' in descriptor) { decorateData(descriptor, predicate); } else { decorateAccessor(descriptor, predicate); } return memberDescriptor; }; };
  21. Simple validator function decorateData(descriptor, predicate) { let { value }

    = descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
  22. Simple validator function decorateData(descriptor, predicate) { let { value }

    = descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
  23. Simple validator function decorateData(descriptor, predicate) { let { value }

    = descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
  24. Simple validator function decorateData(descriptor, predicate) { let { value }

    = descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
  25. Simple validator function decorateData(descriptor, predicate) { let { value }

    = descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
  26. Simple validator function decorateData(descriptor, predicate) { let { value }

    = descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
  27. Simple validator function decorateData(descriptor, predicate) { let { value }

    = descriptor; descriptor.get = () => value; descriptor.set = (newValue) => { if (predicate(newValue)) { value = newValue; } }; delete descriptor.writable; delete descriptor.value; }
  28. Simple validator function decorateAccessor(descriptor, predicate) { let { set }

    = descriptor; descriptor.set = (newValue) => { if (predicate(newValue)) { set(newValue); } }; }
  29. Simple validator function decorateAccessor(descriptor, predicate) { let { set }

    = descriptor; descriptor.set = (newValue) => { if (predicate(newValue)) { set(newValue); } }; }
  30. Simple validator function decorateAccessor(descriptor, predicate) { let { set }

    = descriptor; descriptor.set = (newValue) => { if (predicate(newValue)) { set(newValue); } }; }
  31. Simple validator function decorateAccessor(descriptor, predicate) { let { set }

    = descriptor; descriptor.set = (newValue) => { if (predicate(newValue)) { set(newValue); } }; }
  32. Simple validator function decorateAccessor(descriptor, predicate) { let { set }

    = descriptor; descriptor.set = (newValue) => { if (predicate(newValue)) { set(newValue); } }; }
  33. Simple validator const isString = validator( value => typeof value

    === 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; }
  34. Simple validator const isString = validator( value => typeof value

    === 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; }
  35. Simple validator const isString = validator( value => typeof value

    === 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; } Evaluation
  36. Simple validator const isString = validator( value => typeof value

    === 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; } Evaluation
  37. Simple validator const isString = validator( value => typeof value

    === 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; } Execution
  38. Simple validator const isString = validator( value => typeof value

    === 'string’ ); class MyClass { @isString @validator(x => x !== '1234') password = ""; } Execution
  39. setters / getters class MyClass { @duplicate get hola() {

    return 'hola'; } @map( x => x.toLowerCase() ) set hola(x) { send(x); } }
  40. setters / getters class MyClass { @duplicateGetter @mapSetter( x =>

    x.toLowerCase() ) get hola() { return 'hola'; } set hola(x) { send(x); } }
  41. setters / getters class MyClass { get hola() { return

    'hola'; } @duplicateGetter @mapSetter( x => x.toLowerCase() ) set hola(x) { send(x); } }
  42. Classics • Read Only properties • Validations • Computed Properties

    • Memoized methods • Autobinding • Better Singleton Classes • Conversion setters and getters • Deprecate methods • Debounce • Throttle • Map returned value
  43. Different express API @express('/posts') class Posts { @get index(req, res)

    { } @authorized @post create(req, res) { } @get(':id') show(req, res) { } }
  44. @I18ned class Operations { @i18nMethod('operations.sum') static sum(...args) { return args.reduce((a,

    b) => a+b, 0); } } Operations.sum(1, 2) // 3 Operations.suma(2, 3) // 5 Operations.batuketa(2, 3) // 5 I18ned API