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.

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