Skip to content

Commit 331d26f

Browse files
committed
Merge pull request #4741 from Microsoft/es3Decorators
Allow decorators in ES3
2 parents ff3d0f9 + 8a41cde commit 331d26f

File tree

52 files changed

+647
-826
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+647
-826
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8564,6 +8564,12 @@ namespace ts {
85648564
case SyntaxKind.SetAccessor:
85658565
// A method or accessor declaration decorator will have two or three arguments (see
85668566
// `PropertyDecorator` and `MethodDecorator` in core.d.ts)
8567+
8568+
// If we are emitting decorators for ES3, we will only pass two arguments.
8569+
if (languageVersion === ScriptTarget.ES3) {
8570+
return 2;
8571+
}
8572+
85678573
// If the method decorator signature only accepts a target and a key, we will only
85688574
// type check those arguments.
85698575
return signature.parameters.length >= 3 ? 3 : 2;
@@ -14917,9 +14923,6 @@ namespace ts {
1491714923
if (!nodeCanBeDecorated(node)) {
1491814924
return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_not_valid_here);
1491914925
}
14920-
else if (languageVersion < ScriptTarget.ES5) {
14921-
return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher);
14922-
}
1492314926
else if (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) {
1492414927
let accessors = getAllAccessorDeclarations((<ClassDeclaration>node.parent).members, <AccessorDeclaration>node);
1492514928
if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) {

src/compiler/diagnosticMessages.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -631,10 +631,6 @@
631631
"category": "Error",
632632
"code": 1204
633633
},
634-
"Decorators are only available when targeting ECMAScript 5 and higher.": {
635-
"category": "Error",
636-
"code": 1205
637-
},
638634
"Decorators are not valid here.": {
639635
"category": "Error",
640636
"code": 1206

src/compiler/emitter.ts

Lines changed: 26 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -285,12 +285,10 @@ var __extends = (this && this.__extends) || function (d, b) {
285285
// emit output for the __decorate helper function
286286
const decorateHelper = `
287287
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
288-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
289-
switch (arguments.length) {
290-
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
291-
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
292-
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
293-
}
288+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
289+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
290+
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;
291+
return c > 3 && r && Object.defineProperty(target, key, r), r;
294292
};`;
295293

296294
// emit output for the __metadata helper function
@@ -1652,7 +1650,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
16521650
//
16531651
// The emit for the decorated computed property decorator is:
16541652
//
1655-
// Object.defineProperty(C.prototype, _a, __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a)));
1653+
// __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a));
16561654
//
16571655
if (nodeIsDecorated(node.parent)) {
16581656
if (!computedPropertyNamesToGeneratedNames) {
@@ -4707,7 +4705,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
47074705
//
47084706
// let C = class {
47094707
// };
4710-
// Object.defineProperty(C, "name", { value: "C", configurable: true });
47114708
// C = __decorate([dec], C);
47124709
//
47134710
// * For an exported class declaration:
@@ -4719,7 +4716,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
47194716
//
47204717
// export let C = class {
47214718
// };
4722-
// Object.defineProperty(C, "name", { value: "C", configurable: true });
47234719
// C = __decorate([dec], C);
47244720
//
47254721
// * For a default export of a class declaration with a name:
@@ -4731,7 +4727,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
47314727
//
47324728
// let C = class {
47334729
// }
4734-
// Object.defineProperty(C, "name", { value: "C", configurable: true });
47354730
// C = __decorate([dec], C);
47364731
// export default C;
47374732
//
@@ -5059,21 +5054,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
50595054
//
50605055
// The emit for a method is:
50615056
//
5062-
// Object.defineProperty(C.prototype, "method",
5063-
// __decorate([
5064-
// dec,
5065-
// __param(0, dec2),
5066-
// __metadata("design:type", Function),
5067-
// __metadata("design:paramtypes", [Object]),
5068-
// __metadata("design:returntype", void 0)
5069-
// ], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method")));
5057+
// __decorate([
5058+
// dec,
5059+
// __param(0, dec2),
5060+
// __metadata("design:type", Function),
5061+
// __metadata("design:paramtypes", [Object]),
5062+
// __metadata("design:returntype", void 0)
5063+
// ], C.prototype, "method", undefined);
50705064
//
50715065
// The emit for an accessor is:
50725066
//
5073-
// Object.defineProperty(C.prototype, "accessor",
5074-
// __decorate([
5075-
// dec
5076-
// ], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor")));
5067+
// __decorate([
5068+
// dec
5069+
// ], C.prototype, "accessor", undefined);
50775070
//
50785071
// The emit for a property is:
50795072
//
@@ -5084,18 +5077,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
50845077

50855078
writeLine();
50865079
emitStart(member);
5087-
if (member.kind !== SyntaxKind.PropertyDeclaration) {
5088-
write("Object.defineProperty(");
5089-
emitStart(member.name);
5090-
emitClassMemberPrefix(node, member);
5091-
write(", ");
5092-
emitExpressionForPropertyName(member.name);
5093-
emitEnd(member.name);
5094-
write(",");
5095-
increaseIndent();
5096-
writeLine();
5097-
}
5098-
50995080
write("__decorate([");
51005081
increaseIndent();
51015082
writeLine();
@@ -5119,15 +5100,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
51195100
emitExpressionForPropertyName(member.name);
51205101
emitEnd(member.name);
51215102

5122-
if (member.kind !== SyntaxKind.PropertyDeclaration) {
5123-
write(", Object.getOwnPropertyDescriptor(");
5124-
emitStart(member.name);
5125-
emitClassMemberPrefix(node, member);
5126-
write(", ");
5127-
emitExpressionForPropertyName(member.name);
5128-
emitEnd(member.name);
5129-
write("))");
5130-
decreaseIndent();
5103+
if (languageVersion > ScriptTarget.ES3) {
5104+
if (member.kind !== SyntaxKind.PropertyDeclaration) {
5105+
// We emit `null` here to indicate to `__decorate` that it can invoke `Object.getOwnPropertyDescriptor` directly.
5106+
// We have this extra argument here so that we can inject an explicit property descriptor at a later date.
5107+
write(", null");
5108+
}
5109+
else {
5110+
// We emit `void 0` here to indicate to `__decorate` that it can invoke `Object.defineProperty` directly, but that it
5111+
// should not invoke `Object.getOwnPropertyDescriptor`.
5112+
write(", void 0");
5113+
}
51315114
}
51325115

51335116
write(");");

tests/baselines/reference/classExpressionWithDecorator1.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,10 @@ var v = @decorate class C { static p = 1 };
33

44
//// [classExpressionWithDecorator1.js]
55
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
6-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
7-
switch (arguments.length) {
8-
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
9-
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
10-
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
11-
}
6+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
7+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
8+
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;
9+
return c > 3 && r && Object.defineProperty(target, key, r), r;
1210
};
1311
var v = ;
1412
var C = (function () {

tests/baselines/reference/decoratedClassFromExternalModule.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,10 @@ import Decorated from 'decorated';
1111

1212
//// [decorated.js]
1313
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
14-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
15-
switch (arguments.length) {
16-
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
17-
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
18-
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
19-
}
14+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
15+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
16+
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;
17+
return c > 3 && r && Object.defineProperty(target, key, r), r;
2018
};
2119
function decorate(target) { }
2220
let Decorated = class {

tests/baselines/reference/decoratorChecksFunctionBodies.js

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,10 @@ class A {
1717

1818
//// [decoratorChecksFunctionBodies.js]
1919
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
20-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
21-
switch (arguments.length) {
22-
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
23-
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
24-
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
25-
}
20+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
21+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
22+
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;
23+
return c > 3 && r && Object.defineProperty(target, key, r), r;
2624
};
2725
// from #2971
2826
function func(s) {
@@ -32,13 +30,12 @@ var A = (function () {
3230
}
3331
A.prototype.m = function () {
3432
};
35-
Object.defineProperty(A.prototype, "m",
36-
__decorate([
37-
(function (x, p) {
38-
var a = 3;
39-
func(a);
40-
return x;
41-
})
42-
], A.prototype, "m", Object.getOwnPropertyDescriptor(A.prototype, "m")));
33+
__decorate([
34+
(function (x, p) {
35+
var a = 3;
36+
func(a);
37+
return x;
38+
})
39+
], A.prototype, "m", null);
4340
return A;
4441
})();

tests/baselines/reference/decoratorInstantiateModulesInFunctionBodies.js

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,10 @@ class Wat {
2626
exports.test = 'abc';
2727
//// [b.js]
2828
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
29-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
30-
switch (arguments.length) {
31-
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
32-
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
33-
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
34-
}
29+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
30+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
31+
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;
32+
return c > 3 && r && Object.defineProperty(target, key, r), r;
3533
};
3634
var a_1 = require('./a');
3735
function filter(handler) {
@@ -45,9 +43,8 @@ var Wat = (function () {
4543
Wat.whatever = function () {
4644
// ...
4745
};
48-
Object.defineProperty(Wat, "whatever",
49-
__decorate([
50-
filter(function () { return a_1.test == 'abc'; })
51-
], Wat, "whatever", Object.getOwnPropertyDescriptor(Wat, "whatever")));
46+
__decorate([
47+
filter(function () { return a_1.test == 'abc'; })
48+
], Wat, "whatever", null);
5249
return Wat;
5350
})();

tests/baselines/reference/decoratorMetadata.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
2424
exports.default = Service;
2525
//// [component.js]
2626
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
27-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
28-
switch (arguments.length) {
29-
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
30-
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
31-
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
32-
}
27+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
28+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
29+
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;
30+
return c > 3 && r && Object.defineProperty(target, key, r), r;
3331
};
3432
var __metadata = (this && this.__metadata) || function (k, v) {
3533
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);

tests/baselines/reference/decoratorMetadataForMethodWithNoReturnTypeAnnotation01.js

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,11 @@ var MyClass = (function () {
2020
}
2121
MyClass.prototype.doSomething = function () {
2222
};
23-
Object.defineProperty(MyClass.prototype, "doSomething",
24-
__decorate([
25-
decorator,
26-
__metadata('design:type', Function),
27-
__metadata('design:paramtypes', []),
28-
__metadata('design:returntype', void 0)
29-
], MyClass.prototype, "doSomething", Object.getOwnPropertyDescriptor(MyClass.prototype, "doSomething")));
23+
__decorate([
24+
decorator,
25+
__metadata('design:type', Function),
26+
__metadata('design:paramtypes', []),
27+
__metadata('design:returntype', void 0)
28+
], MyClass.prototype, "doSomething", null);
3029
return MyClass;
3130
})();

tests/baselines/reference/decoratorMetadataOnInferredType.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ var B = (function () {
3333
__decorate([
3434
decorator,
3535
__metadata('design:type', Object)
36-
], B.prototype, "x");
36+
], B.prototype, "x", void 0);
3737
return B;
3838
})();
3939
exports.B = B;

tests/baselines/reference/decoratorMetadataWithConstructorType.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ var B = (function () {
3333
__decorate([
3434
decorator,
3535
__metadata('design:type', A)
36-
], B.prototype, "x");
36+
], B.prototype, "x", void 0);
3737
return B;
3838
})();
3939
exports.B = B;

tests/baselines/reference/decoratorOnClass1.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@ class C {
77

88
//// [decoratorOnClass1.js]
99
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
10-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
11-
switch (arguments.length) {
12-
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
13-
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
14-
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
15-
}
10+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
11+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
12+
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;
13+
return c > 3 && r && Object.defineProperty(target, key, r), r;
1614
};
1715
var C = (function () {
1816
function C() {

0 commit comments

Comments
 (0)