Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
59162fd
Support for auto-accessor fields
rbuckton Jun 28, 2022
34da680
Add tests, ensure accessors are initialized in ctor
rbuckton Aug 9, 2022
02405ec
classFields cleanup and PR feedback
rbuckton Sep 1, 2022
9d1176a
Support for auto-accessor fields
rbuckton Jun 28, 2022
b853cb7
Add tests, ensure accessors are initialized in ctor
rbuckton Aug 9, 2022
96c9393
Thread 'experimentalDecorators' through some utility functions
rbuckton Aug 24, 2022
fdfb49c
Split out decorators types from the default lib
rbuckton Aug 25, 2022
beb8e0a
Allow 'export default' before decorators
rbuckton Aug 26, 2022
f5c6935
Clean up ts class transformation
rbuckton Aug 31, 2022
50c7e00
WIP Stage 3 Decorators
rbuckton Sep 17, 2022
86e0cd2
Evaluation tests and bug fixes
rbuckton Sep 19, 2022
e87b89c
Merge branch 'main' into decorators-stage-3
rbuckton Sep 20, 2022
8c33a18
Set script target for esDecorator evaluator tests to ES2021
rbuckton Sep 20, 2022
3da06f6
Merge branch 'main' into decorators-stage-3
rbuckton Sep 20, 2022
63df46d
Support static private elements with class decorators
rbuckton Sep 28, 2022
ba66494
Merge branch 'main' into decorators-stage-3
rbuckton Sep 28, 2022
5797ac7
Accept baselines after merge
rbuckton Sep 28, 2022
712b037
Contextual types for decorators
rbuckton Sep 30, 2022
8f3ee6a
Improve comment preservation
rbuckton Oct 10, 2022
24b18d7
SourceMap validation
rbuckton Oct 14, 2022
b289642
Remove excess temp in computed name, fix collision in generated names
rbuckton Oct 15, 2022
32c4ed6
Merge branch 'main' into decorators-stage-3
rbuckton Oct 17, 2022
caea4b0
Fix for ClassGetter/SetterDecoratorFunction target types
rbuckton Oct 20, 2022
8abe852
decorator typing updates, minor fixes, remove --annotateTransforms
rbuckton Oct 25, 2022
d330199
getDecoratorCallSignature clean up, make ES and legacy decorators han…
rbuckton Oct 26, 2022
49dbc72
Address additional PR feedback
rbuckton Oct 27, 2022
2142a10
Remove extranous loop in transformClassLike
rbuckton Oct 30, 2022
b5a2ad6
Additional PR feedback, cleanup and fixes
rbuckton Oct 31, 2022
c837d78
revert change to isParameterPropertyDeclaration
rbuckton Nov 1, 2022
c954517
Cleanup of lib.decorators types, added documentation
rbuckton Nov 4, 2022
aece08d
Merge branch 'main' into decorators-stage-3
rbuckton Nov 5, 2022
d65c50b
Fix for missing initializer, some decorators.d.ts type cleanup
rbuckton Nov 7, 2022
aaa2966
Merge branch 'main' into decorators-stage-3
rbuckton Nov 8, 2022
c2b35ff
Merge branch 'main' into decorators-stage-3
rbuckton Nov 8, 2022
995e961
Improve importHelper warnings for missing helpers
rbuckton Nov 8, 2022
0d9504e
Handle named evaluation in parameters, fix test failures
rbuckton Nov 9, 2022
c83e46d
Remove src/lib/decorators.parameters.d.ts
rbuckton Nov 9, 2022
f4294f3
Remove *DecoratorFunctionTypes
rbuckton Nov 9, 2022
1fbaa5c
Fix inconsistent indentation due to merge
rbuckton Nov 15, 2022
09a6a36
Merge branch 'main' into decorators-stage-3
rbuckton Nov 16, 2022
923ce71
Merge branch 'main' into decorators-stage-3
rbuckton Nov 28, 2022
4841c5f
Add cache for decorator context override type
rbuckton Dec 14, 2022
1717240
Merge branch 'main' into decorators-stage-3
rbuckton Dec 14, 2022
1746823
Update syntactic diagnostics for JS files
rbuckton Dec 16, 2022
82d822a
Merge branch 'main' into decorators-stage-3
rbuckton Dec 16, 2022
50ac2b8
Remove 'Experimental decorators' warning from diagnosticMessages.json
rbuckton Dec 16, 2022
50ae4df
Remove 'experimentalDecorators' quick fix
rbuckton Jan 5, 2023
31dfda9
Merge branch 'main' into decorators-stage-3
rbuckton Jan 5, 2023
b8885ae
Merge branch 'main' into decorators-stage-3
rbuckton Jan 9, 2023
ae3885a
Simplify decorators+modifiers merge
rbuckton Jan 10, 2023
fb0b9ee
Remove stub variables for potential type mutations
rbuckton Jan 10, 2023
6656953
Fix static accessor initialization order
rbuckton Jan 11, 2023
882e686
Merge branch 'main' into decorators-stage-3
rbuckton Jan 11, 2023
3cc86d9
Accept baselines
rbuckton Jan 11, 2023
57ef107
Fix class decorator+static auto-accessor transformation
rbuckton Jan 11, 2023
844c303
Add additional contextual typing test
rbuckton Jan 11, 2023
0d41f51
Amend decorator evaluation order
rbuckton Jan 11, 2023
e52ee01
Test evaluation order against multiple targets
rbuckton Jan 11, 2023
b476408
Add evaluation tests for decorator examples, fix parameter-property emit
rbuckton Jan 12, 2023
b9050d3
Merge branch 'main' into decorators-stage-3
rbuckton Jan 12, 2023
1e51d59
Fix lint after merge
rbuckton Jan 13, 2023
2c08e15
fix 'this' references in decorator expressions
rbuckton Jan 13, 2023
3def45f
Merge branch 'main' into decorators-stage-3
rbuckton Jan 13, 2023
298bce5
Accept baseline after merge
rbuckton Jan 13, 2023
b0020f6
Fix incorrectly renamed test
rbuckton Jan 13, 2023
02e93fd
Merge branch 'main' into decorators-stage-3
rbuckton Jan 18, 2023
673073c
Temporarily disable 'context.access'
rbuckton Jan 18, 2023
f0947fc
Merge branch 'main' into decorators-stage-3
rbuckton Jan 19, 2023
09855dc
Documentation comment updates
rbuckton Jan 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Prev Previous commit
Next Next commit
Split out decorators types from the default lib
  • Loading branch information
