Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decorators Testing Plan #4042

Open
pzuraq opened this issue Apr 3, 2024 · 0 comments
Open

Decorators Testing Plan #4042

pzuraq opened this issue Apr 3, 2024 · 0 comments

Comments

@pzuraq
Copy link

pzuraq commented Apr 3, 2024

Proposal Readme
Proposal Spec Text

Tests

  • Fields

    • Context kind is "field"
    • Received value is undefined
    • Decorator can return an initializer function that receives the initial value and can return a new value, or undefined. Any other type of return value besides throws an error
    • Initializer functions for fields with multiple decorators are run in the reverse order of decorator evaluation (e.g. lexical order), and each initializer receives the return value of the previous initializer as its input
    • Decorated field initializers are interleaved lexically with non-decorated field initializers
    • Instance
      • The this value of the initializer function is the instance of the class that is being initialized
      • Initializers is called at the same time as when the class field would be assigned if not decorated (e.g. right after super(), in lexical order)
    • Static
      • The this value of the initializer function is the class definition itself
      • Initializers are called at the same time as when the class field would be assigned if not decorated (e.g. ordering is the same relative to static class blocks, computed name evaluation, etc.)
  • Methods

    • Context kind is "method"
    • Received value is the class method function, or the function returned by the previous decorator applied to the method (if any)
    • Decorator can return a function or undefined. Any other type of return value throws an error
    • The returned function is assigned in the same location as a non-decorated version would have been (e.g. on the class prototype for instance methods, on the class itself for static methods)
    • If the decorator returns undefined, it assigns the original method OR the output of the most recent decorator which returned a function
  • Getters/Setters

    • Context kind is "getter" or "setter"
    • Received value is the class getter/setter function, or the function returned by the previous decorator applied to the method (if any)
    • Decorator can return a function or undefined. Any other type of return value throws an error
    • The returned function is assigned in the same location as a non-decorated version would have been (e.g. on the class prototype for instance getters/setters, on the class itself for static getters/setters)
    • If the decorator returns undefined, it assigns the original getter/setter OR the output of the most recent decorator which returned a function
  • Auto-Accessors

    • Behavior
      • accessor keyword can be used to create an "empty" getter/setter pair on the class. The getter and setter read from and set to a private slot, with no additional observable behavior.
      • accessor can be combined with private fields, static, and computed property names, and works with all permutations of them
      • accessor can be given an initializer that provides a default value
      • Initializers run at the same time as class fields, and are interleaved lexically with class field initializers
    • Decoration
      • Context kind is "accessor"
      • Received value is an object with get and set properties which are the getter and setter of the accessor, or the most recent decoration that returned one.
      • Decorator can return an object containing get, set, and/or init properties. Each of these must be a function, any other type of value will throw an error
      • Decorator can return undefined, in which case previous value is used instead
      • If a previous decorator returns get but not set, get is replaced with the new value, and the previous set is used
      • If a previous decorator returns set but not get, set is replaced with the new value, and the previous get is used
      • init receives the initial value of the auto-accessor (or the returned value from the previous init) and may return a new value
      • init runs at the same time as a non-decorated accessor's initializer
      • init functions for multiple decorators on a single field run in the reverse order of decorator evaluation (e.g. lexical order), and each initializer receives the returned value of the previous initializer
      • The returned getter and setter are assigned in the same location as a non-decorated version would have been (e.g. on the class prototype for instance accessors, on the class itself for static accessors)
      • If the decorator returns undefined, it assigns the original getter/setter OR the output of the most recent decorator which returned a value
  • Classes

    • Context kind is "class"
    • Class decorators receive the class definition, and may return a new construct-able value (e.g. another class, a proxy, a non-arrow function), or undefined
    • Class decorators are applied before static elements are evaluated, static blocks are called, etc.
    • If the returned value cannot be constructed, throw an error
    • Class declarations can be decorated
    • Class expressions can be decorated
    • Bindings to the class itself within the class definition reference the final class definition (e.g. the value returned by the last decorator)
  • Context

    • name
      • Name is correct for standard public elements
      • Name is the same as the name in code for private values (e.g. #foo)
      • Name is correct for computed property names
      • Name is correct for classes
    • access
      • Access includes get and set functions
      • get and set functions must be called with this value to work properly
      • Access works for public elements
      • Access works for private elements
      • get and set access the method itself for methods/getters/setters (e.g. the slot that contains the method, public or private). This allows a decorator to get the final version of the method, for instance.
      • set does NOT work for private class methods/getters/setters
      • Not defined for classes
    • private
      • true for private elements
      • false for public elements
      • Not defined for classes
    • static
      • true for static elements
      • false for non-static elements
      • Not defined for classes
    • addInitializer
      • Can receive a function as its first argument, throws an error if it receives any other type of value
      • Methods/Getters/Setters: Extra initializers run immediately before class fields/accessors are assigned
      • Fields/Accessors: Extra initializers run after the standard initializers are run and initial value is assigned
      • Classes: Extra initializers run after class definition has completed, after static fields and elements have been assigned, just before the next statement or expression after the definition is run.
      • Initializers run in the same order as decorator application (e.g. reverse lexical per element, lexical across all elements)
      • addInitializer throws an error if called after decoration has finished (including if decoration was interrupted by an error)
  • General

    • Syntax
      • Application
        • Decorators can be single identifiers (e.g. @foo)
        • Decorators can be single call expressions (e.g. @foo())
        • Decorators can be a chain of property accesses (e.g. @foo.bar.baz)
        • Decorators can be a chain of property accesses with a call expression at the end (e.g. @foo.bar.baz())
        • Decorator property accesses can include private names (e.g. @foo.#bar)
        • Any other expression can be wrapped in parens at the top level, examples:
          • @(foo().bar)
          • @(foo[0])
          • @(super.foo)
          • @(this.foo)
          • @(yield foo)
          • @(await foo)
        • Any other syntax is invalid
      • Placement
        • Can be placed just before a class element
        • Can be placed just before a class declaration or expression
        • Are placed before export and default keywords if they are applied to the class
    • Ordering
      • Decorators are applied to each element/class from inner to outer (reverse lexical)
      • Decorators run in the order: Static non-fields -> Instance non-fields -> Static fields -> Instance fields -> Class
      • Decorator expressions (e.g. the dec() part of @dec()) are run before application, before static block initialization, interleaved and at the same time as computed expression name evaluation
    • Decorators can be applied to all valid types of class elements (except static blocks)
      • private
      • static
      • async
      • generator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant