Skip to content

Commit 7610048

Browse files
committed
Allow decorators in ES3
1 parent bed25dd commit 7610048

4 files changed

Lines changed: 32 additions & 51 deletions

File tree

src/compiler/checker.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8322,6 +8322,12 @@ namespace ts {
83228322
case SyntaxKind.SetAccessor:
83238323
// A method or accessor declaration decorator will have two or three arguments (see
83248324
// `PropertyDecorator` and `MethodDecorator` in core.d.ts)
8325+
8326+
// If we are emitting decorators for ES3, we will only pass two arguments.
8327+
if (languageVersion === ScriptTarget.ES3) {
8328+
return 2;
8329+
}
8330+
83258331
// If the method decorator signature only accepts a target and a key, we will only
83268332
// type check those arguments.
83278333
return signature.parameters.length >= 3 ? 3 : 2;
@@ -14627,9 +14633,6 @@ namespace ts {
1462714633
if (!nodeCanBeDecorated(node)) {
1462814634
return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_not_valid_here);
1462914635
}
14630-
else if (languageVersion < ScriptTarget.ES5) {
14631-
return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher);
14632-
}
1463314636
else if (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) {
1463414637
let accessors = getAllAccessorDeclarations((<ClassDeclaration>node.parent).members, <AccessorDeclaration>node);
1463514638
if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) {

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ namespace ts {
161161
Import_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_import_Asterisk_as_ns_from_mod_import_a_from_mod_or_import_d_from_mod_instead: { code: 1202, category: DiagnosticCategory.Error, key: "Import assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'import * as ns from \"mod\"', 'import {a} from \"mod\"' or 'import d from \"mod\"' instead." },
162162
Export_assignment_cannot_be_used_when_targeting_ECMAScript_6_or_higher_Consider_using_export_default_instead: { code: 1203, category: DiagnosticCategory.Error, key: "Export assignment cannot be used when targeting ECMAScript 6 or higher. Consider using 'export default' instead." },
163163
Cannot_compile_modules_into_commonjs_amd_system_or_umd_when_targeting_ES6_or_higher: { code: 1204, category: DiagnosticCategory.Error, key: "Cannot compile modules into 'commonjs', 'amd', 'system' or 'umd' when targeting 'ES6' or higher." },
164-
Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher: { code: 1205, category: DiagnosticCategory.Error, key: "Decorators are only available when targeting ECMAScript 5 and higher." },
165164
Decorators_are_not_valid_here: { code: 1206, category: DiagnosticCategory.Error, key: "Decorators are not valid here." },
166165
Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name: { code: 1207, category: DiagnosticCategory.Error, key: "Decorators cannot be applied to multiple get/set accessors of the same name." },
167166
Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided: { code: 1208, category: DiagnosticCategory.Error, key: "Cannot compile namespaces when the '--isolatedModules' flag is provided." },

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
@@ -27,12 +27,10 @@ var __extends = (this && this.__extends) || function (d, b) {
2727
// emit output for the __decorate helper function
2828
const decorateHelper = `
2929
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
30-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
31-
switch (arguments.length) {
32-
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
33-
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
34-
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
35-
}
30+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
31+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
32+
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;
33+
return c > 3 && r && Object.defineProperty(target, key, r), r;
3634
};`;
3735

3836
// emit output for the __metadata helper function
@@ -1382,7 +1380,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
13821380
//
13831381
// The emit for the decorated computed property decorator is:
13841382
//
1385-
// Object.defineProperty(C.prototype, _a, __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a)));
1383+
// __decorate([dec], C.prototype, _a, Object.getOwnPropertyDescriptor(C.prototype, _a));
13861384
//
13871385
if (nodeIsDecorated(node.parent)) {
13881386
if (!computedPropertyNamesToGeneratedNames) {
@@ -4410,7 +4408,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
44104408
//
44114409
// let C = class {
44124410
// };
4413-
// Object.defineProperty(C, "name", { value: "C", configurable: true });
44144411
// C = __decorate([dec], C);
44154412
//
44164413
// * For an exported class declaration:
@@ -4422,7 +4419,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
44224419
//
44234420
// export let C = class {
44244421
// };
4425-
// Object.defineProperty(C, "name", { value: "C", configurable: true });
44264422
// C = __decorate([dec], C);
44274423
//
44284424
// * For a default export of a class declaration with a name:
@@ -4434,7 +4430,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
44344430
//
44354431
// let C = class {
44364432
// }
4437-
// Object.defineProperty(C, "name", { value: "C", configurable: true });
44384433
// C = __decorate([dec], C);
44394434
// export default C;
44404435
//
@@ -4760,21 +4755,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
47604755
//
47614756
// The emit for a method is:
47624757
//
4763-
// Object.defineProperty(C.prototype, "method",
4764-
// __decorate([
4765-
// dec,
4766-
// __param(0, dec2),
4767-
// __metadata("design:type", Function),
4768-
// __metadata("design:paramtypes", [Object]),
4769-
// __metadata("design:returntype", void 0)
4770-
// ], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method")));
4758+
// __decorate([
4759+
// dec,
4760+
// __param(0, dec2),
4761+
// __metadata("design:type", Function),
4762+
// __metadata("design:paramtypes", [Object]),
4763+
// __metadata("design:returntype", void 0)
4764+
// ], C.prototype, "method", undefined);
47714765
//
47724766
// The emit for an accessor is:
47734767
//
4774-
// Object.defineProperty(C.prototype, "accessor",
4775-
// __decorate([
4776-
// dec
4777-
// ], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor")));
4768+
// __decorate([
4769+
// dec
4770+
// ], C.prototype, "accessor", undefined);
47784771
//
47794772
// The emit for a property is:
47804773
//
@@ -4785,18 +4778,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
47854778

47864779
writeLine();
47874780
emitStart(member);
4788-
if (member.kind !== SyntaxKind.PropertyDeclaration) {
4789-
write("Object.defineProperty(");
4790-
emitStart(member.name);
4791-
emitClassMemberPrefix(node, member);
4792-
write(", ");
4793-
emitExpressionForPropertyName(member.name);
4794-
emitEnd(member.name);
4795-
write(",");
4796-
increaseIndent();
4797-
writeLine();
4798-
}
4799-
48004781
write("__decorate([");
48014782
increaseIndent();
48024783
writeLine();
@@ -4820,15 +4801,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
48204801
emitExpressionForPropertyName(member.name);
48214802
emitEnd(member.name);
48224803

4823-
if (member.kind !== SyntaxKind.PropertyDeclaration) {
4824-
write(", Object.getOwnPropertyDescriptor(");
4825-
emitStart(member.name);
4826-
emitClassMemberPrefix(node, member);
4827-
write(", ");
4828-
emitExpressionForPropertyName(member.name);
4829-
emitEnd(member.name);
4830-
write("))");
4831-
decreaseIndent();
4804+
if (languageVersion > ScriptTarget.ES3) {
4805+
if (member.kind !== SyntaxKind.PropertyDeclaration) {
4806+
// We emit `null` here to indicate to `__decorate` that it can invoke `Object.getOwnPropertyDescriptor` directly.
4807+
// We have this extra argument here so that we can inject an explicit property descriptor at a later date.
4808+
write(", null");
4809+
}
4810+
else {
4811+
// We emit `void 0` here to indicate to `__decorate` that it can invoke `Object.defineProperty` directly, but that it
4812+
// should not invoke `Object.getOwnPropertyDescriptor`.
4813+
write(", void 0");
4814+
}
48324815
}
48334816

48344817
write(");");

0 commit comments

Comments
 (0)