rbuckton committed Sep 2, 2022
commit fdfb49c9652af520095c4bcde4a910d25a601700
5 changes: 4 additions & 1 deletion src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ namespace ts {
["esnext.bigint", "lib.es2020.bigint.d.ts"],
["esnext.string", "lib.es2022.string.d.ts"],
["esnext.promise", "lib.es2021.promise.d.ts"],
["esnext.weakref", "lib.es2021.weakref.d.ts"]
["esnext.weakref", "lib.es2021.weakref.d.ts"],
["decorators", "lib.decorators.d.ts"],
["decorators.legacy", "lib.decorators.legacy.d.ts"],
["decorators.parameters", "lib.decorators.parameters.d.ts"],
];

/**
Expand Down
12 changes: 12 additions & 0 deletions src/harness/fourslashInterfaceImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1164,6 +1164,18 @@ namespace FourSlashInterface {
typeEntry("PropertyDecorator"),
typeEntry("MethodDecorator"),
typeEntry("ParameterDecorator"),
interfaceEntry("ClassDecoratorContext"),
typeEntry("ClassDecoratorFunction"),
interfaceEntry("ClassMethodDecoratorContext"),
typeEntry("ClassMethodDecoratorFunction"),
interfaceEntry("ClassGetterDecoratorContext"),
typeEntry("ClassGetterDecoratorFunction"),
interfaceEntry("ClassSetterDecoratorContext"),
typeEntry("ClassSetterDecoratorFunction"),
interfaceEntry("ClassAccessorDecoratorContext"),
typeEntry("ClassAccessorDecoratorFunction"),
interfaceEntry("ClassFieldDecoratorContext"),
typeEntry("ClassFieldDecoratorFunction"),
typeEntry("PromiseConstructorLike"),
interfaceEntry("PromiseLike"),
interfaceEntry("Promise"),
Expand Down
247 changes: 247 additions & 0 deletions src/lib/decorators.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
/**
* Context provided to a class decorator.
*/
interface ClassDecoratorContext<Class extends abstract new (...args: any[]) => any> {
readonly kind: "class";
readonly name: string | undefined;

/**
* Adds a callback to be invoked after the class definition has been finalized.
*
* @example
* ```ts
* function customElement(name: string): ClassDecoratorFunction {
* return (target, { addInitializer }) => {
* addInitializer(function () {
* customElements.define(name, this);
* });
* }
* }
*
* @customElement("my-element")
* class MyElement {}
* ```
*/
addInitializer(initializer: (this: Class) => void): void;
}

