Recreate old decorator metadata behavior (#19089)

* Emulate pre 2.4 metadata behavior of eliding null and undefined from unions without strictNullChecks

* Accept baseline

* Update comment

* Update for second old baseline

* Respect strict
This commit is contained in:
Wesley Wigham 2017-10-12 15:05:04 -07:00 committed by GitHub
parent 98f04e6cfd
commit de0e475c64
7 changed files with 99 additions and 11 deletions

View file

@ -45,6 +45,7 @@ namespace ts {
const resolver = context.getEmitResolver();
const compilerOptions = context.getCompilerOptions();
const strictNullChecks = typeof compilerOptions.strictNullChecks === "undefined" ? compilerOptions.strict : compilerOptions.strictNullChecks;
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
@ -1869,7 +1870,16 @@ namespace ts {
// Note when updating logic here also update getEntityNameForDecoratorMetadata
// so that aliases can be marked as referenced
let serializedUnion: SerializedTypeNode;
for (const typeNode of node.types) {
for (let typeNode of node.types) {
while (typeNode.kind === SyntaxKind.ParenthesizedType) {
typeNode = (typeNode as ParenthesizedTypeNode).type; // Skip parens if need be
}
if (typeNode.kind === SyntaxKind.NeverKeyword) {
continue; // Always elide `never` from the union/intersection if possible
}
if (!strictNullChecks && (typeNode.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) {
continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks
}
const serializedIndividual = serializeTypeNode(typeNode);
if (isIdentifier(serializedIndividual) && serializedIndividual.escapedText === "Object") {
@ -1893,7 +1903,7 @@ namespace ts {
}
// If we were able to find common type, use it
return serializedUnion;
return serializedUnion || createVoidZero(); // Fallback is only hit if all union constituients are null/undefined/never
}
/**

View file

@ -0,0 +1,32 @@
//// [decoratorMetadataNoStrictNull.ts]
const dec = (obj: {}, prop: string) => undefined
class Foo {
@dec public foo: string | null;
@dec public bar: string;
}
//// [decoratorMetadataNoStrictNull.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var dec = function (obj, prop) { return undefined; };
var Foo = /** @class */ (function () {
function Foo() {
}
__decorate([
dec,
__metadata("design:type", String)
], Foo.prototype, "foo");
__decorate([
dec,
__metadata("design:type", String)
], Foo.prototype, "bar");
return Foo;
}());

View file

@ -0,0 +1,18 @@
=== tests/cases/compiler/decoratorMetadataNoStrictNull.ts ===
const dec = (obj: {}, prop: string) => undefined
>dec : Symbol(dec, Decl(decoratorMetadataNoStrictNull.ts, 0, 5))
>obj : Symbol(obj, Decl(decoratorMetadataNoStrictNull.ts, 0, 13))
>prop : Symbol(prop, Decl(decoratorMetadataNoStrictNull.ts, 0, 21))
>undefined : Symbol(undefined)
class Foo {
>Foo : Symbol(Foo, Decl(decoratorMetadataNoStrictNull.ts, 0, 48))
@dec public foo: string | null;
>dec : Symbol(dec, Decl(decoratorMetadataNoStrictNull.ts, 0, 5))
>foo : Symbol(Foo.foo, Decl(decoratorMetadataNoStrictNull.ts, 2, 11))
@dec public bar: string;
>dec : Symbol(dec, Decl(decoratorMetadataNoStrictNull.ts, 0, 5))
>bar : Symbol(Foo.bar, Decl(decoratorMetadataNoStrictNull.ts, 3, 33))
}

View file

@ -0,0 +1,20 @@
=== tests/cases/compiler/decoratorMetadataNoStrictNull.ts ===
const dec = (obj: {}, prop: string) => undefined
>dec : (obj: {}, prop: string) => any
>(obj: {}, prop: string) => undefined : (obj: {}, prop: string) => any
>obj : {}
>prop : string
>undefined : undefined
class Foo {
>Foo : Foo
@dec public foo: string | null;
>dec : (obj: {}, prop: string) => any
>foo : string
>null : null
@dec public bar: string;
>dec : (obj: {}, prop: string) => any
>bar : string
}

View file

@ -43,7 +43,7 @@ var ClassA = /** @class */ (function () {
}
__decorate([
annotation(),
__metadata("design:type", Object)
__metadata("design:type", auxiliry_1.SomeClass)
], ClassA.prototype, "array", void 0);
return ClassA;
}());

View file

@ -63,15 +63,15 @@ var B = /** @class */ (function () {
}
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", String)
], B.prototype, "x");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", Boolean)
], B.prototype, "y");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", String)
], B.prototype, "z");
__decorate([
PropDeco,
@ -87,11 +87,11 @@ var B = /** @class */ (function () {
], B.prototype, "c");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", void 0)
], B.prototype, "d");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", typeof Symbol === "function" ? Symbol : Object)
], B.prototype, "e");
__decorate([
PropDeco,
@ -99,15 +99,15 @@ var B = /** @class */ (function () {
], B.prototype, "f");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", A)
], B.prototype, "g");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", B)
], B.prototype, "h");
__decorate([
PropDeco,
__metadata("design:type", Object)
__metadata("design:type", typeof Symbol === "function" ? Symbol : Object)
], B.prototype, "j");
return B;
}());

View file

@ -0,0 +1,8 @@
// @experimentalDecorators: true
// @emitDecoratorMetadata: true
const dec = (obj: {}, prop: string) => undefined
class Foo {
@dec public foo: string | null;
@dec public bar: string;
}