/**
* Describes a function that can be used to decorate a class.
*/
type ClassDecoratorFunction = <
In extends abstract new (...args: any[]) => any,
Out extends abstract new (...args: any[]) => any = In,
Class extends abstract new (...args: any[]) => any = Out
>(target: In, context: ClassDecoratorContext<Class>) => Out | void;

/**
* Context provided to a class method decorator.
*/
interface ClassMethodDecoratorContext<This, Value extends (this: This, ...args: any[]) => any> {
readonly kind: "method";
readonly name: string | symbol;
readonly static: boolean;
readonly private: boolean;
readonly access: {
/**
* Gets the current value of the method from the provided receiver.
*
* @example
* let fn = context.access.get.call(instance);
*/
get(this: This): Value;
};

/**
* Adds a callback to be invoked either before static initializers are run (when
* decorating a `static` member), or before instance initializers are run (when
* decorating a non-`static` member).
*
* @example
* ```ts
* const bound: ClassMethodDecoratorFunction = (value, { name, private: isPrivate, addInitializer }) {
* if (isPrivate) throw new TypeError("Not supported on private methods.");
* addInitializer(function () {
* this[name] = this[name].bind(this);
* });
* }
*
* class C {
* message = "Hello";
*
* @bound
* m() {
* console.log(this.message);
* }
* }
* ```
*/
addInitializer(initializer: (this: This) => void): void;
}

/**
* Describes a function that can be used to decorate a class method.
*/
type ClassMethodDecoratorFunction<Traits extends { name?: string | symbol, static?: boolean, private?: boolean } = {}> = <
This,
In extends (this: This, ...args: any[]) => any,
Out extends (this: This, ...args: any[]) => any = In,
Value extends (this: This, ...args: any[]) => any = Out
>(target: In, context: ClassMethodDecoratorContext<This, Value> & Readonly<Pick<Traits, "name" | "static" | "private">>) => Out | void;

/**
* Context provided to a class `get` method decorator.
*/
interface ClassGetterDecoratorContext<This, Value> {
readonly kind: "getter";
readonly name: string | symbol;
readonly static: boolean;
readonly private: boolean;
readonly access: {
/**
* Invokes the getter on the provided receiver.
*
* @example
* let value = context.access.get.call(instance);
*/
get(this: This): Value;
};

/**
* Adds a callback to be invoked either before static initializers are run (when
* decorating a `static` member), or before instance initializers are run (when
* decorating a non-`static` member).
*/
addInitializer(initializer: (this: This) => void): void;
}

/**
* Describes a function that can be used to decorate a class `get` method.
*/
type ClassGetterDecoratorFunction = <
This,
In,
Out = In,
Value = Out,
>(target: { get(this: This): In }, context: ClassGetterDecoratorContext<This, Value>) => { get(this: This): Out; } | void;

/**
* Context provided to a class `set` method decorator.
*/
interface ClassSetterDecoratorContext<This, Value> {
readonly kind: "setter";
readonly name: string | symbol;
readonly static: boolean;
readonly private: boolean;
readonly access: {
/**
* Invokes the setter on the provided receiver.
*
* @example
* context.access.set.call(instance, value);
*/
set(this: This, value: Value): void;
};

/**
* Adds a callback to be invoked either before static initializers are run (when
* decorating a `static` member), or before instance initializers are run (when
* decorating a non-`static` member).
*/
addInitializer(initializer: (this: This) => void): void;
}

/**
* Describes a function that can be used to decorate a class `set` method.
*/
type ClassSetterDecoratorFunction = <
This,
In,
Out = In,
Value = Out
>(target: { set(this: This, value: In): void; }, context: ClassSetterDecoratorContext<This, Value>) => { set(this: This, value: Out): void; } | void;

/**
* Context provided to a class `accessor` field decorator.
*/
interface ClassAccessorDecoratorContext<This, Value> {
readonly kind: "accessor";
readonly name: string | symbol;
readonly static: boolean;
readonly private: boolean;
readonly access: {
/**
* Invokes the getter on the provided receiver.
*
* @example
* let value = context.access.get.call(instance);
*/
get(this: This): Value;

/**
* Invokes the setter on the provided receiver.
*
* @example
* context.access.set.call(instance, value);
*/
set(this: This, value: Value): void;
};

/**
* Adds a callback to be invoked either before static initializers are run (when
* decorating a `static` member), or before instance initializers are run (when
* decorating a non-`static` member).
*/
addInitializer(initializer: (this: This) => void): void;
}

/**
* Describes a function that can be used to decorate a class `accessor` field.
*/
type ClassAccessorDecoratorFunction = <
This,
In,
Out = In,
Value = Out
>(
target: { get(this: This): In; set(this: This, value: In): void; },
context: ClassAccessorDecoratorContext<This, Value>
) => { get?(this: This): Out; set?(this: This, value: Out): void; init?(this: This, value: In): Out; } | void;

/**
* Context provided to a class field decorator.
*/
interface ClassFieldDecoratorContext<This, Value> {
readonly kind: "field";
readonly name: string | symbol;
readonly static: boolean;
readonly private: boolean;
readonly access: {
/**
* Gets the value of the field on the provided receiver.
*/
get(this: This): Value;

/**
* Sets the value of the field on the provided receiver.
*/
set(this: This, value: Value): void;
};

/**
* Adds a callback to be invoked either before static initializers are run (when
* decorating a `static` member), or before instance initializers are run (when
* decorating a non-`static` member).
*/
addInitializer(initializer: (this: This) => void): void;
}

/**
* Describes a function that can be used to decorate a class field.
*/
type ClassFieldDecoratorFunction = <
This,
In,
Out = In,
Value = Out
>(target: undefined, context: ClassAccessorDecoratorContext<This, Value>) => ((this: This, initialValue: In) => Out) | void;
4 changes: 4 additions & 0 deletions src/lib/decorators.legacy.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
14 changes: 14 additions & 0 deletions src/lib/decorators.parameters.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
interface ParameterDecoratorContext<Func extends Function> {
readonly kind: "parameter";
readonly index: number;
readonly name: string | undefined;
readonly rest: boolean;
addInitializer(initializer: (this: Func) => void): void;
}

type ParameterDecoratorFunction = <
Func extends Function,
This,
In,
Out = In
>(target: undefined, context: ParameterDecoratorContext<Func>) => ((this: This, initialValue: In) => Out) | void;
8 changes: 3 additions & 5 deletions src/lib/es5.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
/// <reference lib="decorators" />
/// <reference lib="decorators.legacy" />

/////////////////////////////
/// ECMAScript APIs
/////////////////////////////
Expand Down Expand Up @@ -1478,11 +1481,6 @@ interface TypedPropertyDescriptor<T> {
set?: (value: T) => void;
}

declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;

declare type PromiseConstructorLike = new <T>(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) => PromiseLike<T>;

interface PromiseLike<T> {
Expand Down
3 changes: 3 additions & 0 deletions src/lib/libs.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@
"es2022.sharedmemory",
"es2022.string",
"esnext.intl",
"decorators",
"decorators.legacy",
"decorators.parameters",
// Default libraries
"es5.full",
"es2015.full",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ tests/cases/compiler/weird.js(9,17): error TS7006: Parameter 'error' implicitly
someFunction(function(BaseClass) {
~~~~~~~~~~~~
!!! error TS2552: Cannot find name 'someFunction'. Did you mean 'Function'?
!!! related TS2728 /.ts/lib.es5.d.ts:318:13: 'Function' is declared here.
!!! related TS2728 /.ts/lib.es5.d.ts:321:13: 'Function' is declared here.
~~~~~~~~~
!!! error TS7006: Parameter 'BaseClass' implicitly has an 'any' type.
'use strict';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
=== tests/cases/conformance/es6/moduleExportsAmd/a.ts ===
var decorator: ClassDecorator;
>decorator : Symbol(decorator, Decl(a.ts, 0, 3))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.es5.d.ts, --, --))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.decorators.legacy.d.ts, --, --))

@decorator
>decorator : Symbol(decorator, Decl(a.ts, 0, 3))
Expand All @@ -12,7 +12,7 @@ export default class Foo {}
=== tests/cases/conformance/es6/moduleExportsAmd/b.ts ===
var decorator: ClassDecorator;
>decorator : Symbol(decorator, Decl(b.ts, 0, 3))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.es5.d.ts, --, --))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.decorators.legacy.d.ts, --, --))

@decorator
>decorator : Symbol(decorator, Decl(b.ts, 0, 3))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
=== tests/cases/conformance/es6/moduleExportsCommonjs/a.ts ===
var decorator: ClassDecorator;
>decorator : Symbol(decorator, Decl(a.ts, 0, 3))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.es5.d.ts, --, --))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.decorators.legacy.d.ts, --, --))

@decorator
>decorator : Symbol(decorator, Decl(a.ts, 0, 3))
Expand All @@ -12,7 +12,7 @@ export default class Foo {}
=== tests/cases/conformance/es6/moduleExportsCommonjs/b.ts ===
var decorator: ClassDecorator;
>decorator : Symbol(decorator, Decl(b.ts, 0, 3))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.es5.d.ts, --, --))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.decorators.legacy.d.ts, --, --))

@decorator
>decorator : Symbol(decorator, Decl(b.ts, 0, 3))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
=== tests/cases/conformance/es6/moduleExportsSystem/a.ts ===
var decorator: ClassDecorator;
>decorator : Symbol(decorator, Decl(a.ts, 0, 3))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.es5.d.ts, --, --))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.decorators.legacy.d.ts, --, --))

@decorator
>decorator : Symbol(decorator, Decl(a.ts, 0, 3))
Expand All @@ -12,7 +12,7 @@ export default class Foo {}
=== tests/cases/conformance/es6/moduleExportsSystem/b.ts ===
var decorator: ClassDecorator;
>decorator : Symbol(decorator, Decl(b.ts, 0, 3))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.es5.d.ts, --, --))
>ClassDecorator : Symbol(ClassDecorator, Decl(lib.decorators.legacy.d.ts, --, --))

@decorator
>decorator : Symbol(decorator, Decl(b.ts, 0, 3))
Expand Down
Loading